#include <libpspp/misc.h>
#include <libpspp/str.h>
#include <libpspp/taint.h>
+#include <libpspp/i18n.h>
+#include "minmax.h"
#include "xalloc.h"
struct dataset {
proc_state;
casenumber cases_written; /* Cases output so far. */
bool ok; /* Error status. */
+
+ void (*callback) (void *); /* Callback for when the dataset changes */
+ void *cb_data;
+
}; /* struct dataset */
static void add_filter_trns (struct dataset *ds);
static void update_last_proc_invocation (struct dataset *ds);
+
+static void
+dataset_set_unsaved (const struct dataset *ds)
+{
+ if (ds->callback) ds->callback (ds->cb_data);
+}
+
\f
/* Public functions. */
+void
+dataset_set_callback (struct dataset *ds, void (*cb) (void *), void *cb_data)
+{
+ ds->callback = cb;
+ ds->cb_data = cb_data;
+}
+
+
/* Returns the last time the data was read. */
time_t
time_of_last_procedure (struct dataset *ds)
{
struct dictionary *pd = ds->permanent_dict;
size_t compacted_value_cnt = dict_count_values (pd, 1u << DC_SCRATCH);
- bool should_compact = compacted_value_cnt < dict_get_next_value_idx (pd);
- ds->compactor = (should_compact
- ? case_map_to_compact_dict (pd, 1u << DC_SCRATCH)
- : NULL);
- ds->sink = autopaging_writer_create (compacted_value_cnt);
+ if (compacted_value_cnt < dict_get_next_value_idx (pd))
+ {
+ struct caseproto *compacted_proto;
+ compacted_proto = dict_get_compacted_proto (pd, 1u << DC_SCRATCH);
+ ds->compactor = case_map_to_compact_dict (pd, 1u << DC_SCRATCH);
+ ds->sink = autopaging_writer_create (compacted_proto);
+ caseproto_unref (compacted_proto);
+ }
+ else
+ {
+ ds->compactor = NULL;
+ ds->sink = autopaging_writer_create (dict_get_proto (pd));
+ }
}
else
{
/* FIXME: use taint in dataset in place of `ok'? */
/* FIXME: for trivial cases we can just return a clone of
ds->source? */
- return casereader_create_sequential (NULL,
- dict_get_next_value_idx (ds->dict),
+ return casereader_create_sequential (NULL, dict_get_proto (ds->dict),
CASENUMBER_MAX,
&proc_casereader_class, ds);
}
c = casereader_read (ds->source);
if (c == NULL)
return NULL;
- c = case_unshare_and_resize (c, dict_get_next_value_idx (ds->dict));
+ c = case_unshare_and_resize (c, dict_get_proto (ds->dict));
caseinit_init_vars (ds->caseinit, c);
/* Execute permanent transformations. */
assert (ds->proc_state == PROC_CLOSED);
ds->proc_state = PROC_COMMITTED;
+ dataset_set_unsaved (ds);
+
/* Free memory for lagged cases. */
while (!deque_is_empty (&ds->lag))
case_unref (ds->lag_cases[deque_pop_back (&ds->lag)]);
return ok;
}
\f
+
+static void
+dict_callback (struct dictionary *d UNUSED, void *ds_)
+{
+ struct dataset *ds = ds_;
+ dataset_set_unsaved (ds);
+}
+
/* Initializes procedure handling. */
struct dataset *
create_dataset (void)
{
struct dataset *ds = xzalloc (sizeof(*ds));
ds->dict = dict_create ();
+
+ dict_set_change_callback (ds->dict, dict_callback, ds);
+
+ dict_set_encoding (ds->dict, get_default_encoding ());
+
ds->caseinit = caseinit_create ();
proc_cancel_all_transformations (ds);
return ds;
dict_destroy (ds->dict);
ds->dict = dict;
+ dict_set_change_callback (ds->dict, dict_callback, ds);
proc_set_active_file_data (ds, source);
}