X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fprocedure.c;h=b762214d10e20a33d6bbdf89ac52253a67589453;hb=b5c82cc9aabe7e641011130240ae1b2e84348e23;hp=91e185a45a43f3d78802338d6b26536f0a9dc6b0;hpb=8953baa61127d6d3b91f763663ea647bf3e4e793;p=pspp-builds.git diff --git a/src/data/procedure.c b/src/data/procedure.c index 91e185a4..b762214d 100644 --- a/src/data/procedure.c +++ b/src/data/procedure.c @@ -36,7 +36,9 @@ #include #include #include +#include +#include "minmax.h" #include "xalloc.h" struct dataset { @@ -92,6 +94,10 @@ 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 */ @@ -99,9 +105,24 @@ static void add_case_limit_trns (struct dataset *ds); 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); +} + /* 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) @@ -166,11 +187,19 @@ proc_open (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 { @@ -188,8 +217,7 @@ proc_open (struct dataset *ds) /* 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); } @@ -225,7 +253,7 @@ proc_casereader_read (struct casereader *reader UNUSED, void *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. */ @@ -293,6 +321,8 @@ proc_commit (struct dataset *ds) 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)]); @@ -510,12 +540,25 @@ proc_cancel_all_transformations (struct dataset *ds) return ok; } + +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; @@ -585,6 +628,7 @@ proc_set_active_file (struct dataset *ds, dict_destroy (ds->dict); ds->dict = dict; + dict_set_change_callback (ds->dict, dict_callback, ds); proc_set_active_file_data (ds, source); }