X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fdictionary.c;h=a5a36527c3d2803d48a686f02e82070c078de42c;hb=72147c12357446b304264b6944b8a1d92c45f53c;hp=d344e7516ac17b00da06567369d47b519e1254da;hpb=480a0746507ce73d26f528b56dc3ed80195096e0;p=pspp-builds.git diff --git a/src/data/dictionary.c b/src/data/dictionary.c index d344e751..a5a36527 100644 --- a/src/data/dictionary.c +++ b/src/data/dictionary.c @@ -61,14 +61,33 @@ struct dictionary char *documents; /* Documents, as a string. */ struct vector **vector; /* Vectors of variables. */ size_t vector_cnt; /* Number of vectors. */ + const struct dict_callbacks *callbacks; /* Callbacks on dictionary + modification */ + void *cb_data ; /* Data passed to callbacks */ }; + +/* Associate CALLBACKS with DICT. Callbacks will be invoked whenever + the dictionary or any of the variables it contains are modified. + Each callback will get passed CALLBACK_DATA. + Any callback may be NULL, in which case it'll be ignored. +*/ +void +dict_set_callbacks (struct dictionary *dict, + const struct dict_callbacks *callbacks, + void *callback_data) +{ + dict->callbacks = callbacks; + dict->cb_data = callback_data; +} + + /* Creates and returns a new dictionary. */ struct dictionary * -dict_create (void) +dict_create (void) { - struct dictionary *d = xmalloc (sizeof *d); - + struct dictionary *d = xzalloc (sizeof *d); + d->var = NULL; d->var_cnt = d->var_cap = 0; d->name_tab = hsh_create (8, compare_vars_by_name, hash_var_by_name, @@ -90,7 +109,7 @@ dict_create (void) /* Creates and returns a (deep) copy of an existing dictionary. */ struct dictionary * -dict_clone (const struct dictionary *s) +dict_clone (const struct dictionary *s) { struct dictionary *d; size_t i; @@ -99,7 +118,7 @@ dict_clone (const struct dictionary *s) d = dict_create (); - for (i = 0; i < s->var_cnt; i++) + for (i = 0; i < s->var_cnt; i++) { struct variable *sv = s->var[i]; struct variable *dv = dict_clone_var_assert (d, sv, var_get_name (sv)); @@ -109,17 +128,17 @@ dict_clone (const struct dictionary *s) d->next_value_idx = s->next_value_idx; d->split_cnt = s->split_cnt; - if (d->split_cnt > 0) + if (d->split_cnt > 0) { d->split = xnmalloc (d->split_cnt, sizeof *d->split); - for (i = 0; i < d->split_cnt; i++) + for (i = 0; i < d->split_cnt; i++) d->split[i] = dict_lookup_var_assert (d, var_get_name (s->split[i])); } - if (s->weight != NULL) + if (s->weight != NULL) d->weight = dict_lookup_var_assert (d, var_get_name (s->weight)); - if (s->filter != NULL) + if (s->filter != NULL) d->filter = dict_lookup_var_assert (d, var_get_name (s->filter)); d->case_limit = s->case_limit; @@ -137,7 +156,7 @@ dict_clone (const struct dictionary *s) /* Clears the contents from a dictionary without destroying the dictionary itself. */ void -dict_clear (struct dictionary *d) +dict_clear (struct dictionary *d) { /* FIXME? Should we really clear case_limit, label, documents? Others are necessarily cleared by deleting all the variables.*/ @@ -148,7 +167,7 @@ dict_clear (struct dictionary *d) for (i = 0; i < d->var_cnt; i++) { var_clear_vardict (d->var[i]); - var_destroy (d->var[i]); + var_destroy (d->var[i]); } free (d->var); d->var = NULL; @@ -171,12 +190,12 @@ dict_clear (struct dictionary *d) /* Destroys the aux data for every variable in D, by calling var_clear_aux() for each variable. */ void -dict_clear_aux (struct dictionary *d) +dict_clear_aux (struct dictionary *d) { int i; - + assert (d != NULL); - + for (i = 0; i < d->var_cnt; i++) var_clear_aux (d->var[i]); } @@ -185,7 +204,7 @@ dict_clear_aux (struct dictionary *d) void dict_destroy (struct dictionary *d) { - if (d != NULL) + if (d != NULL) { dict_clear (d); hsh_destroy (d->name_tab); @@ -195,7 +214,7 @@ dict_destroy (struct dictionary *d) /* Returns the number of variables in D. */ size_t -dict_get_var_cnt (const struct dictionary *d) +dict_get_var_cnt (const struct dictionary *d) { assert (d != NULL); @@ -206,7 +225,7 @@ dict_get_var_cnt (const struct dictionary *d) must be between 0 and the count returned by dict_get_var_cnt(), exclusive. */ struct variable * -dict_get_var (const struct dictionary *d, size_t idx) +dict_get_var (const struct dictionary *d, size_t idx) { assert (d != NULL); assert (idx < d->var_cnt); @@ -225,14 +244,14 @@ dict_get_vars (const struct dictionary *d, struct variable ***vars, { size_t count; size_t i; - + assert (d != NULL); assert (vars != NULL); assert (cnt != NULL); assert ((exclude_classes & ~((1u << DC_ORDINARY) | (1u << DC_SYSTEM) | (1u << DC_SCRATCH))) == 0); - + count = 0; for (i = 0; i < d->var_cnt; i++) { @@ -240,36 +259,40 @@ dict_get_vars (const struct dictionary *d, struct variable ***vars, if (!(exclude_classes & (1u << class))) count++; } - + *vars = xnmalloc (count, sizeof **vars); *cnt = 0; - for (i = 0; i < d->var_cnt; i++) + for (i = 0; i < d->var_cnt; i++) { enum dict_class class = dict_class_from_id (var_get_name (d->var[i])); if (!(exclude_classes & (1u << class))) - (*vars)[(*cnt)++] = d->var[i]; + (*vars)[(*cnt)++] = d->var[i]; } assert (*cnt == count); } static struct variable * -add_var (struct dictionary *d, struct variable *v) +add_var (struct dictionary *d, struct variable *v) { /* Add dictionary info to variable. */ struct vardict_info vdi; vdi.case_index = d->next_value_idx; vdi.dict_index = d->var_cnt; + vdi.dict = d; var_set_vardict (v, &vdi); /* Update dictionary. */ - if (d->var_cnt >= d->var_cap) + if (d->var_cnt >= d->var_cap) { - d->var_cap = 8 + 2 * d->var_cap; + d->var_cap = 8 + 2 * d->var_cap; d->var = xnrealloc (d->var, d->var_cap, sizeof *d->var); } d->var[d->var_cnt++] = v; hsh_force_insert (d->name_tab, v); + if ( d->callbacks && d->callbacks->var_added ) + d->callbacks->var_added (d, d->next_value_idx, d->cb_data); + d->next_value_idx += var_get_value_cnt (v); return v; @@ -350,12 +373,12 @@ dict_lookup_var_assert (const struct dictionary *d, const char *name) bool dict_contains_var (const struct dictionary *d, const struct variable *v) { - if (var_has_vardict (v)) + if (var_has_vardict (v)) { const struct vardict_info *vdi = var_get_vardict (v); return (vdi->dict_index >= 0 && vdi->dict_index < d->var_cnt - && d->var[vdi->dict_index] == v); + && d->var[vdi->dict_index] == v); } else return false; @@ -378,7 +401,7 @@ set_var_dict_index (struct variable *v, int dict_index) { struct vardict_info vdi = *var_get_vardict (v); vdi.dict_index = dict_index; - var_set_vardict (v, &vdi); + var_set_vardict (v, &vdi); } /* Sets the case_index in V's vardict to DICT_INDEX. */ @@ -387,16 +410,16 @@ set_var_case_index (struct variable *v, int case_index) { struct vardict_info vdi = *var_get_vardict (v); vdi.case_index = case_index; - var_set_vardict (v, &vdi); + var_set_vardict (v, &vdi); } /* Re-sets the dict_index in the dictionary variables with indexes from FROM to TO (exclusive). */ static void -reindex_vars (struct dictionary *d, size_t from, size_t to) +reindex_vars (struct dictionary *d, size_t from, size_t to) { size_t i; - + for (i = from; i < to; i++) set_var_dict_index (d->var[i], i); } @@ -442,9 +465,13 @@ dict_delete_var (struct dictionary *d, struct variable *v) /* Update name hash. */ hsh_force_delete (d->name_tab, v); + /* Free memory. */ var_clear_vardict (v); var_destroy (v); + + if (d->callbacks && d->callbacks->var_deleted ) + d->callbacks->var_deleted (d, dict_index, d->cb_data); } /* Deletes the COUNT variables listed in VARS from D. This is @@ -559,9 +586,9 @@ rename_var (struct dictionary *d, struct variable *v, const char *new_name) /* Changes the name of V in D to name NEW_NAME. Assert-fails if a variable named NEW_NAME is already in D, except that NEW_NAME may be the same as V's existing name. */ -void +void dict_rename_var (struct dictionary *d, struct variable *v, - const char *new_name) + const char *new_name) { assert (!strcasecmp (var_get_name (v), new_name) || dict_lookup_var (d, new_name) == NULL); @@ -572,6 +599,9 @@ dict_rename_var (struct dictionary *d, struct variable *v, if (get_algorithm () == ENHANCED) var_clear_short_name (v); + + if ( d->callbacks && d->callbacks->var_changed ) + d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data); } /* Renames COUNT variables specified in VARS to the names given @@ -1237,3 +1267,21 @@ dict_assign_short_names (struct dictionary *d) /* Get rid of hash table. */ hsh_destroy (short_names); } + + +/* Called from variable.c to notify the dictionary that some property of + the variable has changed */ +void +dict_var_changed (const struct variable *v) +{ + if ( var_has_vardict (v)) + { + const struct vardict_info *vdi = var_get_vardict (v); + struct dictionary *d; + + d = vdi->dict; + + if ( d->callbacks && d->callbacks->var_changed ) + d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data); + } +}