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