SAVE TRANSLATE: Allow variable names with space, etc. in output.
[pspp] / src / data / dictionary.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "data/dictionary.h"
20
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <ctype.h>
24 #include <unistr.h>
25
26 #include "data/attributes.h"
27 #include "data/case.h"
28 #include "data/identifier.h"
29 #include "data/mrset.h"
30 #include "data/settings.h"
31 #include "data/value-labels.h"
32 #include "data/vardict.h"
33 #include "data/variable.h"
34 #include "data/vector.h"
35 #include "libpspp/array.h"
36 #include "libpspp/assertion.h"
37 #include "libpspp/compiler.h"
38 #include "libpspp/hash-functions.h"
39 #include "libpspp/hmap.h"
40 #include "libpspp/i18n.h"
41 #include "libpspp/message.h"
42 #include "libpspp/misc.h"
43 #include "libpspp/pool.h"
44 #include "libpspp/str.h"
45 #include "libpspp/string-array.h"
46
47 #include "gl/intprops.h"
48 #include "gl/minmax.h"
49 #include "gl/xalloc.h"
50 #include "gl/xmemdup0.h"
51
52 #include "gettext.h"
53 #define _(msgid) gettext (msgid)
54
55 /* A dictionary. */
56 struct dictionary
57   {
58     struct vardict_info *var;   /* Variables. */
59     size_t var_cnt, var_cap;    /* Number of variables, capacity. */
60     struct caseproto *proto;    /* Prototype for dictionary cases
61                                    (updated lazily). */
62     struct hmap name_map;       /* Variable index by name. */
63     int next_value_idx;         /* Index of next `union value' to allocate. */
64     const struct variable **split;    /* SPLIT FILE vars. */
65     size_t split_cnt;           /* SPLIT FILE count. */
66     struct variable *weight;    /* WEIGHT variable. */
67     struct variable *filter;    /* FILTER variable. */
68     casenumber case_limit;      /* Current case limit (N command). */
69     char *label;                /* File label. */
70     struct string_array documents; /* Documents. */
71     struct vector **vector;     /* Vectors of variables. */
72     size_t vector_cnt;          /* Number of vectors. */
73     struct attrset attributes;  /* Custom attributes. */
74     struct mrset **mrsets;      /* Multiple response sets. */
75     size_t n_mrsets;            /* Number of multiple response sets. */
76
77     /* Whether variable names must be valid identifiers.  Normally, this is
78        true, but sometimes a dictionary is prepared for external use
79        (e.g. output to a CSV file) where names don't have to be valid. */
80     bool names_must_be_ids;
81
82     char *encoding;             /* Character encoding of string data */
83
84     const struct dict_callbacks *callbacks; /* Callbacks on dictionary
85                                                modification */
86     void *cb_data ;                  /* Data passed to callbacks */
87
88     void (*changed) (struct dictionary *, void *); /* Generic change callback */
89     void *changed_data;
90   };
91
92 static void dict_unset_split_var (struct dictionary *, struct variable *);
93 static void dict_unset_mrset_var (struct dictionary *, struct variable *);
94
95 /* Returns the encoding for data in dictionary D.  The return value is a
96    nonnull string that contains an IANA character set name. */
97 const char *
98 dict_get_encoding (const struct dictionary *d)
99 {
100   return d->encoding ;
101 }
102
103 /* Returns true if UTF-8 string ID is an acceptable identifier in DICT's
104    encoding, false otherwise.  If ISSUE_ERROR is true, issues an explanatory
105    error message on failure. */
106 bool
107 dict_id_is_valid (const struct dictionary *dict, const char *id,
108                   bool issue_error)
109 {
110   return (!dict->names_must_be_ids
111           || id_is_valid (id, dict->encoding, issue_error));
112 }
113
114 void
115 dict_set_change_callback (struct dictionary *d,
116                           void (*changed) (struct dictionary *, void*),
117                           void *data)
118 {
119   d->changed = changed;
120   d->changed_data = data;
121 }
122
123 /* Discards dictionary D's caseproto.  (It will be regenerated
124    lazily, on demand.) */
125 static void
126 invalidate_proto (struct dictionary *d)
127 {
128   caseproto_unref (d->proto);
129   d->proto = NULL;
130 }
131
132 /* Print a representation of dictionary D to stdout, for
133    debugging purposes. */
134 void
135 dict_dump (const struct dictionary *d)
136 {
137   int i;
138   for (i = 0 ; i < d->var_cnt ; ++i )
139     {
140       const struct variable *v = d->var[i].var;
141       printf ("Name: %s;\tdict_idx: %zu; case_idx: %zu\n",
142               var_get_name (v),
143               var_get_dict_index (v),
144               var_get_case_index (v));
145
146     }
147 }
148
149 /* Associate CALLBACKS with DICT.  Callbacks will be invoked whenever
150    the dictionary or any of the variables it contains are modified.
151    Each callback will get passed CALLBACK_DATA.
152    Any callback may be NULL, in which case it'll be ignored.
153 */
154 void
155 dict_set_callbacks (struct dictionary *dict,
156                     const struct dict_callbacks *callbacks,
157                     void *callback_data)
158 {
159   dict->callbacks = callbacks;
160   dict->cb_data = callback_data;
161 }
162
163 /* Shallow copy the callbacks from SRC to DEST */
164 void
165 dict_copy_callbacks (struct dictionary *dest,
166                      const struct dictionary *src)
167 {
168   dest->callbacks = src->callbacks;
169   dest->cb_data = src->cb_data;
170 }
171
172 /* Creates and returns a new dictionary with the specified ENCODING. */
173 struct dictionary *
174 dict_create (const char *encoding)
175 {
176   struct dictionary *d = xzalloc (sizeof *d);
177
178   d->encoding = xstrdup (encoding);
179   d->names_must_be_ids = true;
180   hmap_init (&d->name_map);
181   attrset_init (&d->attributes);
182
183   return d;
184 }
185
186 /* Creates and returns a (deep) copy of an existing
187    dictionary.
188
189    The new dictionary's case indexes are copied from the old
190    dictionary.  If the new dictionary won't be used to access
191    cases produced with the old dictionary, then the new
192    dictionary's case indexes should be compacted with
193    dict_compact_values to save space.
194
195    Callbacks are not cloned. */
196 struct dictionary *
197 dict_clone (const struct dictionary *s)
198 {
199   struct dictionary *d;
200   size_t i;
201
202   d = dict_create (s->encoding);
203   dict_set_names_must_be_ids (d, dict_get_names_must_be_ids (s));
204
205   for (i = 0; i < s->var_cnt; i++)
206     {
207       struct variable *sv = s->var[i].var;
208       struct variable *dv = dict_clone_var_assert (d, sv);
209       size_t i;
210
211       for (i = 0; i < var_get_short_name_cnt (sv); i++)
212         var_set_short_name (dv, i, var_get_short_name (sv, i));
213
214       var_get_vardict (dv)->case_index = var_get_vardict (sv)->case_index;
215     }
216
217   d->next_value_idx = s->next_value_idx;
218
219   d->split_cnt = s->split_cnt;
220   if (d->split_cnt > 0)
221     {
222       d->split = xnmalloc (d->split_cnt, sizeof *d->split);
223       for (i = 0; i < d->split_cnt; i++)
224         d->split[i] = dict_lookup_var_assert (d, var_get_name (s->split[i]));
225     }
226
227   if (s->weight != NULL)
228     dict_set_weight (d, dict_lookup_var_assert (d, var_get_name (s->weight)));
229
230   if (s->filter != NULL)
231     dict_set_filter (d, dict_lookup_var_assert (d, var_get_name (s->filter)));
232
233   d->case_limit = s->case_limit;
234   dict_set_label (d, dict_get_label (s));
235   dict_set_documents (d, dict_get_documents (s));
236
237   d->vector_cnt = s->vector_cnt;
238   d->vector = xnmalloc (d->vector_cnt, sizeof *d->vector);
239   for (i = 0; i < s->vector_cnt; i++)
240     d->vector[i] = vector_clone (s->vector[i], s, d);
241
242   dict_set_attributes (d, dict_get_attributes (s));
243
244   for (i = 0; i < s->n_mrsets; i++)
245     {
246       const struct mrset *old = s->mrsets[i];
247       struct mrset *new;
248       size_t j;
249
250       /* Clone old mrset, then replace vars from D by vars from S. */
251       new = mrset_clone (old);
252       for (j = 0; j < new->n_vars; j++)
253         new->vars[j] = dict_lookup_var_assert (d, var_get_name (new->vars[j]));
254
255       dict_add_mrset (d, new);
256     }
257
258   return d;
259 }
260
261 /* Clears the contents from a dictionary without destroying the
262    dictionary itself. */
263 void
264 dict_clear (struct dictionary *d)
265 {
266   /* FIXME?  Should we really clear case_limit, label, documents?
267      Others are necessarily cleared by deleting all the variables.*/
268   while (d->var_cnt > 0 )
269     {
270       dict_delete_var (d, d->var[d->var_cnt - 1].var);
271     }
272
273   free (d->var);
274   d->var = NULL;
275   d->var_cnt = d->var_cap = 0;
276   invalidate_proto (d);
277   hmap_clear (&d->name_map);
278   d->next_value_idx = 0;
279   dict_set_split_vars (d, NULL, 0);
280   dict_set_weight (d, NULL);
281   dict_set_filter (d, NULL);
282   d->case_limit = 0;
283   free (d->label);
284   d->label = NULL;
285   string_array_clear (&d->documents);
286   dict_clear_vectors (d);
287   attrset_clear (&d->attributes);
288 }
289
290 /* Clears a dictionary and destroys it. */
291 void
292 dict_destroy (struct dictionary *d)
293 {
294   if (d != NULL)
295     {
296       /* In general, we don't want callbacks occurring, if the dictionary
297          is being destroyed */
298       d->callbacks  = NULL ;
299
300       dict_clear (d);
301       string_array_destroy (&d->documents);
302       hmap_destroy (&d->name_map);
303       attrset_destroy (&d->attributes);
304       dict_clear_mrsets (d);
305       free (d->encoding);
306       free (d);
307     }
308 }
309
310 /* Returns the number of variables in D. */
311 size_t
312 dict_get_var_cnt (const struct dictionary *d)
313 {
314   return d->var_cnt;
315 }
316
317 /* Returns the variable in D with dictionary index IDX, which
318    must be between 0 and the count returned by
319    dict_get_var_cnt(), exclusive. */
320 struct variable *
321 dict_get_var (const struct dictionary *d, size_t idx)
322 {
323   assert (idx < d->var_cnt);
324
325   return d->var[idx].var;
326 }
327
328 /* Sets *VARS to an array of pointers to variables in D and *CNT
329    to the number of variables in *D.  All variables are returned
330    except for those, if any, in the classes indicated by EXCLUDE.
331    (There is no point in putting DC_SYSTEM in EXCLUDE as
332    dictionaries never include system variables.) */
333 void
334 dict_get_vars (const struct dictionary *d, const struct variable ***vars,
335                size_t *cnt, enum dict_class exclude)
336 {
337   dict_get_vars_mutable (d, (struct variable ***) vars, cnt, exclude);
338 }
339
340 /* Sets *VARS to an array of pointers to variables in D and *CNT
341    to the number of variables in *D.  All variables are returned
342    except for those, if any, in the classes indicated by EXCLUDE.
343    (There is no point in putting DC_SYSTEM in EXCLUDE as
344    dictionaries never include system variables.) */
345 void
346 dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
347                        size_t *cnt, enum dict_class exclude)
348 {
349   size_t count;
350   size_t i;
351
352   assert (exclude == (exclude & DC_ALL));
353
354   count = 0;
355   for (i = 0; i < d->var_cnt; i++)
356     {
357       enum dict_class class = var_get_dict_class (d->var[i].var);
358       if (!(class & exclude))
359         count++;
360     }
361
362   *vars = xnmalloc (count, sizeof **vars);
363   *cnt = 0;
364   for (i = 0; i < d->var_cnt; i++)
365     {
366       enum dict_class class = var_get_dict_class (d->var[i].var);
367       if (!(class & exclude))
368         (*vars)[(*cnt)++] = d->var[i].var;
369     }
370   assert (*cnt == count);
371 }
372
373 static struct variable *
374 add_var_with_case_index (struct dictionary *d, struct variable *v,
375                          int case_index)
376 {
377   struct vardict_info *vardict;
378
379   assert (case_index >= d->next_value_idx);
380
381   /* Update dictionary. */
382   if (d->var_cnt >= d->var_cap)
383     {
384       size_t i;
385
386       d->var = x2nrealloc (d->var, &d->var_cap, sizeof *d->var);
387       hmap_clear (&d->name_map);
388       for (i = 0; i < d->var_cnt; i++)
389         {
390           var_set_vardict (d->var[i].var, &d->var[i]);
391           hmap_insert_fast (&d->name_map, &d->var[i].name_node,
392                             d->var[i].name_node.hash);
393         }
394     }
395
396   vardict = &d->var[d->var_cnt++];
397   vardict->dict = d;
398   vardict->var = v;
399   hmap_insert (&d->name_map, &vardict->name_node,
400                utf8_hash_case_string (var_get_name (v), 0));
401   vardict->case_index = case_index;
402   var_set_vardict (v, vardict);
403
404   if ( d->changed ) d->changed (d, d->changed_data);
405   if ( d->callbacks &&  d->callbacks->var_added )
406     d->callbacks->var_added (d, var_get_dict_index (v), d->cb_data);
407
408   invalidate_proto (d);
409   d->next_value_idx = case_index + 1;
410
411   return v;
412 }
413
414 static struct variable *
415 add_var (struct dictionary *d, struct variable *v)
416 {
417   return add_var_with_case_index (d, v, d->next_value_idx);
418 }
419
420 /* Creates and returns a new variable in D with the given NAME
421    and WIDTH.  Returns a null pointer if the given NAME would
422    duplicate that of an existing variable in the dictionary. */
423 struct variable *
424 dict_create_var (struct dictionary *d, const char *name, int width)
425 {
426   return (dict_lookup_var (d, name) == NULL
427           ? dict_create_var_assert (d, name, width)
428           : NULL);
429 }
430
431 /* Creates and returns a new variable in D with the given NAME
432    and WIDTH.  Assert-fails if the given NAME would duplicate
433    that of an existing variable in the dictionary. */
434 struct variable *
435 dict_create_var_assert (struct dictionary *d, const char *name, int width)
436 {
437   assert (dict_lookup_var (d, name) == NULL);
438   return add_var (d, var_create (name, width));
439 }
440
441 /* Creates and returns a new variable in D, as a copy of existing variable
442    OLD_VAR, which need not be in D or in any dictionary.  Returns a null
443    pointer if OLD_VAR's name would duplicate that of an existing variable in
444    the dictionary. */
445 struct variable *
446 dict_clone_var (struct dictionary *d, const struct variable *old_var)
447 {
448   return dict_clone_var_as (d, old_var, var_get_name (old_var));
449 }
450
451 /* Creates and returns a new variable in D, as a copy of existing variable
452    OLD_VAR, which need not be in D or in any dictionary.  Assert-fails if
453    OLD_VAR's name would duplicate that of an existing variable in the
454    dictionary. */
455 struct variable *
456 dict_clone_var_assert (struct dictionary *d, const struct variable *old_var)
457 {
458   return dict_clone_var_as_assert (d, old_var, var_get_name (old_var));
459 }
460
461 /* Creates and returns a new variable in D with name NAME, as a copy of
462    existing variable OLD_VAR, which need not be in D or in any dictionary.
463    Returns a null pointer if the given NAME would duplicate that of an existing
464    variable in the dictionary. */
465 struct variable *
466 dict_clone_var_as (struct dictionary *d, const struct variable *old_var,
467                    const char *name)
468 {
469   return (dict_lookup_var (d, name) == NULL
470           ? dict_clone_var_as_assert (d, old_var, name)
471           : NULL);
472 }
473
474 /* Creates and returns a new variable in D with name NAME, as a copy of
475    existing variable OLD_VAR, which need not be in D or in any dictionary.
476    Assert-fails if the given NAME would duplicate that of an existing variable
477    in the dictionary. */
478 struct variable *
479 dict_clone_var_as_assert (struct dictionary *d, const struct variable *old_var,
480                           const char *name)
481 {
482   struct variable *new_var = var_clone (old_var);
483   assert (dict_lookup_var (d, name) == NULL);
484   var_set_name (new_var, name);
485   return add_var (d, new_var);
486 }
487
488 struct variable *
489 dict_clone_var_in_place_assert (struct dictionary *d,
490                                 const struct variable *old_var)
491 {
492   assert (dict_lookup_var (d, var_get_name (old_var)) == NULL);
493   return add_var_with_case_index (d, var_clone (old_var),
494                                   var_get_case_index (old_var));
495 }
496
497 /* Returns the variable named NAME in D, or a null pointer if no
498    variable has that name. */
499 struct variable *
500 dict_lookup_var (const struct dictionary *d, const char *name)
501 {
502   struct vardict_info *vardict;
503
504   HMAP_FOR_EACH_WITH_HASH (vardict, struct vardict_info, name_node,
505                            utf8_hash_case_string (name, 0), &d->name_map)
506     {
507       struct variable *var = vardict->var;
508       if (!utf8_strcasecmp (var_get_name (var), name))
509         return var;
510     }
511
512   return NULL;
513 }
514
515 /* Returns the variable named NAME in D.  Assert-fails if no
516    variable has that name. */
517 struct variable *
518 dict_lookup_var_assert (const struct dictionary *d, const char *name)
519 {
520   struct variable *v = dict_lookup_var (d, name);
521   assert (v != NULL);
522   return v;
523 }
524
525 /* Returns true if variable V is in dictionary D,
526    false otherwise. */
527 bool
528 dict_contains_var (const struct dictionary *d, const struct variable *v)
529 {
530   return (var_has_vardict (v)
531           && vardict_get_dictionary (var_get_vardict (v)) == d);
532 }
533
534 /* Compares two double pointers to variables, which should point
535    to elements of a struct dictionary's `var' member array. */
536 static int
537 compare_var_ptrs (const void *a_, const void *b_, const void *aux UNUSED)
538 {
539   struct variable *const *a = a_;
540   struct variable *const *b = b_;
541
542   return *a < *b ? -1 : *a > *b;
543 }
544
545 static void
546 unindex_var (struct dictionary *d, struct vardict_info *vardict)
547 {
548   hmap_delete (&d->name_map, &vardict->name_node);
549 }
550
551 /* This function assumes that vardict->name_node.hash is valid, that is, that
552    its name has not changed since it was hashed (rename_var() updates this
553    hash along with the name itself). */
554 static void
555 reindex_var (struct dictionary *d, struct vardict_info *vardict)
556 {
557   struct variable *old = (d->callbacks && d->callbacks->var_changed
558                           ? var_clone (vardict->var)
559                           : NULL);
560
561   struct variable *var = vardict->var;
562   var_set_vardict (var, vardict);
563   hmap_insert_fast (&d->name_map, &vardict->name_node,
564                     vardict->name_node.hash);
565
566   if ( d->changed ) d->changed (d, d->changed_data);
567   if (old)
568     {
569       d->callbacks->var_changed (d, var_get_dict_index (var), VAR_TRAIT_POSITION, old, d->cb_data);
570       var_destroy (old);
571     }
572 }
573
574 /* Sets the case_index in V's vardict to CASE_INDEX. */
575 static void
576 set_var_case_index (struct variable *v, int case_index)
577 {
578   var_get_vardict (v)->case_index = case_index;
579 }
580
581 /* Removes the dictionary variables with indexes from FROM to TO (exclusive)
582    from name_map. */
583 static void
584 unindex_vars (struct dictionary *d, size_t from, size_t to)
585 {
586   size_t i;
587
588   for (i = from; i < to; i++)
589     unindex_var (d, &d->var[i]);
590 }
591
592 /* Re-sets the dict_index in the dictionary variables with
593    indexes from FROM to TO (exclusive). */
594 static void
595 reindex_vars (struct dictionary *d, size_t from, size_t to)
596 {
597   size_t i;
598
599   for (i = from; i < to; i++)
600     reindex_var (d, &d->var[i]);
601 }
602
603 /* Deletes variable V from dictionary D and frees V.
604
605    This is a very bad idea if there might be any pointers to V
606    from outside D.  In general, no variable in the active dataset's
607    dictionary should be deleted when any transformations are
608    active on the dictionary's dataset, because those
609    transformations might reference the deleted variable.  The
610    safest time to delete a variable is just after a procedure has
611    been executed, as done by DELETE VARIABLES.
612
613    Pointers to V within D are not a problem, because
614    dict_delete_var() knows to remove V from split variables,
615    weights, filters, etc. */
616 void
617 dict_delete_var (struct dictionary *d, struct variable *v)
618 {
619   int dict_index = var_get_dict_index (v);
620   const int case_index = var_get_case_index (v);
621
622   assert (dict_contains_var (d, v));
623
624   dict_unset_split_var (d, v);
625   dict_unset_mrset_var (d, v);
626
627   if (d->weight == v)
628     dict_set_weight (d, NULL);
629
630   if (d->filter == v)
631     dict_set_filter (d, NULL);
632
633   dict_clear_vectors (d);
634
635   /* Remove V from var array. */
636   unindex_vars (d, dict_index, d->var_cnt);
637   remove_element (d->var, d->var_cnt, sizeof *d->var, dict_index);
638   d->var_cnt--;
639
640   /* Update dict_index for each affected variable. */
641   reindex_vars (d, dict_index, d->var_cnt);
642
643   /* Free memory. */
644   var_clear_vardict (v);
645
646   if ( d->changed ) d->changed (d, d->changed_data);
647
648   invalidate_proto (d);
649   if (d->callbacks &&  d->callbacks->var_deleted )
650     d->callbacks->var_deleted (d, v, dict_index, case_index, d->cb_data);
651
652   var_destroy (v);
653 }
654
655 /* Deletes the COUNT variables listed in VARS from D.  This is
656    unsafe; see the comment on dict_delete_var() for details. */
657 void
658 dict_delete_vars (struct dictionary *d,
659                   struct variable *const *vars, size_t count)
660 {
661   /* FIXME: this can be done in O(count) time, but this algorithm
662      is O(count**2). */
663   assert (count == 0 || vars != NULL);
664
665   while (count-- > 0)
666     dict_delete_var (d, *vars++);
667 }
668
669 /* Deletes the COUNT variables in D starting at index IDX.  This
670    is unsafe; see the comment on dict_delete_var() for
671    details. */
672 void
673 dict_delete_consecutive_vars (struct dictionary *d, size_t idx, size_t count)
674 {
675   /* FIXME: this can be done in O(count) time, but this algorithm
676      is O(count**2). */
677   assert (idx + count <= d->var_cnt);
678
679   while (count-- > 0)
680     dict_delete_var (d, d->var[idx].var);
681 }
682
683 /* Deletes scratch variables from dictionary D. */
684 void
685 dict_delete_scratch_vars (struct dictionary *d)
686 {
687   int i;
688
689   /* FIXME: this can be done in O(count) time, but this algorithm
690      is O(count**2). */
691   for (i = 0; i < d->var_cnt; )
692     if (var_get_dict_class (d->var[i].var) == DC_SCRATCH)
693       dict_delete_var (d, d->var[i].var);
694     else
695       i++;
696 }
697
698 /* Moves V to 0-based position IDX in D.  Other variables in D,
699    if any, retain their relative positions.  Runs in time linear
700    in the distance moved. */
701 void
702 dict_reorder_var (struct dictionary *d, struct variable *v, size_t new_index)
703 {
704   size_t old_index = var_get_dict_index (v);
705
706   assert (new_index < d->var_cnt);
707
708   unindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1);
709   move_element (d->var, d->var_cnt, sizeof *d->var, old_index, new_index);
710   reindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1);
711 }
712
713 /* Reorders the variables in D, placing the COUNT variables
714    listed in ORDER in that order at the beginning of D.  The
715    other variables in D, if any, retain their relative
716    positions. */
717 void
718 dict_reorder_vars (struct dictionary *d,
719                    struct variable *const *order, size_t count)
720 {
721   struct vardict_info *new_var;
722   size_t i;
723
724   assert (count == 0 || order != NULL);
725   assert (count <= d->var_cnt);
726
727   new_var = xnmalloc (d->var_cap, sizeof *new_var);
728
729   /* Add variables in ORDER to new_var. */
730   for (i = 0; i < count; i++)
731     {
732       struct vardict_info *old_var;
733
734       assert (dict_contains_var (d, order[i]));
735
736       old_var = var_get_vardict (order[i]);
737       new_var[i] = *old_var;
738       old_var->dict = NULL;
739     }
740
741   /* Add remaining variables to new_var. */
742   for (i = 0; i < d->var_cnt; i++)
743     if (d->var[i].dict != NULL)
744       new_var[count++] = d->var[i];
745   assert (count == d->var_cnt);
746
747   /* Replace old vardicts by new ones. */
748   free (d->var);
749   d->var = new_var;
750
751   hmap_clear (&d->name_map);
752   reindex_vars (d, 0, d->var_cnt);
753 }
754
755 /* Changes the name of variable V that is currently in a dictionary to
756    NEW_NAME. */
757 static void
758 rename_var (struct variable *v, const char *new_name)
759 {
760   struct vardict_info *vardict = var_get_vardict (v);
761   var_clear_vardict (v);
762   var_set_name (v, new_name);
763   vardict->name_node.hash = utf8_hash_case_string (new_name, 0);
764   var_set_vardict (v, vardict);
765 }
766
767 /* Tries to changes the name of V in D to name NEW_NAME.  Returns true if
768    successful, false if a variable (other than V) with the given name already
769    exists in D. */
770 bool
771 dict_try_rename_var (struct dictionary *d, struct variable *v,
772                      const char *new_name)
773 {
774   struct variable *conflict = dict_lookup_var (d, new_name);
775   if (conflict && v != conflict)
776     return false;
777
778   struct variable *old = var_clone (v);
779   unindex_var (d, var_get_vardict (v));
780   rename_var (v, new_name);
781   reindex_var (d, var_get_vardict (v));
782
783   if (settings_get_algorithm () == ENHANCED)
784     var_clear_short_names (v);
785
786   if ( d->changed ) d->changed (d, d->changed_data);
787   if ( d->callbacks &&  d->callbacks->var_changed )
788     d->callbacks->var_changed (d, var_get_dict_index (v), VAR_TRAIT_NAME, old, d->cb_data);
789
790   var_destroy (old);
791
792   return true;
793 }
794
795 /* Changes the name of V in D to name NEW_NAME.  Assert-fails if
796    a variable named NEW_NAME is already in D, except that
797    NEW_NAME may be the same as V's existing name. */
798 void
799 dict_rename_var (struct dictionary *d, struct variable *v,
800                  const char *new_name)
801 {
802   bool ok UNUSED = dict_try_rename_var (d, v, new_name);
803   assert (ok);
804 }
805
806 /* Renames COUNT variables specified in VARS to the names given
807    in NEW_NAMES within dictionary D.  If the renaming would
808    result in a duplicate variable name, returns false and stores a
809    name that would be duplicated into *ERR_NAME (if ERR_NAME is
810    non-null).  Otherwise, the renaming is successful, and true
811    is returned. */
812 bool
813 dict_rename_vars (struct dictionary *d,
814                   struct variable **vars, char **new_names, size_t count,
815                   char **err_name)
816 {
817   struct pool *pool;
818   char **old_names;
819   size_t i;
820
821   assert (count == 0 || vars != NULL);
822   assert (count == 0 || new_names != NULL);
823
824   /* Save the names of the variables to be renamed. */
825   pool = pool_create ();
826   old_names = pool_nalloc (pool, count, sizeof *old_names);
827   for (i = 0; i < count; i++)
828     old_names[i] = pool_strdup (pool, var_get_name (vars[i]));
829
830   /* Remove the variables to be renamed from the name hash,
831      and rename them. */
832   for (i = 0; i < count; i++)
833     {
834       unindex_var (d, var_get_vardict (vars[i]));
835       rename_var (vars[i], new_names[i]);
836     }
837
838   /* Add the renamed variables back into the name hash,
839      checking for conflicts. */
840   for (i = 0; i < count; i++)
841     {
842       if (dict_lookup_var (d, var_get_name (vars[i])) != NULL)
843         {
844           /* There is a name conflict.
845              Back out all the name changes that have already
846              taken place, and indicate failure. */
847           size_t fail_idx = i;
848           if (err_name != NULL)
849             *err_name = new_names[i];
850
851           for (i = 0; i < fail_idx; i++)
852             unindex_var (d, var_get_vardict (vars[i]));
853
854           for (i = 0; i < count; i++)
855             {
856               rename_var (vars[i], old_names[i]);
857               reindex_var (d, var_get_vardict (vars[i]));
858             }
859
860           pool_destroy (pool);
861           return false;
862         }
863       reindex_var (d, var_get_vardict (vars[i]));
864     }
865
866   /* Clear short names. */
867   if (settings_get_algorithm () == ENHANCED)
868     for (i = 0; i < count; i++)
869       var_clear_short_names (vars[i]);
870
871   pool_destroy (pool);
872   return true;
873 }
874
875 /* Returns true if a variable named NAME may be inserted in DICT;
876    that is, if there is not already a variable with that name in
877    DICT and if NAME is not a reserved word.  (The caller's checks
878    have already verified that NAME is otherwise acceptable as a
879    variable name.) */
880 static bool
881 var_name_is_insertable (const struct dictionary *dict, const char *name)
882 {
883   return (dict_lookup_var (dict, name) == NULL
884           && lex_id_to_token (ss_cstr (name)) == T_ID);
885 }
886
887 static char *
888 make_hinted_name (const struct dictionary *dict, const char *hint)
889 {
890   size_t hint_len = strlen (hint);
891   bool dropped = false;
892   char *root, *rp;
893   size_t ofs;
894   int mblen;
895
896   /* The allocation size here is OK: characters that are copied directly fit
897      OK, and characters that are not copied directly are replaced by a single
898      '_' byte.  If u8_mbtouc() replaces bad input by 0xfffd, then that will get
899      replaced by '_' too.  */
900   root = rp = xmalloc (hint_len + 1);
901   for (ofs = 0; ofs < hint_len; ofs += mblen)
902     {
903       ucs4_t uc;
904
905       mblen = u8_mbtouc (&uc, CHAR_CAST (const uint8_t *, hint + ofs),
906                          hint_len - ofs);
907       if (rp == root
908           ? lex_uc_is_id1 (uc) && uc != '$'
909           : lex_uc_is_idn (uc))
910         {
911           if (dropped)
912             {
913               *rp++ = '_';
914               dropped = false;
915             }
916           rp += u8_uctomb (CHAR_CAST (uint8_t *, rp), uc, 6);
917         }
918       else if (rp != root)
919         dropped = true;
920     }
921   *rp = '\0';
922
923   if (root[0] != '\0')
924     {
925       unsigned long int i;
926
927       if (var_name_is_insertable (dict, root))
928         return root;
929
930       for (i = 0; i < ULONG_MAX; i++)
931         {
932           char suffix[INT_BUFSIZE_BOUND (i) + 1];
933           char *name;
934
935           suffix[0] = '_';
936           if (!str_format_26adic (i + 1, true, &suffix[1], sizeof suffix - 1))
937             NOT_REACHED ();
938
939           name = utf8_encoding_concat (root, suffix, dict->encoding, 64);
940           if (var_name_is_insertable (dict, name))
941             {
942               free (root);
943               return name;
944             }
945           free (name);
946         }
947     }
948
949   free (root);
950
951   return NULL;
952 }
953
954 static char *
955 make_numeric_name (const struct dictionary *dict, unsigned long int *num_start)
956 {
957   unsigned long int number;
958
959   for (number = num_start != NULL ? MAX (*num_start, 1) : 1;
960        number < ULONG_MAX;
961        number++)
962     {
963       char name[3 + INT_STRLEN_BOUND (number) + 1];
964
965       sprintf (name, "VAR%03lu", number);
966       if (dict_lookup_var (dict, name) == NULL)
967         {
968           if (num_start != NULL)
969             *num_start = number + 1;
970           return xstrdup (name);
971         }
972     }
973
974   NOT_REACHED ();
975 }
976
977
978 /* Devises and returns a variable name unique within DICT.  The variable name
979    is owned by the caller, which must free it with free() when it is no longer
980    needed.
981
982    HINT, if it is non-null, is used as a suggestion that will be
983    modified for suitability as a variable name and for
984    uniqueness.
985
986    If HINT is null or entirely unsuitable, a name in the form
987    "VAR%03d" will be generated, where the smallest unused integer
988    value is used.  If NUM_START is non-null, then its value is
989    used as the minimum numeric value to check, and it is updated
990    to the next value to be checked.
991 */
992 char *
993 dict_make_unique_var_name (const struct dictionary *dict, const char *hint,
994                            unsigned long int *num_start)
995 {
996   if (hint != NULL)
997     {
998       char *hinted_name = make_hinted_name (dict, hint);
999       if (hinted_name != NULL)
1000         return hinted_name;
1001     }
1002   return make_numeric_name (dict, num_start);
1003 }
1004
1005 /* Returns whether variable names must be valid identifiers.  Normally, this is
1006    true, but sometimes a dictionary is prepared for external use (e.g. output
1007    to a CSV file) where names don't have to be valid. */
1008 bool
1009 dict_get_names_must_be_ids (const struct dictionary *d)
1010 {
1011   return d->names_must_be_ids;
1012 }
1013
1014 /* Sets whether variable names must be valid identifiers.  Normally, this is
1015    true, but sometimes a dictionary is prepared for external use (e.g. output
1016    to a CSV file) where names don't have to be valid.
1017
1018    Changing this setting from false to true doesn't make the dictionary check
1019    all the existing variable names, so it can cause an invariant violation. */
1020 void
1021 dict_set_names_must_be_ids (struct dictionary *d, bool names_must_be_ids)
1022 {
1023   d->names_must_be_ids = names_must_be_ids;
1024 }
1025
1026 /* Returns the weighting variable in dictionary D, or a null
1027    pointer if the dictionary is unweighted. */
1028 struct variable *
1029 dict_get_weight (const struct dictionary *d)
1030 {
1031   assert (d->weight == NULL || dict_contains_var (d, d->weight));
1032
1033   return d->weight;
1034 }
1035
1036 /* Returns the value of D's weighting variable in case C, except
1037    that a negative weight is returned as 0.  Returns 1 if the
1038    dictionary is unweighted.  Will warn about missing, negative,
1039    or zero values if *WARN_ON_INVALID is true.  The function will
1040    set *WARN_ON_INVALID to false if an invalid weight is
1041    found. */
1042 double
1043 dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
1044                       bool *warn_on_invalid)
1045 {
1046   assert (c != NULL);
1047
1048   if (d->weight == NULL)
1049     return 1.0;
1050   else
1051     {
1052       double w = case_num (c, d->weight);
1053
1054       return var_force_valid_weight (d->weight, w, warn_on_invalid);
1055     }
1056 }
1057
1058 /* Sets the weighting variable of D to V, or turning off
1059    weighting if V is a null pointer. */
1060 void
1061 dict_set_weight (struct dictionary *d, struct variable *v)
1062 {
1063   assert (v == NULL || dict_contains_var (d, v));
1064   assert (v == NULL || var_is_numeric (v));
1065
1066   d->weight = v;
1067
1068   if (d->changed) d->changed (d, d->changed_data);
1069   if ( d->callbacks &&  d->callbacks->weight_changed )
1070     d->callbacks->weight_changed (d,
1071                                   v ? var_get_dict_index (v) : -1,
1072                                   d->cb_data);
1073 }
1074
1075 /* Returns the filter variable in dictionary D (see cmd_filter())
1076    or a null pointer if the dictionary is unfiltered. */
1077 struct variable *
1078 dict_get_filter (const struct dictionary *d)
1079 {
1080   assert (d->filter == NULL || dict_contains_var (d, d->filter));
1081
1082   return d->filter;
1083 }
1084
1085 /* Sets V as the filter variable for dictionary D.  Passing a
1086    null pointer for V turn off filtering. */
1087 void
1088 dict_set_filter (struct dictionary *d, struct variable *v)
1089 {
1090   assert (v == NULL || dict_contains_var (d, v));
1091   assert (v == NULL || var_is_numeric (v));
1092
1093   d->filter = v;
1094
1095   if (d->changed) d->changed (d, d->changed_data);
1096   if ( d->callbacks && d->callbacks->filter_changed )
1097     d->callbacks->filter_changed (d,
1098                                   v ? var_get_dict_index (v) : -1,
1099                                   d->cb_data);
1100 }
1101
1102 /* Returns the case limit for dictionary D, or zero if the number
1103    of cases is unlimited. */
1104 casenumber
1105 dict_get_case_limit (const struct dictionary *d)
1106 {
1107   return d->case_limit;
1108 }
1109
1110 /* Sets CASE_LIMIT as the case limit for dictionary D.  Use
1111    0 for CASE_LIMIT to indicate no limit. */
1112 void
1113 dict_set_case_limit (struct dictionary *d, casenumber case_limit)
1114 {
1115   d->case_limit = case_limit;
1116 }
1117
1118 /* Returns the prototype used for cases created by dictionary D. */
1119 const struct caseproto *
1120 dict_get_proto (const struct dictionary *d_)
1121 {
1122   struct dictionary *d = CONST_CAST (struct dictionary *, d_);
1123   if (d->proto == NULL)
1124     {
1125       size_t i;
1126
1127       d->proto = caseproto_create ();
1128       d->proto = caseproto_reserve (d->proto, d->var_cnt);
1129       for (i = 0; i < d->var_cnt; i++)
1130         d->proto = caseproto_set_width (d->proto,
1131                                         var_get_case_index (d->var[i].var),
1132                                         var_get_width (d->var[i].var));
1133     }
1134   return d->proto;
1135 }
1136
1137 /* Returns the case index of the next value to be added to D.
1138    This value is the number of `union value's that need to be
1139    allocated to store a case for dictionary D. */
1140 int
1141 dict_get_next_value_idx (const struct dictionary *d)
1142 {
1143   return d->next_value_idx;
1144 }
1145
1146 /* Returns the number of bytes needed to store a case for
1147    dictionary D. */
1148 size_t
1149 dict_get_case_size (const struct dictionary *d)
1150 {
1151   return sizeof (union value) * dict_get_next_value_idx (d);
1152 }
1153
1154 /* Reassigns values in dictionary D so that fragmentation is
1155    eliminated. */
1156 void
1157 dict_compact_values (struct dictionary *d)
1158 {
1159   size_t i;
1160
1161   d->next_value_idx = 0;
1162   for (i = 0; i < d->var_cnt; i++)
1163     {
1164       struct variable *v = d->var[i].var;
1165       set_var_case_index (v, d->next_value_idx++);
1166     }
1167   invalidate_proto (d);
1168 }
1169
1170 /* Returns the number of values occupied by the variables in
1171    dictionary D.  All variables are considered if EXCLUDE_CLASSES
1172    is 0, or it may contain one or more of (1u << DC_ORDINARY),
1173    (1u << DC_SYSTEM), or (1u << DC_SCRATCH) to exclude the
1174    corresponding type of variable.
1175
1176    The return value may be less than the number of values in one
1177    of dictionary D's cases (as returned by
1178    dict_get_next_value_idx) even if E is 0, because there may be
1179    gaps in D's cases due to deleted variables. */
1180 size_t
1181 dict_count_values (const struct dictionary *d, unsigned int exclude_classes)
1182 {
1183   size_t i;
1184   size_t cnt;
1185
1186   assert ((exclude_classes & ~((1u << DC_ORDINARY)
1187                                | (1u << DC_SYSTEM)
1188                                | (1u << DC_SCRATCH))) == 0);
1189
1190   cnt = 0;
1191   for (i = 0; i < d->var_cnt; i++)
1192     {
1193       enum dict_class class = var_get_dict_class (d->var[i].var);
1194       if (!(exclude_classes & (1u << class)))
1195         cnt++;
1196     }
1197   return cnt;
1198 }
1199
1200 /* Returns the case prototype that would result after deleting
1201    all variables from D that are not in one of the
1202    EXCLUDE_CLASSES and compacting the dictionary with
1203    dict_compact().
1204
1205    The caller must unref the returned caseproto when it is no
1206    longer needed. */
1207 struct caseproto *
1208 dict_get_compacted_proto (const struct dictionary *d,
1209                           unsigned int exclude_classes)
1210 {
1211   struct caseproto *proto;
1212   size_t i;
1213
1214   assert ((exclude_classes & ~((1u << DC_ORDINARY)
1215                                | (1u << DC_SYSTEM)
1216                                | (1u << DC_SCRATCH))) == 0);
1217
1218   proto = caseproto_create ();
1219   for (i = 0; i < d->var_cnt; i++)
1220     {
1221       struct variable *v = d->var[i].var;
1222       if (!(exclude_classes & (1u << var_get_dict_class (v))))
1223         proto = caseproto_add_width (proto, var_get_width (v));
1224     }
1225   return proto;
1226 }
1227 \f
1228 /* Returns the SPLIT FILE vars (see cmd_split_file()).  Call
1229    dict_get_split_cnt() to determine how many SPLIT FILE vars
1230    there are.  Returns a null pointer if and only if there are no
1231    SPLIT FILE vars. */
1232 const struct variable *const *
1233 dict_get_split_vars (const struct dictionary *d)
1234 {
1235   return d->split;
1236 }
1237
1238 /* Returns the number of SPLIT FILE vars. */
1239 size_t
1240 dict_get_split_cnt (const struct dictionary *d)
1241 {
1242   return d->split_cnt;
1243 }
1244
1245 /* Removes variable V, which must be in D, from D's set of split
1246    variables. */
1247 static void
1248 dict_unset_split_var (struct dictionary *d, struct variable *v)
1249 {
1250   int orig_count;
1251
1252   assert (dict_contains_var (d, v));
1253
1254   orig_count = d->split_cnt;
1255   d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
1256                                &v, compare_var_ptrs, NULL);
1257   if (orig_count != d->split_cnt)
1258     {
1259       if (d->changed) d->changed (d, d->changed_data);
1260       /* We changed the set of split variables so invoke the
1261          callback. */
1262       if (d->callbacks &&  d->callbacks->split_changed)
1263         d->callbacks->split_changed (d, d->cb_data);
1264     }
1265 }
1266
1267 /* Sets CNT split vars SPLIT in dictionary D. */
1268 void
1269 dict_set_split_vars (struct dictionary *d,
1270                      struct variable *const *split, size_t cnt)
1271 {
1272   assert (cnt == 0 || split != NULL);
1273
1274   d->split_cnt = cnt;
1275   if ( cnt > 0 )
1276    {
1277     d->split = xnrealloc (d->split, cnt, sizeof *d->split) ;
1278     memcpy (d->split, split, cnt * sizeof *d->split);
1279    }
1280   else
1281    {
1282     free (d->split);
1283     d->split = NULL;
1284    }
1285
1286   if (d->changed) d->changed (d, d->changed_data);
1287   if ( d->callbacks &&  d->callbacks->split_changed )
1288     d->callbacks->split_changed (d, d->cb_data);
1289 }
1290
1291 /* Returns the file label for D, or a null pointer if D is
1292    unlabeled (see cmd_file_label()). */
1293 const char *
1294 dict_get_label (const struct dictionary *d)
1295 {
1296   return d->label;
1297 }
1298
1299 /* Sets D's file label to LABEL, truncating it to at most 60 bytes in D's
1300    encoding.
1301
1302    Removes D's label if LABEL is null or the empty string. */
1303 void
1304 dict_set_label (struct dictionary *d, const char *label)
1305 {
1306   free (d->label);
1307   if (label == NULL || label[0] == '\0')
1308     d->label = NULL;
1309   else
1310     d->label = utf8_encoding_trunc (label, d->encoding, 60);
1311 }
1312
1313 /* Returns the documents for D, as an UTF-8 encoded string_array.  The
1314    return value is always nonnull; if there are no documents then the
1315    string_arary is empty.*/
1316 const struct string_array *
1317 dict_get_documents (const struct dictionary *d)
1318 {
1319   return &d->documents;
1320 }
1321
1322 /* Replaces the documents for D by NEW_DOCS, a UTF-8 encoded string_array. */
1323 void
1324 dict_set_documents (struct dictionary *d, const struct string_array *new_docs)
1325 {
1326   size_t i;
1327
1328   dict_clear_documents (d);
1329
1330   for (i = 0; i < new_docs->n; i++)
1331     dict_add_document_line (d, new_docs->strings[i], false);
1332 }
1333
1334 /* Replaces the documents for D by UTF-8 encoded string NEW_DOCS, dividing it
1335    into individual lines at new-line characters.  Each line is truncated to at
1336    most DOC_LINE_LENGTH bytes in D's encoding. */
1337 void
1338 dict_set_documents_string (struct dictionary *d, const char *new_docs)
1339 {
1340   const char *s;
1341
1342   dict_clear_documents (d);
1343   for (s = new_docs; *s != '\0'; )
1344     {
1345       size_t len = strcspn (s, "\n");
1346       char *line = xmemdup0 (s, len);
1347       dict_add_document_line (d, line, false);
1348       free (line);
1349
1350       s += len;
1351       if (*s == '\n')
1352         s++;
1353     }
1354 }
1355
1356 /* Drops the documents from dictionary D. */
1357 void
1358 dict_clear_documents (struct dictionary *d)
1359 {
1360   string_array_clear (&d->documents);
1361 }
1362
1363 /* Appends the UTF-8 encoded LINE to the documents in D.  LINE will be
1364    truncated so that it is no more than 80 bytes in the dictionary's
1365    encoding.  If this causes some text to be lost, and ISSUE_WARNING is true,
1366    then a warning will be issued. */
1367 bool
1368 dict_add_document_line (struct dictionary *d, const char *line,
1369                         bool issue_warning)
1370 {
1371   size_t trunc_len;
1372   bool truncated;
1373
1374   trunc_len = utf8_encoding_trunc_len (line, d->encoding, DOC_LINE_LENGTH);
1375   truncated = line[trunc_len] != '\0';
1376   if (truncated && issue_warning)
1377     {
1378       /* Note to translators: "bytes" is correct, not characters */
1379       msg (SW, _("Truncating document line to %d bytes."), DOC_LINE_LENGTH);
1380     }
1381
1382   string_array_append_nocopy (&d->documents, xmemdup0 (line, trunc_len));
1383
1384   return !truncated;
1385 }
1386
1387 /* Returns the number of document lines in dictionary D. */
1388 size_t
1389 dict_get_document_line_cnt (const struct dictionary *d)
1390 {
1391   return d->documents.n;
1392 }
1393
1394 /* Returns document line number IDX in dictionary D.  The caller must not
1395    modify or free the returned string. */
1396 const char *
1397 dict_get_document_line (const struct dictionary *d, size_t idx)
1398 {
1399   assert (idx < d->documents.n);
1400   return d->documents.strings[idx];
1401 }
1402
1403 /* Creates in D a vector named NAME that contains the CNT
1404    variables in VAR.  Returns true if successful, or false if a
1405    vector named NAME already exists in D. */
1406 bool
1407 dict_create_vector (struct dictionary *d,
1408                     const char *name,
1409                     struct variable **var, size_t cnt)
1410 {
1411   size_t i;
1412
1413   assert (cnt > 0);
1414   for (i = 0; i < cnt; i++)
1415     assert (dict_contains_var (d, var[i]));
1416
1417   if (dict_lookup_vector (d, name) == NULL)
1418     {
1419       d->vector = xnrealloc (d->vector, d->vector_cnt + 1, sizeof *d->vector);
1420       d->vector[d->vector_cnt++] = vector_create (name, var, cnt);
1421       return true;
1422     }
1423   else
1424     return false;
1425 }
1426
1427 /* Creates in D a vector named NAME that contains the CNT
1428    variables in VAR.  A vector named NAME must not already exist
1429    in D. */
1430 void
1431 dict_create_vector_assert (struct dictionary *d,
1432                            const char *name,
1433                            struct variable **var, size_t cnt)
1434 {
1435   assert (dict_lookup_vector (d, name) == NULL);
1436   dict_create_vector (d, name, var, cnt);
1437 }
1438
1439 /* Returns the vector in D with index IDX, which must be less
1440    than dict_get_vector_cnt (D). */
1441 const struct vector *
1442 dict_get_vector (const struct dictionary *d, size_t idx)
1443 {
1444   assert (idx < d->vector_cnt);
1445
1446   return d->vector[idx];
1447 }
1448
1449 /* Returns the number of vectors in D. */
1450 size_t
1451 dict_get_vector_cnt (const struct dictionary *d)
1452 {
1453   return d->vector_cnt;
1454 }
1455
1456 /* Looks up and returns the vector within D with the given
1457    NAME. */
1458 const struct vector *
1459 dict_lookup_vector (const struct dictionary *d, const char *name)
1460 {
1461   size_t i;
1462   for (i = 0; i < d->vector_cnt; i++)
1463     if (!utf8_strcasecmp (vector_get_name (d->vector[i]), name))
1464       return d->vector[i];
1465   return NULL;
1466 }
1467
1468 /* Deletes all vectors from D. */
1469 void
1470 dict_clear_vectors (struct dictionary *d)
1471 {
1472   size_t i;
1473
1474   for (i = 0; i < d->vector_cnt; i++)
1475     vector_destroy (d->vector[i]);
1476   free (d->vector);
1477
1478   d->vector = NULL;
1479   d->vector_cnt = 0;
1480 }
1481 \f
1482 /* Multiple response sets. */
1483
1484 /* Returns the multiple response set in DICT with index IDX, which must be
1485    between 0 and the count returned by dict_get_n_mrsets(), exclusive. */
1486 const struct mrset *
1487 dict_get_mrset (const struct dictionary *dict, size_t idx)
1488 {
1489   assert (idx < dict->n_mrsets);
1490   return dict->mrsets[idx];
1491 }
1492
1493 /* Returns the number of multiple response sets in DICT. */
1494 size_t
1495 dict_get_n_mrsets (const struct dictionary *dict)
1496 {
1497   return dict->n_mrsets;
1498 }
1499
1500 /* Looks for a multiple response set named NAME in DICT.  If it finds one,
1501    returns its index; otherwise, returns SIZE_MAX. */
1502 static size_t
1503 dict_lookup_mrset_idx (const struct dictionary *dict, const char *name)
1504 {
1505   size_t i;
1506
1507   for (i = 0; i < dict->n_mrsets; i++)
1508     if (!utf8_strcasecmp (name, dict->mrsets[i]->name))
1509       return i;
1510
1511   return SIZE_MAX;
1512 }
1513
1514 /* Looks for a multiple response set named NAME in DICT.  If it finds one,
1515    returns it; otherwise, returns NULL. */
1516 const struct mrset *
1517 dict_lookup_mrset (const struct dictionary *dict, const char *name)
1518 {
1519   size_t idx = dict_lookup_mrset_idx (dict, name);
1520   return idx != SIZE_MAX ? dict->mrsets[idx] : NULL;
1521 }
1522
1523 /* Adds MRSET to DICT, replacing any existing set with the same name.  Returns
1524    true if a set was replaced, false if none existed with the specified name.
1525
1526    Ownership of MRSET is transferred to DICT. */
1527 bool
1528 dict_add_mrset (struct dictionary *dict, struct mrset *mrset)
1529 {
1530   size_t idx;
1531
1532   assert (mrset_ok (mrset, dict));
1533
1534   idx = dict_lookup_mrset_idx (dict, mrset->name);
1535   if (idx == SIZE_MAX)
1536     {
1537       dict->mrsets = xrealloc (dict->mrsets,
1538                                (dict->n_mrsets + 1) * sizeof *dict->mrsets);
1539       dict->mrsets[dict->n_mrsets++] = mrset;
1540       return true;
1541     }
1542   else
1543     {
1544       mrset_destroy (dict->mrsets[idx]);
1545       dict->mrsets[idx] = mrset;
1546       return false;
1547     }
1548 }
1549
1550 /* Looks for a multiple response set in DICT named NAME.  If found, removes it
1551    from DICT and returns true.  If none is found, returns false without
1552    modifying DICT.
1553
1554    Deleting one multiple response set causes the indexes of other sets within
1555    DICT to change. */
1556 bool
1557 dict_delete_mrset (struct dictionary *dict, const char *name)
1558 {
1559   size_t idx = dict_lookup_mrset_idx (dict, name);
1560   if (idx != SIZE_MAX)
1561     {
1562       mrset_destroy (dict->mrsets[idx]);
1563       dict->mrsets[idx] = dict->mrsets[--dict->n_mrsets];
1564       return true;
1565     }
1566   else
1567     return false;
1568 }
1569
1570 /* Deletes all multiple response sets from DICT. */
1571 void
1572 dict_clear_mrsets (struct dictionary *dict)
1573 {
1574   size_t i;
1575
1576   for (i = 0; i < dict->n_mrsets; i++)
1577     mrset_destroy (dict->mrsets[i]);
1578   free (dict->mrsets);
1579   dict->mrsets = NULL;
1580   dict->n_mrsets = 0;
1581 }
1582
1583 /* Removes VAR, which must be in DICT, from DICT's multiple response sets. */
1584 static void
1585 dict_unset_mrset_var (struct dictionary *dict, struct variable *var)
1586 {
1587   size_t i;
1588
1589   assert (dict_contains_var (dict, var));
1590
1591   for (i = 0; i < dict->n_mrsets; )
1592     {
1593       struct mrset *mrset = dict->mrsets[i];
1594       size_t j;
1595
1596       for (j = 0; j < mrset->n_vars; )
1597         if (mrset->vars[j] == var)
1598           remove_element (mrset->vars, mrset->n_vars--,
1599                           sizeof *mrset->vars, j);
1600         else
1601           j++;
1602
1603       if (mrset->n_vars < 2)
1604         {
1605           mrset_destroy (mrset);
1606           dict->mrsets[i] = dict->mrsets[--dict->n_mrsets];
1607         }
1608       else
1609         i++;
1610     }
1611 }
1612 \f
1613 /* Returns D's attribute set.  The caller may examine or modify
1614    the attribute set, but must not destroy it.  Destroying D or
1615    calling dict_set_attributes for D will also destroy D's
1616    attribute set. */
1617 struct attrset *
1618 dict_get_attributes (const struct dictionary *d)
1619 {
1620   return CONST_CAST (struct attrset *, &d->attributes);
1621 }
1622
1623 /* Replaces D's attributes set by a copy of ATTRS. */
1624 void
1625 dict_set_attributes (struct dictionary *d, const struct attrset *attrs)
1626 {
1627   attrset_destroy (&d->attributes);
1628   attrset_clone (&d->attributes, attrs);
1629 }
1630
1631 /* Returns true if D has at least one attribute in its attribute
1632    set, false if D's attribute set is empty. */
1633 bool
1634 dict_has_attributes (const struct dictionary *d)
1635 {
1636   return attrset_count (&d->attributes) > 0;
1637 }
1638
1639 /* Called from variable.c to notify the dictionary that some property (indicated
1640    by WHAT) of the variable has changed.  OLDVAR is a copy of V as it existed
1641    prior to the change.  OLDVAR is destroyed by this function.
1642 */
1643 void
1644 dict_var_changed (const struct variable *v, unsigned int what, struct variable *oldvar)
1645 {
1646   if ( var_has_vardict (v))
1647     {
1648       const struct vardict_info *vardict = var_get_vardict (v);
1649       struct dictionary *d = vardict->dict;
1650
1651       if ( NULL == d)
1652         return;
1653
1654       if (d->changed ) d->changed (d, d->changed_data);
1655       if ( d->callbacks && d->callbacks->var_changed )
1656         d->callbacks->var_changed (d, var_get_dict_index (v), what, oldvar, d->cb_data);
1657     }
1658   var_destroy (oldvar);
1659 }
1660
1661
1662 \f
1663 /* Dictionary used to contain "internal variables". */
1664 static struct dictionary *internal_dict;
1665
1666 /* Create a variable of the specified WIDTH to be used for internal
1667    calculations only.  The variable is assigned case index CASE_IDX. */
1668 struct variable *
1669 dict_create_internal_var (int case_idx, int width)
1670 {
1671   if (internal_dict == NULL)
1672     internal_dict = dict_create ("UTF-8");
1673
1674   for (;;)
1675     {
1676       static int counter = INT_MAX / 2;
1677       struct variable *var;
1678       char name[64];
1679
1680       if (++counter == INT_MAX)
1681         counter = INT_MAX / 2;
1682
1683       sprintf (name, "$internal%d", counter);
1684       var = dict_create_var (internal_dict, name, width);
1685       if (var != NULL)
1686         {
1687           set_var_case_index (var, case_idx);
1688           return var;
1689         }
1690     }
1691 }
1692
1693 /* Destroys VAR, which must have been created with
1694    dict_create_internal_var(). */
1695 void
1696 dict_destroy_internal_var (struct variable *var)
1697 {
1698   if (var != NULL)
1699     {
1700       dict_delete_var (internal_dict, var);
1701
1702       /* Destroy internal_dict if it has no variables left, just so that
1703          valgrind --leak-check --show-reachable won't show internal_dict. */
1704       if (dict_get_var_cnt (internal_dict) == 0)
1705         {
1706           dict_destroy (internal_dict);
1707           internal_dict = NULL;
1708         }
1709     }
1710 }
1711 \f
1712 int
1713 vardict_get_dict_index (const struct vardict_info *vardict)
1714 {
1715   return vardict - vardict->dict->var;
1716 }