struct caseproto *proto; /* Prototype for dictionary cases
(updated lazily). */
struct hmap name_map; /* Variable index by name. */
- int next_value_idx; /* Index of next `union value' to allocate. */
const struct variable **split; /* SPLIT FILE vars. */
size_t n_splits; /* SPLIT FILE count. */
enum split_type split_type;
/* Creates and returns a (deep) copy of an existing
dictionary.
- The new dictionary's case indexes are copied from the old
- dictionary. If the new dictionary won't be used to access
- cases produced with the old dictionary, then the new
- dictionary's case indexes should be compacted with
- dict_compact_values to save space.
-
Callbacks are not cloned. */
struct dictionary *
dict_clone (const struct dictionary *s)
var_get_vardict (dv)->case_index = var_get_vardict (sv)->case_index;
}
- d->next_value_idx = s->next_value_idx;
-
d->n_splits = s->n_splits;
if (d->n_splits > 0)
{
dict_delete_var__ (struct dictionary *d, struct variable *v, bool skip_callbacks)
{
int dict_index = var_get_dict_index (v);
- const int case_index = var_get_case_index (v);
assert (dict_contains_var (d, v));
if (! skip_callbacks)
{
if (d->changed) d->changed (d, d->changed_data);
- if (d->callbacks && d->callbacks->var_deleted)
- d->callbacks->var_deleted (d, v, dict_index, case_index, d->cb_data);
+ if (d->callbacks && d->callbacks->vars_deleted)
+ d->callbacks->vars_deleted (d, dict_index, 1, d->cb_data);
}
invalidate_proto (d);
dict_delete_var (struct dictionary *d, struct variable *v)
{
dict_delete_var__ (d, v, false);
+ dict_compact_values (d);
}
while (count-- > 0)
dict_delete_var (d, *vars++);
+ dict_compact_values (d);
}
/* Deletes the COUNT variables in D starting at index IDX. This
struct delvar {
struct ll ll;
struct variable *var;
- int case_index;
};
struct ll_list list = LL_INITIALIZER (list);
dict_set_filter (d, NULL);
dv->var = v;
- dv->case_index = var_get_case_index (v);
ll_push_tail (&list, (struct ll *)dv);
}
the variables. The vardict is not valid at this point
anymore. That is the reason why we stored the
caseindex before reindexing. */
+ if (d->callbacks && d->callbacks->vars_deleted)
+ d->callbacks->vars_deleted (d, idx, count, d->cb_data);
for (size_t vi = idx; vi < idx + count; vi++)
{
struct delvar *dv = (struct delvar *) ll_pop_head (&list);
var_clear_vardict (dv->var);
- if (d->callbacks && d->callbacks->var_deleted)
- d->callbacks->var_deleted (d, dv->var, vi, dv->case_index, d->cb_data);
var_unref (dv->var);
free (dv);
}
+
+ dict_compact_values (d);
}
/* Deletes scratch variables from dictionary D. */
dict_delete_var (d, d->vars[i].var);
else
i++;
+
+ dict_compact_values (d);
}
\f
d->n_vars = d->allocated_vars = 0;
invalidate_proto (d);
hmap_clear (&d->name_map);
- d->next_value_idx = 0;
dict_set_split_vars__ (d, NULL, 0, SPLIT_NONE, skip_callbacks);
if (skip_callbacks)
{
struct vardict_info *vardict;
- assert (case_index >= d->next_value_idx);
-
/* Update dictionary. */
if (d->n_vars >= d->allocated_vars)
{
d->callbacks->var_added (d, var_get_dict_index (v), d->cb_data);
invalidate_proto (d);
- d->next_value_idx = case_index + 1;
return v;
}
static struct variable *
add_var (struct dictionary *d, struct variable *v)
{
- return add_var_with_case_index (d, v, d->next_value_idx);
+ return add_var_with_case_index (d, v, dict_get_n_vars (d));
}
/* Creates and returns a new variable in D with the given NAME
return d->proto;
}
-/* Returns the case index of the next value to be added to D.
- This value is the number of `union value's that need to be
- allocated to store a case for dictionary D. */
-int
-dict_get_next_value_idx (const struct dictionary *d)
-{
- return d->next_value_idx;
-}
-
-/* Returns the number of bytes needed to store a case for
- dictionary D. */
-size_t
-dict_get_case_size (const struct dictionary *d)
-{
- return sizeof (union value) * dict_get_next_value_idx (d);
-}
-
/* Reassigns values in dictionary D so that fragmentation is
eliminated. */
void
dict_compact_values (struct dictionary *d)
{
- size_t i;
-
- d->next_value_idx = 0;
- for (i = 0; i < d->n_vars; i++)
+ for (size_t i = 0; i < d->n_vars; i++)
{
struct variable *v = d->vars[i].var;
- set_var_case_index (v, d->next_value_idx++);
+ set_var_case_index (v, i);
}
invalidate_proto (d);
}
/* Returns the number of values occupied by the variables in
dictionary D. All variables are considered if EXCLUDE_CLASSES
is 0, or it may contain one or more of DC_ORDINARY, DC_SYSTEM,
- or DC_SCRATCH to exclude the corresponding type of variable.
-
- The return value may be less than the number of values in one
- of dictionary D's cases (as returned by
- dict_get_next_value_idx) even if E is 0, because there may be
- gaps in D's cases due to deleted variables. */
+ or DC_SCRATCH to exclude the corresponding type of variable. */
size_t
dict_count_values (const struct dictionary *d, unsigned int exclude_classes)
{
return n;
}
-/* Returns the case prototype that would result after deleting
- all variables from D that are not in one of the
- EXCLUDE_CLASSES and compacting the dictionary with
- dict_compact().
-
- The caller must unref the returned caseproto when it is no
- longer needed. */
-struct caseproto *
-dict_get_compacted_proto (const struct dictionary *d,
- unsigned int exclude_classes)
-{
- struct caseproto *proto;
- size_t i;
-
- assert (!(exclude_classes & ~DC_ALL));
-
- proto = caseproto_create ();
- for (i = 0; i < d->n_vars; i++)
- {
- struct variable *v = d->vars[i].var;
- if (!(exclude_classes & var_get_dict_class (v)))
- proto = caseproto_add_width (proto, var_get_width (v));
- }
- return proto;
-}
/* Returns the file label for D, or a null pointer if D is
unlabeled (see cmd_file_label()). */
const char *
}
-\f
-/* Dictionary used to contain "internal variables". */
-static struct dictionary *internal_dict;
-
-/* Create a variable of the specified WIDTH to be used for internal
- calculations only. The variable is assigned case index CASE_IDX. */
-struct variable *
-dict_create_internal_var (int case_idx, int width)
-{
- if (internal_dict == NULL)
- internal_dict = dict_create ("UTF-8");
-
- for (;;)
- {
- static int counter = INT_MAX / 2;
- struct variable *var;
- char name[64];
-
- if (++counter == INT_MAX)
- counter = INT_MAX / 2;
-
- sprintf (name, "$internal%d", counter);
- var = dict_create_var (internal_dict, name, width);
- if (var != NULL)
- {
- set_var_case_index (var, case_idx);
- return var;
- }
- }
-}
-
-/* Destroys VAR, which must have been created with
- dict_create_internal_var(). */
-void
-dict_destroy_internal_var (struct variable *var)
-{
- if (var != NULL)
- {
- dict_delete_var (internal_dict, var);
-
- /* Destroy internal_dict if it has no variables left, just so that
- valgrind --leak-check --show-reachable won't show internal_dict. */
- if (dict_get_n_vars (internal_dict) == 0)
- {
- dict_unref (internal_dict);
- internal_dict = NULL;
- }
- }
-}
\f
int
vardict_get_dict_index (const struct vardict_info *vardict)