1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2012, 2013, 2014,
3 2015, 2020 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #include "data/dictionary.h"
27 #include "data/attributes.h"
28 #include "data/case.h"
29 #include "data/identifier.h"
30 #include "data/mrset.h"
31 #include "data/settings.h"
32 #include "data/value-labels.h"
33 #include "data/vardict.h"
34 #include "data/variable.h"
35 #include "data/vector.h"
36 #include "libpspp/array.h"
37 #include "libpspp/assertion.h"
38 #include "libpspp/compiler.h"
39 #include "libpspp/hash-functions.h"
40 #include "libpspp/hmap.h"
41 #include "libpspp/i18n.h"
42 #include "libpspp/message.h"
43 #include "libpspp/misc.h"
44 #include "libpspp/pool.h"
45 #include "libpspp/str.h"
46 #include "libpspp/string-array.h"
47 #include "libpspp/ll.h"
49 #include "gl/intprops.h"
50 #include "gl/minmax.h"
51 #include "gl/xalloc.h"
52 #include "gl/xmemdup0.h"
55 #define _(msgid) gettext (msgid)
61 struct vardict_info *vars; /* Variables. */
62 size_t n_vars; /* Number of variables. */
63 size_t allocated_vars; /* Allocated space in 'vars'. */
64 struct caseproto *proto; /* Prototype for dictionary cases
66 struct hmap name_map; /* Variable index by name. */
67 int next_value_idx; /* Index of next `union value' to allocate. */
68 const struct variable **split; /* SPLIT FILE vars. */
69 size_t n_splits; /* SPLIT FILE count. */
70 enum split_type split_type;
71 struct variable *weight; /* WEIGHT variable. */
72 struct variable *filter; /* FILTER variable. */
73 casenumber case_limit; /* Current case limit (N command). */
74 char *label; /* File label. */
75 struct string_array documents; /* Documents. */
76 struct vector **vector; /* Vectors of variables. */
77 size_t n_vectors; /* Number of vectors. */
78 struct attrset attributes; /* Custom attributes. */
79 struct mrset **mrsets; /* Multiple response sets. */
80 size_t n_mrsets; /* Number of multiple response sets. */
82 /* Whether variable names must be valid identifiers. Normally, this is
83 true, but sometimes a dictionary is prepared for external use
84 (e.g. output to a CSV file) where names don't have to be valid. */
85 bool names_must_be_ids;
87 char *encoding; /* Character encoding of string data */
89 const struct dict_callbacks *callbacks; /* Callbacks on dictionary
91 void *cb_data ; /* Data passed to callbacks */
93 void (*changed) (struct dictionary *, void *); /* Generic change callback */
97 static void dict_unset_split_var (struct dictionary *, struct variable *, bool);
98 static void dict_unset_mrset_var (struct dictionary *, struct variable *);
100 /* Compares two double pointers to variables, which should point
101 to elements of a struct dictionary's `var' member array. */
103 compare_var_ptrs (const void *a_, const void *b_, const void *aux UNUSED)
105 struct variable *const *a = a_;
106 struct variable *const *b = b_;
108 return *a < *b ? -1 : *a > *b;
112 unindex_var (struct dictionary *d, struct vardict_info *vardict)
114 hmap_delete (&d->name_map, &vardict->name_node);
117 /* This function assumes that vardict->name_node.hash is valid, that is, that
118 its name has not changed since it was hashed (rename_var() updates this
119 hash along with the name itself). */
121 reindex_var (struct dictionary *d, struct vardict_info *vardict, bool skip_callbacks)
123 struct variable *old = (d->callbacks && d->callbacks->var_changed
124 ? var_clone (vardict->var)
127 struct variable *var = vardict->var;
128 var_set_vardict (var, vardict);
129 hmap_insert_fast (&d->name_map, &vardict->name_node,
130 vardict->name_node.hash);
132 if (! skip_callbacks)
134 if (d->changed) d->changed (d, d->changed_data);
137 d->callbacks->var_changed (d, var_get_dict_index (var), VAR_TRAIT_POSITION, old, d->cb_data);
143 /* Sets the case_index in V's vardict to CASE_INDEX. */
145 set_var_case_index (struct variable *v, int case_index)
147 var_get_vardict (v)->case_index = case_index;
150 /* Removes the dictionary variables with indexes from FROM to TO (exclusive)
153 unindex_vars (struct dictionary *d, size_t from, size_t to)
157 for (i = from; i < to; i++)
158 unindex_var (d, &d->vars[i]);
161 /* Re-sets the dict_index in the dictionary variables with
162 indexes from FROM to TO (exclusive). */
164 reindex_vars (struct dictionary *d, size_t from, size_t to, bool skip_callbacks)
168 for (i = from; i < to; i++)
169 reindex_var (d, &d->vars[i], skip_callbacks);
174 /* Returns the encoding for data in dictionary D. The return value is a
175 nonnull string that contains an IANA character set name. */
177 dict_get_encoding (const struct dictionary *d)
182 /* Checks whether UTF-8 string ID is an acceptable identifier in DICT's
183 encoding. Returns true if it is, otherwise an error message that the caller
185 char * WARN_UNUSED_RESULT
186 dict_id_is_valid__ (const struct dictionary *dict, const char *id)
188 if (!dict->names_must_be_ids)
190 return id_is_valid__ (id, dict->encoding);
194 error_to_bool (char *error)
205 /* Returns true if UTF-8 string ID is an acceptable identifier in DICT's
206 encoding, false otherwise. */
208 dict_id_is_valid (const struct dictionary *dict, const char *id)
210 return error_to_bool (dict_id_is_valid__ (dict, id));
214 dict_set_change_callback (struct dictionary *d,
215 void (*changed) (struct dictionary *, void*),
218 d->changed = changed;
219 d->changed_data = data;
222 /* Discards dictionary D's caseproto. (It will be regenerated
223 lazily, on demand.) */
225 invalidate_proto (struct dictionary *d)
227 caseproto_unref (d->proto);
231 /* Print a representation of dictionary D to stdout, for
232 debugging purposes. */
234 dict_dump (const struct dictionary *d)
237 for (i = 0 ; i < d->n_vars ; ++i)
239 const struct variable *v = d->vars[i].var;
240 printf ("Name: %s;\tdict_idx: %zu; case_idx: %zu\n",
242 var_get_dict_index (v),
243 var_get_case_index (v));
248 /* Associate CALLBACKS with DICT. Callbacks will be invoked whenever
249 the dictionary or any of the variables it contains are modified.
250 Each callback will get passed CALLBACK_DATA.
251 Any callback may be NULL, in which case it'll be ignored.
254 dict_set_callbacks (struct dictionary *dict,
255 const struct dict_callbacks *callbacks,
258 dict->callbacks = callbacks;
259 dict->cb_data = callback_data;
262 /* Shallow copy the callbacks from SRC to DEST */
264 dict_copy_callbacks (struct dictionary *dest,
265 const struct dictionary *src)
267 dest->callbacks = src->callbacks;
268 dest->cb_data = src->cb_data;
271 /* Creates and returns a new dictionary with the specified ENCODING. */
273 dict_create (const char *encoding)
275 struct dictionary *d = xmalloc (sizeof *d);
277 *d = (struct dictionary) {
278 .encoding = xstrdup (encoding),
279 .names_must_be_ids = true,
280 .name_map = HMAP_INITIALIZER (d->name_map),
281 .attributes = ATTRSET_INITIALIZER (d->attributes),
282 .split_type = SPLIT_NONE,
289 /* Creates and returns a (deep) copy of an existing
292 The new dictionary's case indexes are copied from the old
293 dictionary. If the new dictionary won't be used to access
294 cases produced with the old dictionary, then the new
295 dictionary's case indexes should be compacted with
296 dict_compact_values to save space.
298 Callbacks are not cloned. */
300 dict_clone (const struct dictionary *s)
302 struct dictionary *d;
305 d = dict_create (s->encoding);
306 dict_set_names_must_be_ids (d, dict_get_names_must_be_ids (s));
308 for (i = 0; i < s->n_vars; i++)
310 struct variable *sv = s->vars[i].var;
311 struct variable *dv = dict_clone_var_assert (d, sv);
314 for (i = 0; i < var_get_n_short_names (sv); i++)
315 var_set_short_name (dv, i, var_get_short_name (sv, i));
317 var_get_vardict (dv)->case_index = var_get_vardict (sv)->case_index;
320 d->next_value_idx = s->next_value_idx;
322 d->n_splits = s->n_splits;
325 d->split = xnmalloc (d->n_splits, sizeof *d->split);
326 for (i = 0; i < d->n_splits; i++)
327 d->split[i] = dict_lookup_var_assert (d, var_get_name (s->split[i]));
329 d->split_type = s->split_type;
331 if (s->weight != NULL)
332 dict_set_weight (d, dict_lookup_var_assert (d, var_get_name (s->weight)));
334 if (s->filter != NULL)
335 dict_set_filter (d, dict_lookup_var_assert (d, var_get_name (s->filter)));
337 d->case_limit = s->case_limit;
338 dict_set_label (d, dict_get_label (s));
339 dict_set_documents (d, dict_get_documents (s));
341 d->n_vectors = s->n_vectors;
342 d->vector = xnmalloc (d->n_vectors, sizeof *d->vector);
343 for (i = 0; i < s->n_vectors; i++)
344 d->vector[i] = vector_clone (s->vector[i], s, d);
346 dict_set_attributes (d, dict_get_attributes (s));
348 for (i = 0; i < s->n_mrsets; i++)
350 const struct mrset *old = s->mrsets[i];
354 /* Clone old mrset, then replace vars from D by vars from S. */
355 new = mrset_clone (old);
356 for (j = 0; j < new->n_vars; j++)
357 new->vars[j] = dict_lookup_var_assert (d, var_get_name (new->vars[j]));
359 dict_add_mrset (d, new);
367 /* Returns the SPLIT FILE vars (see cmd_split_file()). Call
368 dict_get_n_splits() to determine how many SPLIT FILE vars
369 there are. Returns a null pointer if and only if there are no
371 const struct variable *const *
372 dict_get_split_vars (const struct dictionary *d)
377 /* Returns the number of SPLIT FILE vars. */
379 dict_get_n_splits (const struct dictionary *d)
384 /* Removes variable V, which must be in D, from D's set of split
387 dict_unset_split_var (struct dictionary *d, struct variable *v, bool skip_callbacks)
391 assert (dict_contains_var (d, v));
393 orig_count = d->n_splits;
394 d->n_splits = remove_equal (d->split, d->n_splits, sizeof *d->split,
395 &v, compare_var_ptrs, NULL);
396 if (orig_count != d->n_splits && !skip_callbacks)
398 if (d->changed) d->changed (d, d->changed_data);
399 /* We changed the set of split variables so invoke the
401 if (d->callbacks && d->callbacks->split_changed)
402 d->callbacks->split_changed (d, d->cb_data);
407 /* Sets N split vars SPLIT in dictionary D. N is silently capped to a maximum
410 dict_set_split_vars__ (struct dictionary *d,
411 struct variable *const *split, size_t n,
412 enum split_type type, bool skip_callbacks)
416 assert (n == 0 || split != NULL);
419 d->split_type = type == SPLIT_NONE ? SPLIT_LAYERED : type;
422 d->split = xnrealloc (d->split, n, sizeof *d->split) ;
423 memcpy (d->split, split, n * sizeof *d->split);
433 if (d->changed) d->changed (d, d->changed_data);
434 if (d->callbacks && d->callbacks->split_changed)
435 d->callbacks->split_changed (d, d->cb_data);
440 dict_get_split_type (const struct dictionary *d)
442 return d->split_type;
445 /* Sets N split vars SPLIT in dictionary D. */
447 dict_set_split_vars (struct dictionary *d,
448 struct variable *const *split, size_t n,
449 enum split_type type)
451 dict_set_split_vars__ (d, split, n, type, false);
455 dict_clear_split_vars (struct dictionary *d)
457 dict_set_split_vars (d, NULL, 0, SPLIT_NONE);
461 /* Deletes variable V from dictionary D and frees V.
463 This is a very bad idea if there might be any pointers to V
464 from outside D. In general, no variable in the active dataset's
465 dictionary should be deleted when any transformations are
466 active on the dictionary's dataset, because those
467 transformations might reference the deleted variable. The
468 safest time to delete a variable is just after a procedure has
469 been executed, as done by DELETE VARIABLES.
471 Pointers to V within D are not a problem, because
472 dict_delete_var() knows to remove V from split variables,
473 weights, filters, etc. */
475 dict_delete_var__ (struct dictionary *d, struct variable *v, bool skip_callbacks)
477 int dict_index = var_get_dict_index (v);
478 const int case_index = var_get_case_index (v);
480 assert (dict_contains_var (d, v));
482 dict_unset_split_var (d, v, skip_callbacks);
483 dict_unset_mrset_var (d, v);
486 dict_set_weight (d, NULL);
489 dict_set_filter (d, NULL);
491 dict_clear_vectors (d);
493 /* Remove V from var array. */
494 unindex_vars (d, dict_index, d->n_vars);
495 remove_element (d->vars, d->n_vars, sizeof *d->vars, dict_index);
498 /* Update dict_index for each affected variable. */
499 reindex_vars (d, dict_index, d->n_vars, skip_callbacks);
502 var_clear_vardict (v);
504 if (! skip_callbacks)
506 if (d->changed) d->changed (d, d->changed_data);
507 if (d->callbacks && d->callbacks->var_deleted)
508 d->callbacks->var_deleted (d, v, dict_index, case_index, d->cb_data);
511 invalidate_proto (d);
515 /* Deletes variable V from dictionary D and frees V.
517 This is a very bad idea if there might be any pointers to V
518 from outside D. In general, no variable in the active dataset's
519 dictionary should be deleted when any transformations are
520 active on the dictionary's dataset, because those
521 transformations might reference the deleted variable. The
522 safest time to delete a variable is just after a procedure has
523 been executed, as done by DELETE VARIABLES.
525 Pointers to V within D are not a problem, because
526 dict_delete_var() knows to remove V from split variables,
527 weights, filters, etc. */
529 dict_delete_var (struct dictionary *d, struct variable *v)
531 dict_delete_var__ (d, v, false);
535 /* Deletes the COUNT variables listed in VARS from D. This is
536 unsafe; see the comment on dict_delete_var() for details. */
538 dict_delete_vars (struct dictionary *d,
539 struct variable *const *vars, size_t count)
541 /* FIXME: this can be done in O(count) time, but this algorithm
543 assert (count == 0 || vars != NULL);
546 dict_delete_var (d, *vars++);
549 /* Deletes the COUNT variables in D starting at index IDX. This
550 is unsafe; see the comment on dict_delete_var() for
551 details. Deleting consecutive vars will result in less callbacks
552 compared to iterating over dict_delete_var.
553 A simple while loop over dict_delete_var will
554 produce (d->n_vars - IDX) * COUNT variable changed callbacks
555 plus COUNT variable delete callbacks.
556 This here produces d->n_vars - IDX variable changed callbacks
557 plus COUNT variable delete callbacks. */
559 dict_delete_consecutive_vars (struct dictionary *d, size_t idx, size_t count)
561 assert (idx + count <= d->n_vars);
563 /* We need to store the variable and the corresponding case_index
564 for the delete callbacks later. We store them in a linked list.*/
567 struct variable *var;
570 struct ll_list list = LL_INITIALIZER (list);
572 for (size_t i = idx; i < idx + count; i++)
574 struct delvar *dv = xmalloc (sizeof (struct delvar));
576 struct variable *v = d->vars[i].var;
578 dict_unset_split_var (d, v, false);
579 dict_unset_mrset_var (d, v);
582 dict_set_weight (d, NULL);
585 dict_set_filter (d, NULL);
588 dv->case_index = var_get_case_index (v);
589 ll_push_tail (&list, (struct ll *)dv);
592 dict_clear_vectors (d);
594 /* Remove variables from var array. */
595 unindex_vars (d, idx, d->n_vars);
596 remove_range (d->vars, d->n_vars, sizeof *d->vars, idx, count);
599 /* Reindexing will result variable-changed callback */
600 reindex_vars (d, idx, d->n_vars, false);
602 invalidate_proto (d);
603 if (d->changed) d->changed (d, d->changed_data);
605 /* Now issue the variable delete callbacks and delete
606 the variables. The vardict is not valid at this point
607 anymore. That is the reason why we stored the
608 caseindex before reindexing. */
609 for (size_t vi = idx; vi < idx + count; vi++)
611 struct delvar *dv = (struct delvar *) ll_pop_head (&list);
612 var_clear_vardict (dv->var);
613 if (d->callbacks && d->callbacks->var_deleted)
614 d->callbacks->var_deleted (d, dv->var, vi, dv->case_index, d->cb_data);
620 /* Deletes scratch variables from dictionary D. */
622 dict_delete_scratch_vars (struct dictionary *d)
626 /* FIXME: this can be done in O(count) time, but this algorithm
628 for (i = 0; i < d->n_vars;)
629 if (var_get_dict_class (d->vars[i].var) == DC_SCRATCH)
630 dict_delete_var (d, d->vars[i].var);
637 /* Clears the contents from a dictionary without destroying the
638 dictionary itself. */
640 dict_clear__ (struct dictionary *d, bool skip_callbacks)
642 /* FIXME? Should we really clear case_limit, label, documents?
643 Others are necessarily cleared by deleting all the variables.*/
644 while (d->n_vars > 0)
646 dict_delete_var__ (d, d->vars[d->n_vars - 1].var, skip_callbacks);
651 d->n_vars = d->allocated_vars = 0;
652 invalidate_proto (d);
653 hmap_clear (&d->name_map);
654 d->next_value_idx = 0;
655 dict_set_split_vars__ (d, NULL, 0, SPLIT_NONE, skip_callbacks);
664 dict_set_weight (d, NULL);
665 dict_set_filter (d, NULL);
670 string_array_clear (&d->documents);
671 dict_clear_vectors (d);
672 attrset_clear (&d->attributes);
675 /* Clears the contents from a dictionary without destroying the
676 dictionary itself. */
678 dict_clear (struct dictionary *d)
680 dict_clear__ (d, false);
683 /* Clears a dictionary and destroys it. */
685 _dict_destroy (struct dictionary *d)
687 /* In general, we don't want callbacks occurring, if the dictionary
688 is being destroyed */
689 d->callbacks = NULL ;
691 dict_clear__ (d, true);
692 string_array_destroy (&d->documents);
693 hmap_destroy (&d->name_map);
694 attrset_destroy (&d->attributes);
695 dict_clear_mrsets (d);
701 dict_ref (struct dictionary *d)
708 dict_unref (struct dictionary *d)
713 assert (d->ref_cnt >= 0);
718 /* Returns the number of variables in D. */
720 dict_get_n_vars (const struct dictionary *d)
725 /* Returns the variable in D with dictionary index IDX, which
726 must be between 0 and the count returned by
727 dict_get_n_vars(), exclusive. */
729 dict_get_var (const struct dictionary *d, size_t idx)
731 assert (idx < d->n_vars);
733 return d->vars[idx].var;
736 /* Sets *VARS to an array of pointers to variables in D and *N
737 to the number of variables in *D. All variables are returned
738 except for those, if any, in the classes indicated by EXCLUDE.
739 (There is no point in putting DC_SYSTEM in EXCLUDE as
740 dictionaries never include system variables.) */
742 dict_get_vars (const struct dictionary *d, const struct variable ***vars,
743 size_t *n, enum dict_class exclude)
745 dict_get_vars_mutable (d, (struct variable ***) vars, n, exclude);
748 /* Sets *VARS to an array of pointers to variables in D and *N
749 to the number of variables in *D. All variables are returned
750 except for those, if any, in the classes indicated by EXCLUDE.
751 (There is no point in putting DC_SYSTEM in EXCLUDE as
752 dictionaries never include system variables.) */
754 dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
755 size_t *n, enum dict_class exclude)
760 assert (exclude == (exclude & DC_ALL));
763 for (i = 0; i < d->n_vars; i++)
765 enum dict_class class = var_get_dict_class (d->vars[i].var);
766 if (!(class & exclude))
770 *vars = xnmalloc (count, sizeof **vars);
772 for (i = 0; i < d->n_vars; i++)
774 enum dict_class class = var_get_dict_class (d->vars[i].var);
775 if (!(class & exclude))
776 (*vars)[(*n)++] = d->vars[i].var;
778 assert (*n == count);
781 static struct variable *
782 add_var_with_case_index (struct dictionary *d, struct variable *v,
785 struct vardict_info *vardict;
787 assert (case_index >= d->next_value_idx);
789 /* Update dictionary. */
790 if (d->n_vars >= d->allocated_vars)
794 d->vars = x2nrealloc (d->vars, &d->allocated_vars, sizeof *d->vars);
795 hmap_clear (&d->name_map);
796 for (i = 0; i < d->n_vars; i++)
798 var_set_vardict (d->vars[i].var, &d->vars[i]);
799 hmap_insert_fast (&d->name_map, &d->vars[i].name_node,
800 d->vars[i].name_node.hash);
804 vardict = &d->vars[d->n_vars++];
807 hmap_insert (&d->name_map, &vardict->name_node,
808 utf8_hash_case_string (var_get_name (v), 0));
809 vardict->case_index = case_index;
810 var_set_vardict (v, vardict);
812 if (d->changed) d->changed (d, d->changed_data);
813 if (d->callbacks && d->callbacks->var_added)
814 d->callbacks->var_added (d, var_get_dict_index (v), d->cb_data);
816 invalidate_proto (d);
817 d->next_value_idx = case_index + 1;
822 static struct variable *
823 add_var (struct dictionary *d, struct variable *v)
825 return add_var_with_case_index (d, v, d->next_value_idx);
828 /* Creates and returns a new variable in D with the given NAME
829 and WIDTH. Returns a null pointer if the given NAME would
830 duplicate that of an existing variable in the dictionary. */
832 dict_create_var (struct dictionary *d, const char *name, int width)
834 return (dict_lookup_var (d, name) == NULL
835 ? dict_create_var_assert (d, name, width)
839 /* Creates and returns a new variable in D with the given NAME
840 and WIDTH. Assert-fails if the given NAME would duplicate
841 that of an existing variable in the dictionary. */
843 dict_create_var_assert (struct dictionary *d, const char *name, int width)
845 assert (dict_lookup_var (d, name) == NULL);
846 return add_var (d, var_create (name, width));
849 /* Creates and returns a new variable in D, as a copy of existing variable
850 OLD_VAR, which need not be in D or in any dictionary. Returns a null
851 pointer if OLD_VAR's name would duplicate that of an existing variable in
854 dict_clone_var (struct dictionary *d, const struct variable *old_var)
856 return dict_clone_var_as (d, old_var, var_get_name (old_var));
859 /* Creates and returns a new variable in D, as a copy of existing variable
860 OLD_VAR, which need not be in D or in any dictionary. Assert-fails if
861 OLD_VAR's name would duplicate that of an existing variable in the
864 dict_clone_var_assert (struct dictionary *d, const struct variable *old_var)
866 return dict_clone_var_as_assert (d, old_var, var_get_name (old_var));
869 /* Creates and returns a new variable in D with name NAME, as a copy of
870 existing variable OLD_VAR, which need not be in D or in any dictionary.
871 Returns a null pointer if the given NAME would duplicate that of an existing
872 variable in the dictionary. */
874 dict_clone_var_as (struct dictionary *d, const struct variable *old_var,
877 return (dict_lookup_var (d, name) == NULL
878 ? dict_clone_var_as_assert (d, old_var, name)
882 /* Creates and returns a new variable in D with name NAME, as a copy of
883 existing variable OLD_VAR, which need not be in D or in any dictionary.
884 Assert-fails if the given NAME would duplicate that of an existing variable
885 in the dictionary. */
887 dict_clone_var_as_assert (struct dictionary *d, const struct variable *old_var,
890 struct variable *new_var = var_clone (old_var);
891 assert (dict_lookup_var (d, name) == NULL);
892 var_set_name (new_var, name);
893 return add_var (d, new_var);
897 dict_clone_var_in_place_assert (struct dictionary *d,
898 const struct variable *old_var)
900 assert (dict_lookup_var (d, var_get_name (old_var)) == NULL);
901 return add_var_with_case_index (d, var_clone (old_var),
902 var_get_case_index (old_var));
905 /* Returns the variable named NAME in D, or a null pointer if no
906 variable has that name. */
908 dict_lookup_var (const struct dictionary *d, const char *name)
910 struct vardict_info *vardict;
912 HMAP_FOR_EACH_WITH_HASH (vardict, struct vardict_info, name_node,
913 utf8_hash_case_string (name, 0), &d->name_map)
915 struct variable *var = vardict->var;
916 if (!utf8_strcasecmp (var_get_name (var), name))
923 /* Returns the variable named NAME in D. Assert-fails if no
924 variable has that name. */
926 dict_lookup_var_assert (const struct dictionary *d, const char *name)
928 struct variable *v = dict_lookup_var (d, name);
933 /* Returns true if variable V is in dictionary D,
936 dict_contains_var (const struct dictionary *d, const struct variable *v)
938 return (var_has_vardict (v)
939 && vardict_get_dictionary (var_get_vardict (v)) == d);
942 /* Moves V to 0-based position IDX in D. Other variables in D,
943 if any, retain their relative positions. Runs in time linear
944 in the distance moved. */
946 dict_reorder_var (struct dictionary *d, struct variable *v, size_t new_index)
948 size_t old_index = var_get_dict_index (v);
950 assert (new_index < d->n_vars);
952 unindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1);
953 move_element (d->vars, d->n_vars, sizeof *d->vars, old_index, new_index);
954 reindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1, false);
957 /* Reorders the variables in D, placing the COUNT variables
958 listed in ORDER in that order at the beginning of D. The
959 other variables in D, if any, retain their relative
962 dict_reorder_vars (struct dictionary *d,
963 struct variable *const *order, size_t count)
965 struct vardict_info *new_var;
968 assert (count == 0 || order != NULL);
969 assert (count <= d->n_vars);
971 new_var = xnmalloc (d->allocated_vars, sizeof *new_var);
973 /* Add variables in ORDER to new_var. */
974 for (i = 0; i < count; i++)
976 struct vardict_info *old_var;
978 assert (dict_contains_var (d, order[i]));
980 old_var = var_get_vardict (order[i]);
981 new_var[i] = *old_var;
982 old_var->dict = NULL;
985 /* Add remaining variables to new_var. */
986 for (i = 0; i < d->n_vars; i++)
987 if (d->vars[i].dict != NULL)
988 new_var[count++] = d->vars[i];
989 assert (count == d->n_vars);
991 /* Replace old vardicts by new ones. */
995 hmap_clear (&d->name_map);
996 reindex_vars (d, 0, d->n_vars, false);
999 /* Changes the name of variable V that is currently in a dictionary to
1002 rename_var (struct variable *v, const char *new_name)
1004 struct vardict_info *vardict = var_get_vardict (v);
1005 var_clear_vardict (v);
1006 var_set_name (v, new_name);
1007 vardict->name_node.hash = utf8_hash_case_string (new_name, 0);
1008 var_set_vardict (v, vardict);
1011 /* Tries to changes the name of V in D to name NEW_NAME. Returns true if
1012 successful, false if a variable (other than V) with the given name already
1015 dict_try_rename_var (struct dictionary *d, struct variable *v,
1016 const char *new_name)
1018 struct variable *conflict = dict_lookup_var (d, new_name);
1019 if (conflict && v != conflict)
1022 struct variable *old = var_clone (v);
1023 unindex_var (d, var_get_vardict (v));
1024 rename_var (v, new_name);
1025 reindex_var (d, var_get_vardict (v), false);
1027 if (settings_get_algorithm () == ENHANCED)
1028 var_clear_short_names (v);
1030 if (d->changed) d->changed (d, d->changed_data);
1031 if (d->callbacks && d->callbacks->var_changed)
1032 d->callbacks->var_changed (d, var_get_dict_index (v), VAR_TRAIT_NAME, old, d->cb_data);
1039 /* Changes the name of V in D to name NEW_NAME. Assert-fails if
1040 a variable named NEW_NAME is already in D, except that
1041 NEW_NAME may be the same as V's existing name. */
1043 dict_rename_var (struct dictionary *d, struct variable *v,
1044 const char *new_name)
1046 bool ok UNUSED = dict_try_rename_var (d, v, new_name);
1050 /* Renames COUNT variables specified in VARS to the names given
1051 in NEW_NAMES within dictionary D. If the renaming would
1052 result in a duplicate variable name, returns false and stores a
1053 name that would be duplicated into *ERR_NAME (if ERR_NAME is
1054 non-null). Otherwise, the renaming is successful, and true
1057 dict_rename_vars (struct dictionary *d,
1058 struct variable **vars, char **new_names, size_t count,
1065 assert (count == 0 || vars != NULL);
1066 assert (count == 0 || new_names != NULL);
1068 /* Save the names of the variables to be renamed. */
1069 pool = pool_create ();
1070 old_names = pool_nalloc (pool, count, sizeof *old_names);
1071 for (i = 0; i < count; i++)
1072 old_names[i] = pool_strdup (pool, var_get_name (vars[i]));
1074 /* Remove the variables to be renamed from the name hash,
1076 for (i = 0; i < count; i++)
1078 unindex_var (d, var_get_vardict (vars[i]));
1079 rename_var (vars[i], new_names[i]);
1082 /* Add the renamed variables back into the name hash,
1083 checking for conflicts. */
1084 for (i = 0; i < count; i++)
1086 if (dict_lookup_var (d, var_get_name (vars[i])) != NULL)
1088 /* There is a name conflict.
1089 Back out all the name changes that have already
1090 taken place, and indicate failure. */
1091 size_t fail_idx = i;
1092 if (err_name != NULL)
1093 *err_name = new_names[i];
1095 for (i = 0; i < fail_idx; i++)
1096 unindex_var (d, var_get_vardict (vars[i]));
1098 for (i = 0; i < count; i++)
1100 rename_var (vars[i], old_names[i]);
1101 reindex_var (d, var_get_vardict (vars[i]), false);
1104 pool_destroy (pool);
1107 reindex_var (d, var_get_vardict (vars[i]), false);
1110 /* Clear short names. */
1111 if (settings_get_algorithm () == ENHANCED)
1112 for (i = 0; i < count; i++)
1113 var_clear_short_names (vars[i]);
1115 pool_destroy (pool);
1119 /* Returns true if a variable named NAME may be inserted in DICT;
1120 that is, if there is not already a variable with that name in
1121 DICT and if NAME is not a reserved word. (The caller's checks
1122 have already verified that NAME is otherwise acceptable as a
1125 var_name_is_insertable (const struct dictionary *dict, const char *name)
1127 return (dict_lookup_var (dict, name) == NULL
1128 && lex_id_to_token (ss_cstr (name)) == T_ID);
1132 make_hinted_name (const struct dictionary *dict, const char *hint)
1134 size_t hint_len = strlen (hint);
1135 bool dropped = false;
1140 if (hint_len > ID_MAX_LEN)
1141 hint_len = ID_MAX_LEN;
1143 /* The allocation size here is OK: characters that are copied directly fit
1144 OK, and characters that are not copied directly are replaced by a single
1145 '_' byte. If u8_mbtouc() replaces bad input by 0xfffd, then that will get
1146 replaced by '_' too. */
1147 root = rp = xmalloc (hint_len + 1);
1148 for (ofs = 0; ofs < hint_len; ofs += mblen)
1152 mblen = u8_mbtouc (&uc, CHAR_CAST (const uint8_t *, hint + ofs),
1155 ? lex_uc_is_id1 (uc) && uc != '$'
1156 : lex_uc_is_idn (uc))
1163 rp += u8_uctomb (CHAR_CAST (uint8_t *, rp), uc, 6);
1165 else if (rp != root)
1170 if (root[0] != '\0')
1172 unsigned long int i;
1174 if (var_name_is_insertable (dict, root))
1177 for (i = 0; i < ULONG_MAX; i++)
1179 char suffix[INT_BUFSIZE_BOUND (i) + 1];
1183 if (!str_format_26adic (i + 1, true, &suffix[1], sizeof suffix - 1))
1186 name = utf8_encoding_concat (root, suffix, dict->encoding, 64);
1187 if (var_name_is_insertable (dict, name))
1202 make_numeric_name (const struct dictionary *dict, unsigned long int *num_start)
1204 unsigned long int number;
1206 for (number = num_start != NULL ? MAX (*num_start, 1) : 1;
1210 char name[3 + INT_STRLEN_BOUND (number) + 1];
1212 sprintf (name, "VAR%03lu", number);
1213 if (dict_lookup_var (dict, name) == NULL)
1215 if (num_start != NULL)
1216 *num_start = number + 1;
1217 return xstrdup (name);
1225 /* Devises and returns a variable name unique within DICT. The variable name
1226 is owned by the caller, which must free it with free() when it is no longer
1229 HINT, if it is non-null, is used as a suggestion that will be
1230 modified for suitability as a variable name and for
1233 If HINT is null or entirely unsuitable, a name in the form
1234 "VAR%03d" will be generated, where the smallest unused integer
1235 value is used. If NUM_START is non-null, then its value is
1236 used as the minimum numeric value to check, and it is updated
1237 to the next value to be checked.
1240 dict_make_unique_var_name (const struct dictionary *dict, const char *hint,
1241 unsigned long int *num_start)
1245 char *hinted_name = make_hinted_name (dict, hint);
1246 if (hinted_name != NULL)
1250 return make_numeric_name (dict, num_start);
1253 /* Returns whether variable names must be valid identifiers. Normally, this is
1254 true, but sometimes a dictionary is prepared for external use (e.g. output
1255 to a CSV file) where names don't have to be valid. */
1257 dict_get_names_must_be_ids (const struct dictionary *d)
1259 return d->names_must_be_ids;
1262 /* Sets whether variable names must be valid identifiers. Normally, this is
1263 true, but sometimes a dictionary is prepared for external use (e.g. output
1264 to a CSV file) where names don't have to be valid.
1266 Changing this setting from false to true doesn't make the dictionary check
1267 all the existing variable names, so it can cause an invariant violation. */
1269 dict_set_names_must_be_ids (struct dictionary *d, bool names_must_be_ids)
1271 d->names_must_be_ids = names_must_be_ids;
1274 /* Returns the weighting variable in dictionary D, or a null
1275 pointer if the dictionary is unweighted. */
1277 dict_get_weight (const struct dictionary *d)
1279 assert (d->weight == NULL || dict_contains_var (d, d->weight));
1284 /* Returns the value of D's weighting variable in case C, except
1285 that a negative or missing weight is returned as 0. Returns 1 if the
1286 dictionary is unweighted. Will warn about missing, negative,
1287 or zero values if *WARN_ON_INVALID is true. The function will
1288 set *WARN_ON_INVALID to false if an invalid weight is
1291 dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
1292 bool *warn_on_invalid)
1296 if (d->weight == NULL)
1300 double w = case_num (c, d->weight);
1302 return var_force_valid_weight (d->weight, w, warn_on_invalid);
1306 /* Like dict_get_case_weight(), but additionally rounds each weight to the
1309 dict_get_rounded_case_weight (const struct dictionary *d,
1310 const struct ccase *c, bool *warn_on_invalid)
1312 return floor (dict_get_case_weight (d, c, warn_on_invalid) + 0.5);
1315 /* Returns the format to use for weights. */
1316 const struct fmt_spec *
1317 dict_get_weight_format (const struct dictionary *d)
1319 return d->weight ? var_get_print_format (d->weight) : &F_8_0;
1322 /* Sets the weighting variable of D to V, or turning off
1323 weighting if V is a null pointer. */
1325 dict_set_weight (struct dictionary *d, struct variable *v)
1327 assert (v == NULL || dict_contains_var (d, v));
1328 assert (v == NULL || var_is_numeric (v));
1332 if (d->changed) d->changed (d, d->changed_data);
1333 if (d->callbacks && d->callbacks->weight_changed)
1334 d->callbacks->weight_changed (d,
1335 v ? var_get_dict_index (v) : -1,
1339 /* Returns the filter variable in dictionary D (see cmd_filter())
1340 or a null pointer if the dictionary is unfiltered. */
1342 dict_get_filter (const struct dictionary *d)
1344 assert (d->filter == NULL || dict_contains_var (d, d->filter));
1349 /* Sets V as the filter variable for dictionary D. Passing a
1350 null pointer for V turn off filtering. */
1352 dict_set_filter (struct dictionary *d, struct variable *v)
1354 assert (v == NULL || dict_contains_var (d, v));
1355 assert (v == NULL || var_is_numeric (v));
1359 if (d->changed) d->changed (d, d->changed_data);
1360 if (d->callbacks && d->callbacks->filter_changed)
1361 d->callbacks->filter_changed (d,
1362 v ? var_get_dict_index (v) : -1,
1366 /* Returns the case limit for dictionary D, or zero if the number
1367 of cases is unlimited. */
1369 dict_get_case_limit (const struct dictionary *d)
1371 return d->case_limit;
1374 /* Sets CASE_LIMIT as the case limit for dictionary D. Use
1375 0 for CASE_LIMIT to indicate no limit. */
1377 dict_set_case_limit (struct dictionary *d, casenumber case_limit)
1379 d->case_limit = case_limit;
1382 /* Returns the prototype used for cases created by dictionary D. */
1383 const struct caseproto *
1384 dict_get_proto (const struct dictionary *d_)
1386 struct dictionary *d = CONST_CAST (struct dictionary *, d_);
1387 if (d->proto == NULL)
1391 d->proto = caseproto_create ();
1392 d->proto = caseproto_reserve (d->proto, d->n_vars);
1393 for (i = 0; i < d->n_vars; i++)
1394 d->proto = caseproto_set_width (d->proto,
1395 var_get_case_index (d->vars[i].var),
1396 var_get_width (d->vars[i].var));
1401 /* Returns the case index of the next value to be added to D.
1402 This value is the number of `union value's that need to be
1403 allocated to store a case for dictionary D. */
1405 dict_get_next_value_idx (const struct dictionary *d)
1407 return d->next_value_idx;
1410 /* Returns the number of bytes needed to store a case for
1413 dict_get_case_size (const struct dictionary *d)
1415 return sizeof (union value) * dict_get_next_value_idx (d);
1418 /* Reassigns values in dictionary D so that fragmentation is
1421 dict_compact_values (struct dictionary *d)
1425 d->next_value_idx = 0;
1426 for (i = 0; i < d->n_vars; i++)
1428 struct variable *v = d->vars[i].var;
1429 set_var_case_index (v, d->next_value_idx++);
1431 invalidate_proto (d);
1434 /* Returns the number of values occupied by the variables in
1435 dictionary D. All variables are considered if EXCLUDE_CLASSES
1436 is 0, or it may contain one or more of (1u << DC_ORDINARY),
1437 (1u << DC_SYSTEM), or (1u << DC_SCRATCH) to exclude the
1438 corresponding type of variable.
1440 The return value may be less than the number of values in one
1441 of dictionary D's cases (as returned by
1442 dict_get_next_value_idx) even if E is 0, because there may be
1443 gaps in D's cases due to deleted variables. */
1445 dict_count_values (const struct dictionary *d, unsigned int exclude_classes)
1447 assert ((exclude_classes & ~((1u << DC_ORDINARY)
1449 | (1u << DC_SCRATCH))) == 0);
1452 for (size_t i = 0; i < d->n_vars; i++)
1454 enum dict_class class = var_get_dict_class (d->vars[i].var);
1455 if (!(exclude_classes & (1u << class)))
1461 /* Returns the case prototype that would result after deleting
1462 all variables from D that are not in one of the
1463 EXCLUDE_CLASSES and compacting the dictionary with
1466 The caller must unref the returned caseproto when it is no
1469 dict_get_compacted_proto (const struct dictionary *d,
1470 unsigned int exclude_classes)
1472 struct caseproto *proto;
1475 assert ((exclude_classes & ~((1u << DC_ORDINARY)
1477 | (1u << DC_SCRATCH))) == 0);
1479 proto = caseproto_create ();
1480 for (i = 0; i < d->n_vars; i++)
1482 struct variable *v = d->vars[i].var;
1483 if (!(exclude_classes & (1u << var_get_dict_class (v))))
1484 proto = caseproto_add_width (proto, var_get_width (v));
1488 /* Returns the file label for D, or a null pointer if D is
1489 unlabeled (see cmd_file_label()). */
1491 dict_get_label (const struct dictionary *d)
1496 /* Sets D's file label to LABEL, truncating it to at most 60 bytes in D's
1499 Removes D's label if LABEL is null or the empty string. */
1501 dict_set_label (struct dictionary *d, const char *label)
1504 if (label == NULL || label[0] == '\0')
1507 d->label = utf8_encoding_trunc (label, d->encoding, 60);
1510 /* Returns the documents for D, as an UTF-8 encoded string_array. The
1511 return value is always nonnull; if there are no documents then the
1512 string_arary is empty.*/
1513 const struct string_array *
1514 dict_get_documents (const struct dictionary *d)
1516 return &d->documents;
1519 /* Replaces the documents for D by NEW_DOCS, a UTF-8 encoded string_array. */
1521 dict_set_documents (struct dictionary *d, const struct string_array *new_docs)
1523 /* Swap out the old documents, instead of destroying them immediately, to
1524 allow the new documents to include pointers into the old ones. */
1525 struct string_array old_docs = STRING_ARRAY_INITIALIZER;
1526 string_array_swap (&d->documents, &old_docs);
1528 for (size_t i = 0; i < new_docs->n; i++)
1529 dict_add_document_line (d, new_docs->strings[i], false);
1531 string_array_destroy (&old_docs);
1534 /* Replaces the documents for D by UTF-8 encoded string NEW_DOCS, dividing it
1535 into individual lines at new-line characters. Each line is truncated to at
1536 most DOC_LINE_LENGTH bytes in D's encoding. */
1538 dict_set_documents_string (struct dictionary *d, const char *new_docs)
1542 dict_clear_documents (d);
1543 for (s = new_docs; *s != '\0';)
1545 size_t len = strcspn (s, "\n");
1546 char *line = xmemdup0 (s, len);
1547 dict_add_document_line (d, line, false);
1556 /* Drops the documents from dictionary D. */
1558 dict_clear_documents (struct dictionary *d)
1560 string_array_clear (&d->documents);
1563 /* Appends the UTF-8 encoded LINE to the documents in D. LINE will be
1564 truncated so that it is no more than 80 bytes in the dictionary's
1565 encoding. If this causes some text to be lost, and ISSUE_WARNING is true,
1566 then a warning will be issued. */
1568 dict_add_document_line (struct dictionary *d, const char *line,
1574 trunc_len = utf8_encoding_trunc_len (line, d->encoding, DOC_LINE_LENGTH);
1575 truncated = line[trunc_len] != '\0';
1576 if (truncated && issue_warning)
1578 /* TRANSLATORS: "bytes" is correct, not characters due to UTF encoding */
1579 msg (SW, _("Truncating document line to %d bytes."), DOC_LINE_LENGTH);
1582 string_array_append_nocopy (&d->documents, xmemdup0 (line, trunc_len));
1587 /* Returns the number of document lines in dictionary D. */
1589 dict_get_document_n_lines (const struct dictionary *d)
1591 return d->documents.n;
1594 /* Returns document line number IDX in dictionary D. The caller must not
1595 modify or free the returned string. */
1597 dict_get_document_line (const struct dictionary *d, size_t idx)
1599 assert (idx < d->documents.n);
1600 return d->documents.strings[idx];
1603 /* Creates in D a vector named NAME that contains the N
1604 variables in VAR. Returns true if successful, or false if a
1605 vector named NAME already exists in D. */
1607 dict_create_vector (struct dictionary *d,
1609 struct variable **var, size_t n)
1612 for (size_t i = 0; i < n; i++)
1613 assert (dict_contains_var (d, var[i]));
1615 if (dict_lookup_vector (d, name) == NULL)
1617 d->vector = xnrealloc (d->vector, d->n_vectors + 1, sizeof *d->vector);
1618 d->vector[d->n_vectors++] = vector_create (name, var, n);
1625 /* Creates in D a vector named NAME that contains the N
1626 variables in VAR. A vector named NAME must not already exist
1629 dict_create_vector_assert (struct dictionary *d,
1631 struct variable **var, size_t n)
1633 assert (dict_lookup_vector (d, name) == NULL);
1634 dict_create_vector (d, name, var, n);
1637 /* Returns the vector in D with index IDX, which must be less
1638 than dict_get_n_vectors (D). */
1639 const struct vector *
1640 dict_get_vector (const struct dictionary *d, size_t idx)
1642 assert (idx < d->n_vectors);
1644 return d->vector[idx];
1647 /* Returns the number of vectors in D. */
1649 dict_get_n_vectors (const struct dictionary *d)
1651 return d->n_vectors;
1654 /* Looks up and returns the vector within D with the given
1656 const struct vector *
1657 dict_lookup_vector (const struct dictionary *d, const char *name)
1660 for (i = 0; i < d->n_vectors; i++)
1661 if (!utf8_strcasecmp (vector_get_name (d->vector[i]), name))
1662 return d->vector[i];
1666 /* Deletes all vectors from D. */
1668 dict_clear_vectors (struct dictionary *d)
1672 for (i = 0; i < d->n_vectors; i++)
1673 vector_destroy (d->vector[i]);
1680 /* Multiple response sets. */
1682 /* Returns the multiple response set in DICT with index IDX, which must be
1683 between 0 and the count returned by dict_get_n_mrsets(), exclusive. */
1684 const struct mrset *
1685 dict_get_mrset (const struct dictionary *dict, size_t idx)
1687 assert (idx < dict->n_mrsets);
1688 return dict->mrsets[idx];
1691 /* Returns the number of multiple response sets in DICT. */
1693 dict_get_n_mrsets (const struct dictionary *dict)
1695 return dict->n_mrsets;
1698 /* Looks for a multiple response set named NAME in DICT. If it finds one,
1699 returns its index; otherwise, returns SIZE_MAX. */
1701 dict_lookup_mrset_idx (const struct dictionary *dict, const char *name)
1705 for (i = 0; i < dict->n_mrsets; i++)
1706 if (!utf8_strcasecmp (name, dict->mrsets[i]->name))
1712 /* Looks for a multiple response set named NAME in DICT. If it finds one,
1713 returns it; otherwise, returns NULL. */
1714 const struct mrset *
1715 dict_lookup_mrset (const struct dictionary *dict, const char *name)
1717 size_t idx = dict_lookup_mrset_idx (dict, name);
1718 return idx != SIZE_MAX ? dict->mrsets[idx] : NULL;
1721 /* Adds MRSET to DICT, replacing any existing set with the same name. Returns
1722 true if a set was replaced, false if none existed with the specified name.
1724 Ownership of MRSET is transferred to DICT. */
1726 dict_add_mrset (struct dictionary *dict, struct mrset *mrset)
1730 assert (mrset_ok (mrset, dict));
1732 idx = dict_lookup_mrset_idx (dict, mrset->name);
1733 if (idx == SIZE_MAX)
1735 dict->mrsets = xrealloc (dict->mrsets,
1736 (dict->n_mrsets + 1) * sizeof *dict->mrsets);
1737 dict->mrsets[dict->n_mrsets++] = mrset;
1742 mrset_destroy (dict->mrsets[idx]);
1743 dict->mrsets[idx] = mrset;
1748 /* Looks for a multiple response set in DICT named NAME. If found, removes it
1749 from DICT and returns true. If none is found, returns false without
1752 Deleting one multiple response set causes the indexes of other sets within
1755 dict_delete_mrset (struct dictionary *dict, const char *name)
1757 size_t idx = dict_lookup_mrset_idx (dict, name);
1758 if (idx != SIZE_MAX)
1760 mrset_destroy (dict->mrsets[idx]);
1761 dict->mrsets[idx] = dict->mrsets[--dict->n_mrsets];
1768 /* Deletes all multiple response sets from DICT. */
1770 dict_clear_mrsets (struct dictionary *dict)
1774 for (i = 0; i < dict->n_mrsets; i++)
1775 mrset_destroy (dict->mrsets[i]);
1776 free (dict->mrsets);
1777 dict->mrsets = NULL;
1781 /* Removes VAR, which must be in DICT, from DICT's multiple response sets. */
1783 dict_unset_mrset_var (struct dictionary *dict, struct variable *var)
1787 assert (dict_contains_var (dict, var));
1789 for (i = 0; i < dict->n_mrsets;)
1791 struct mrset *mrset = dict->mrsets[i];
1794 for (j = 0; j < mrset->n_vars;)
1795 if (mrset->vars[j] == var)
1796 remove_element (mrset->vars, mrset->n_vars--,
1797 sizeof *mrset->vars, j);
1801 if (mrset->n_vars < 2)
1803 mrset_destroy (mrset);
1804 dict->mrsets[i] = dict->mrsets[--dict->n_mrsets];
1811 /* Returns D's attribute set. The caller may examine or modify
1812 the attribute set, but must not destroy it. Destroying D or
1813 calling dict_set_attributes for D will also destroy D's
1816 dict_get_attributes (const struct dictionary *d)
1818 return CONST_CAST (struct attrset *, &d->attributes);
1821 /* Replaces D's attributes set by a copy of ATTRS. */
1823 dict_set_attributes (struct dictionary *d, const struct attrset *attrs)
1825 attrset_destroy (&d->attributes);
1826 attrset_clone (&d->attributes, attrs);
1829 /* Returns true if D has at least one attribute in its attribute
1830 set, false if D's attribute set is empty. */
1832 dict_has_attributes (const struct dictionary *d)
1834 return attrset_count (&d->attributes) > 0;
1837 /* Called from variable.c to notify the dictionary that some property (indicated
1838 by WHAT) of the variable has changed. OLDVAR is a copy of V as it existed
1839 prior to the change. OLDVAR is destroyed by this function.
1842 dict_var_changed (const struct variable *v, unsigned int what, struct variable *oldvar)
1844 if (var_has_vardict (v))
1846 const struct vardict_info *vardict = var_get_vardict (v);
1847 struct dictionary *d = vardict->dict;
1852 if (what & (VAR_TRAIT_WIDTH | VAR_TRAIT_POSITION))
1853 invalidate_proto (d);
1855 if (d->changed) d->changed (d, d->changed_data);
1856 if (d->callbacks && d->callbacks->var_changed)
1857 d->callbacks->var_changed (d, var_get_dict_index (v), what, oldvar, d->cb_data);
1864 /* Dictionary used to contain "internal variables". */
1865 static struct dictionary *internal_dict;
1867 /* Create a variable of the specified WIDTH to be used for internal
1868 calculations only. The variable is assigned case index CASE_IDX. */
1870 dict_create_internal_var (int case_idx, int width)
1872 if (internal_dict == NULL)
1873 internal_dict = dict_create ("UTF-8");
1877 static int counter = INT_MAX / 2;
1878 struct variable *var;
1881 if (++counter == INT_MAX)
1882 counter = INT_MAX / 2;
1884 sprintf (name, "$internal%d", counter);
1885 var = dict_create_var (internal_dict, name, width);
1888 set_var_case_index (var, case_idx);
1894 /* Destroys VAR, which must have been created with
1895 dict_create_internal_var(). */
1897 dict_destroy_internal_var (struct variable *var)
1901 dict_delete_var (internal_dict, var);
1903 /* Destroy internal_dict if it has no variables left, just so that
1904 valgrind --leak-check --show-reachable won't show internal_dict. */
1905 if (dict_get_n_vars (internal_dict) == 0)
1907 dict_unref (internal_dict);
1908 internal_dict = NULL;
1914 vardict_get_dict_index (const struct vardict_info *vardict)
1916 return vardict - vardict->dict->vars;