39001d89413f2a67b4972a70f156ad769171adf5
[pspp-builds.git] / src / data / dictionary.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    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, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301, USA. */
19
20 #include <config.h>
21
22 #include "dictionary.h"
23
24 #include <stdlib.h>
25 #include <ctype.h>
26
27 #include "case.h"
28 #include "cat-routines.h"
29 #include "category.h"
30 #include "settings.h"
31 #include "value-labels.h"
32 #include "variable.h"
33 #include <libpspp/alloc.h>
34 #include <libpspp/array.h>
35 #include <libpspp/compiler.h>
36 #include <libpspp/hash.h>
37 #include <libpspp/message.h>
38 #include <libpspp/misc.h>
39 #include <libpspp/str.h>
40
41 #include "minmax.h"
42
43 #include "gettext.h"
44 #define _(msgid) gettext (msgid)
45
46 /* A dictionary. */
47 struct dictionary
48   {
49     struct variable **var;      /* Variables. */
50     size_t var_cnt, var_cap;    /* Number of variables, capacity. */
51     struct hsh_table *name_tab; /* Variable index by name. */
52     int next_value_idx;         /* Index of next `union value' to allocate. */
53     struct variable **split;    /* SPLIT FILE vars. */
54     size_t split_cnt;           /* SPLIT FILE count. */
55     struct variable *weight;    /* WEIGHT variable. */
56     struct variable *filter;    /* FILTER variable. */
57     size_t case_limit;          /* Current case limit (N command). */
58     char *label;                /* File label. */
59     char *documents;            /* Documents, as a string. */
60     struct vector **vector;     /* Vectors of variables. */
61     size_t vector_cnt;          /* Number of vectors. */
62   };
63
64 /* Creates and returns a new dictionary. */
65 struct dictionary *
66 dict_create (void) 
67 {
68   struct dictionary *d = xmalloc (sizeof *d);
69   
70   d->var = NULL;
71   d->var_cnt = d->var_cap = 0;
72   d->name_tab = hsh_create (8, compare_var_names, hash_var_name, NULL, NULL);
73   d->next_value_idx = 0;
74   d->split = NULL;
75   d->split_cnt = 0;
76   d->weight = NULL;
77   d->filter = NULL;
78   d->case_limit = 0;
79   d->label = NULL;
80   d->documents = NULL;
81   d->vector = NULL;
82   d->vector_cnt = 0;
83
84   return d;
85 }
86
87 /* Creates and returns a (deep) copy of an existing
88    dictionary. */
89 struct dictionary *
90 dict_clone (const struct dictionary *s) 
91 {
92   struct dictionary *d;
93   size_t i;
94
95   assert (s != NULL);
96
97   d = dict_create ();
98
99   for (i = 0; i < s->var_cnt; i++) 
100     {
101       struct variable *sv = s->var[i];
102       struct variable *dv = dict_clone_var_assert (d, sv, sv->name);
103       var_set_short_name (dv, sv->short_name);
104     }
105
106   d->next_value_idx = s->next_value_idx;
107
108   d->split_cnt = s->split_cnt;
109   if (d->split_cnt > 0) 
110     {
111       d->split = xnmalloc (d->split_cnt, sizeof *d->split);
112       for (i = 0; i < d->split_cnt; i++) 
113         d->split[i] = dict_lookup_var_assert (d, s->split[i]->name);
114     }
115
116   if (s->weight != NULL) 
117     d->weight = dict_lookup_var_assert (d, s->weight->name);
118
119   if (s->filter != NULL) 
120     d->filter = dict_lookup_var_assert (d, s->filter->name);
121
122   d->case_limit = s->case_limit;
123   dict_set_label (d, dict_get_label (s));
124   dict_set_documents (d, dict_get_documents (s));
125
126   d->vector_cnt = s->vector_cnt;
127   d->vector = xnmalloc (d->vector_cnt, sizeof *d->vector);
128   for (i = 0; i < s->vector_cnt; i++) 
129     {
130       struct vector *sv = s->vector[i];
131       struct vector *dv = d->vector[i] = xmalloc (sizeof *dv);
132       int j;
133       
134       dv->idx = i;
135       strcpy (dv->name, sv->name);
136       dv->cnt = sv->cnt;
137       dv->var = xnmalloc (dv->cnt, sizeof *dv->var);
138       for (j = 0; j < dv->cnt; j++)
139         dv->var[j] = d->var[sv->var[j]->index];
140     }
141
142   return d;
143 }
144
145 /* Clears the contents from a dictionary without destroying the
146    dictionary itself. */
147 void
148 dict_clear (struct dictionary *d) 
149 {
150   /* FIXME?  Should we really clear case_limit, label, documents?
151      Others are necessarily cleared by deleting all the variables.*/
152   int i;
153
154   assert (d != NULL);
155
156   for (i = 0; i < d->var_cnt; i++) 
157     {
158       struct variable *v = d->var[i];
159       var_clear_aux (v);
160       val_labs_destroy (v->val_labs);
161       free (v->label);
162       free (v); 
163     }
164   free (d->var);
165   d->var = NULL;
166   d->var_cnt = d->var_cap = 0;
167   hsh_clear (d->name_tab);
168   d->next_value_idx = 0;
169   free (d->split);
170   d->split = NULL;
171   d->split_cnt = 0;
172   d->weight = NULL;
173   d->filter = NULL;
174   d->case_limit = 0;
175   free (d->label);
176   d->label = NULL;
177   free (d->documents);
178   d->documents = NULL;
179   dict_clear_vectors (d);
180 }
181
182 /* Destroys the aux data for every variable in D, by calling
183    var_clear_aux() for each variable. */
184 void
185 dict_clear_aux (struct dictionary *d) 
186 {
187   int i;
188   
189   assert (d != NULL);
190   
191   for (i = 0; i < d->var_cnt; i++)
192     var_clear_aux (d->var[i]);
193 }
194
195 /* Clears a dictionary and destroys it. */
196 void
197 dict_destroy (struct dictionary *d)
198 {
199   if (d != NULL) 
200     {
201       dict_clear (d);
202       hsh_destroy (d->name_tab);
203       free (d);
204     }
205 }
206
207 /* Returns the number of variables in D. */
208 size_t
209 dict_get_var_cnt (const struct dictionary *d) 
210 {
211   assert (d != NULL);
212
213   return d->var_cnt;
214 }
215
216 /* Returns the variable in D with index IDX, which must be
217    between 0 and the count returned by dict_get_var_cnt(),
218    exclusive. */
219 struct variable *
220 dict_get_var (const struct dictionary *d, size_t idx) 
221 {
222   assert (d != NULL);
223   assert (idx < d->var_cnt);
224
225   return d->var[idx];
226 }
227
228 /* Sets *VARS to an array of pointers to variables in D and *CNT
229    to the number of variables in *D.  All variables are returned
230    if EXCLUDE_CLASSES is 0, or it may contain one or more of (1u
231    << DC_ORDINARY), (1u << DC_SYSTEM), or (1u << DC_SCRATCH) to
232    exclude the corresponding type of variable. */
233 void
234 dict_get_vars (const struct dictionary *d, struct variable ***vars,
235                size_t *cnt, unsigned exclude_classes)
236 {
237   size_t count;
238   size_t i;
239   
240   assert (d != NULL);
241   assert (vars != NULL);
242   assert (cnt != NULL);
243   assert ((exclude_classes & ~((1u << DC_ORDINARY)
244                                | (1u << DC_SYSTEM)
245                                | (1u << DC_SCRATCH))) == 0);
246   
247   count = 0;
248   for (i = 0; i < d->var_cnt; i++)
249     if (!(exclude_classes & (1u << dict_class_from_id (d->var[i]->name))))
250       count++;
251
252   *vars = xnmalloc (count, sizeof **vars);
253   *cnt = 0;
254   for (i = 0; i < d->var_cnt; i++)
255     if (!(exclude_classes & (1u << dict_class_from_id (d->var[i]->name))))
256       (*vars)[(*cnt)++] = d->var[i];
257   assert (*cnt == count);
258 }
259
260
261 /* Creates and returns a new variable in D with the given NAME
262    and WIDTH.  Returns a null pointer if the given NAME would
263    duplicate that of an existing variable in the dictionary. */
264 struct variable *
265 dict_create_var (struct dictionary *d, const char *name, int width)
266 {
267   struct variable *v;
268
269   assert (d != NULL);
270   assert (name != NULL);
271
272   assert (width >= 0 && width <= MAX_STRING);
273
274   assert (var_is_plausible_name(name,0));
275     
276   /* Make sure there's not already a variable by that name. */
277   if (dict_lookup_var (d, name) != NULL)
278     return NULL;
279
280   /* Allocate and initialize variable. */
281   v = xmalloc (sizeof *v);
282   str_copy_trunc (v->name, sizeof v->name, name);
283   v->type = width == 0 ? NUMERIC : ALPHA;
284   v->width = width;
285   v->fv = d->next_value_idx;
286   v->nv = width == 0 ? 1 : DIV_RND_UP (width, MAX_SHORT_STRING);
287   v->leave = dict_class_from_id (v->name) == DC_SCRATCH;
288   v->index = d->var_cnt;
289   mv_init (&v->miss, width);
290   if (v->type == NUMERIC)
291     {
292       v->print = fmt_for_output (FMT_F, 8, 2);
293       v->alignment = ALIGN_RIGHT;
294       v->display_width = 8;
295       v->measure = MEASURE_SCALE;
296     }
297   else
298     {
299       v->print = fmt_for_output (FMT_A, v->width, 0);
300       v->alignment = ALIGN_LEFT;
301       v->display_width = 8;
302       v->measure = MEASURE_NOMINAL;
303     }
304   v->write = v->print;
305   v->val_labs = val_labs_create (v->width);
306   v->label = NULL;
307   var_clear_short_name (v);
308   v->aux = NULL;
309   v->aux_dtor = NULL;
310   v->obs_vals = NULL;
311
312   /* Update dictionary. */
313   if (d->var_cnt >= d->var_cap) 
314     {
315       d->var_cap = 8 + 2 * d->var_cap; 
316       d->var = xnrealloc (d->var, d->var_cap, sizeof *d->var);
317     }
318   d->var[v->index] = v;
319   d->var_cnt++;
320   hsh_force_insert (d->name_tab, v);
321
322   d->next_value_idx += v->nv;
323
324   return v;
325 }
326
327 /* Creates and returns a new variable in D with the given NAME
328    and WIDTH.  Assert-fails if the given NAME would duplicate
329    that of an existing variable in the dictionary. */
330 struct variable *
331 dict_create_var_assert (struct dictionary *d, const char *name, int width)
332 {
333   struct variable *v = dict_create_var (d, name, width);
334   assert (v != NULL);
335   return v;
336 }
337
338 /* Creates and returns a new variable in D with name NAME, as a
339    copy of existing variable OV, which need not be in D or in any
340    dictionary.  Returns a null pointer if the given NAME would
341    duplicate that of an existing variable in the dictionary. */
342 struct variable *
343 dict_clone_var (struct dictionary *d, const struct variable *ov,
344                 const char *name)
345 {
346   struct variable *nv;
347
348   assert (d != NULL);
349   assert (ov != NULL);
350   assert (name != NULL);
351
352   assert (strlen (name) >= 1);
353   assert (strlen (name) <= LONG_NAME_LEN);
354
355   nv = dict_create_var (d, name, ov->width);
356   if (nv == NULL)
357     return NULL;
358
359   /* Copy most members not copied via dict_create_var().
360      short_name[] is intentionally not copied, because there is
361      no reason to give a new variable with potentially a new name
362      the same short name. */
363   nv->leave = ov->leave;
364   mv_copy (&nv->miss, &ov->miss);
365   nv->print = ov->print;
366   nv->write = ov->write;
367   val_labs_destroy (nv->val_labs);
368   nv->val_labs = val_labs_copy (ov->val_labs);
369   if (ov->label != NULL)
370     nv->label = xstrdup (ov->label);
371   nv->measure = ov->measure;
372   nv->display_width = ov->display_width;
373   nv->alignment = ov->alignment;
374
375   return nv;
376 }
377
378 /* Creates and returns a new variable in D with name NAME, as a
379    copy of existing variable OV, which need not be in D or in any
380    dictionary.  Assert-fails if the given NAME would duplicate
381    that of an existing variable in the dictionary. */
382 struct variable *
383 dict_clone_var_assert (struct dictionary *d, const struct variable *ov,
384                        const char *name)
385 {
386   struct variable *v = dict_clone_var (d, ov, name);
387   assert (v != NULL);
388   return v;
389 }
390
391 /* Returns the variable named NAME in D, or a null pointer if no
392    variable has that name. */
393 struct variable *
394 dict_lookup_var (const struct dictionary *d, const char *name)
395 {
396   struct variable v;
397   
398   assert (d != NULL);
399   assert (name != NULL);
400
401   str_copy_trunc (v.name, sizeof v.name, name);
402   return hsh_find (d->name_tab, &v);
403 }
404
405 /* Returns the variable named NAME in D.  Assert-fails if no
406    variable has that name. */
407 struct variable *
408 dict_lookup_var_assert (const struct dictionary *d, const char *name)
409 {
410   struct variable *v = dict_lookup_var (d, name);
411   assert (v != NULL);
412   return v;
413 }
414
415 /* Returns true if variable V is in dictionary D,
416    false otherwise. */
417 bool
418 dict_contains_var (const struct dictionary *d, const struct variable *v)
419 {
420   assert (d != NULL);
421   assert (v != NULL);
422
423   return v->index >= 0 && v->index < d->var_cnt && d->var[v->index] == v;
424 }
425
426 /* Compares two double pointers to variables, which should point
427    to elements of a struct dictionary's `var' member array. */
428 static int
429 compare_var_ptrs (const void *a_, const void *b_, const void *aux UNUSED) 
430 {
431   struct variable *const *a = a_;
432   struct variable *const *b = b_;
433
434   return *a < *b ? -1 : *a > *b;
435 }
436
437 /* Deletes variable V from dictionary D and frees V.
438
439    This is a very bad idea if there might be any pointers to V
440    from outside D.  In general, no variable in should be deleted when 
441    any transformations are active on the dictionary's dataset, because
442    those transformations might reference the deleted variable.
443    The safest time to delete a variable is just after a procedure
444    has been executed, as done by MODIFY VARS.
445
446    Pointers to V within D are not a problem, because
447    dict_delete_var() knows to remove V from split variables,
448    weights, filters, etc. */
449 void
450 dict_delete_var (struct dictionary *d, struct variable *v) 
451 {
452   size_t i;
453
454   assert (d != NULL);
455   assert (v != NULL);
456   assert (dict_contains_var (d, v));
457
458   /* Delete aux data. */
459   var_clear_aux (v);
460
461   /* Remove V from splits, weight, filter variables. */
462   d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
463                                &v, compare_var_ptrs, NULL);
464   if (d->weight == v)
465     d->weight = NULL;
466   if (d->filter == v)
467     d->filter = NULL;
468   dict_clear_vectors (d);
469
470   /* Remove V from var array. */
471   remove_element (d->var, d->var_cnt, sizeof *d->var, v->index);
472   d->var_cnt--;
473
474   /* Update index. */
475   for (i = v->index; i < d->var_cnt; i++)
476     d->var[i]->index = i;
477
478   /* Update name hash. */
479   hsh_force_delete (d->name_tab, v);
480
481   /* Free memory. */
482   val_labs_destroy (v->val_labs);
483   cat_stored_values_destroy (v);
484   free (v->label);
485   free (v);
486 }
487
488 /* Deletes the COUNT variables listed in VARS from D.  This is
489    unsafe; see the comment on dict_delete_var() for details. */
490 void 
491 dict_delete_vars (struct dictionary *d,
492                   struct variable *const *vars, size_t count) 
493 {
494   /* FIXME: this can be done in O(count) time, but this algorithm
495      is O(count**2). */
496   assert (d != NULL);
497   assert (count == 0 || vars != NULL);
498
499   while (count-- > 0)
500     dict_delete_var (d, *vars++);
501 }
502
503 /* Deletes scratch variables from dictionary D. */
504 void
505 dict_delete_scratch_vars (struct dictionary *d)
506 {
507   int i;
508
509   /* FIXME: this can be done in O(count) time, but this algorithm
510      is O(count**2). */
511   assert (d != NULL);
512
513   for (i = 0; i < d->var_cnt; )
514     if (dict_class_from_id (d->var[i]->name) == DC_SCRATCH)
515       dict_delete_var (d, d->var[i]);
516     else
517       i++;
518 }
519
520 /* Moves V to 0-based position IDX in D.  Other variables in D,
521    if any, retain their relative positions.  Runs in time linear
522    in the distance moved. */
523 void
524 dict_reorder_var (struct dictionary *d, struct variable *v,
525                   size_t new_index) 
526 {
527   size_t min_idx, max_idx;
528   size_t i;
529   
530   assert (d != NULL);
531   assert (v != NULL);
532   assert (dict_contains_var (d, v));
533   assert (new_index < d->var_cnt);
534
535   move_element (d->var, d->var_cnt, sizeof *d->var, v->index, new_index);
536
537   min_idx = MIN (v->index, new_index);
538   max_idx = MAX (v->index, new_index);
539   for (i = min_idx; i <= max_idx; i++)
540     d->var[i]->index = i;
541 }
542
543 /* Reorders the variables in D, placing the COUNT variables
544    listed in ORDER in that order at the beginning of D.  The
545    other variables in D, if any, retain their relative
546    positions. */
547 void 
548 dict_reorder_vars (struct dictionary *d,
549                    struct variable *const *order, size_t count) 
550 {
551   struct variable **new_var;
552   size_t i;
553   
554   assert (d != NULL);
555   assert (count == 0 || order != NULL);
556   assert (count <= d->var_cnt);
557
558   new_var = xnmalloc (d->var_cnt, sizeof *new_var);
559   memcpy (new_var, order, count * sizeof *new_var);
560   for (i = 0; i < count; i++) 
561     {
562       assert (d->var[order[i]->index] != NULL);
563       d->var[order[i]->index] = NULL;
564       order[i]->index = i;
565     }
566   for (i = 0; i < d->var_cnt; i++)
567     if (d->var[i] != NULL)
568       {
569         assert (count < d->var_cnt);
570         new_var[count] = d->var[i];
571         new_var[count]->index = count;
572         count++;
573       }
574   free (d->var);
575   d->var = new_var;
576 }
577
578 /* Changes the name of V in D to name NEW_NAME.  Assert-fails if
579    a variable named NEW_NAME is already in D, except that
580    NEW_NAME may be the same as V's existing name. */
581 void 
582 dict_rename_var (struct dictionary *d, struct variable *v,
583                  const char *new_name) 
584 {
585   assert (d != NULL);
586   assert (v != NULL);
587   assert (new_name != NULL);
588   assert (var_is_plausible_name (new_name, false));
589   assert (dict_contains_var (d, v));
590   assert (!compare_var_names (v->name, new_name, NULL)
591           || dict_lookup_var (d, new_name) == NULL);
592
593   hsh_force_delete (d->name_tab, v);
594   str_copy_trunc (v->name, sizeof v->name, new_name);
595   hsh_force_insert (d->name_tab, v);
596
597   if (get_algorithm () == ENHANCED)
598     var_clear_short_name (v);
599 }
600
601 /* Renames COUNT variables specified in VARS to the names given
602    in NEW_NAMES within dictionary D.  If the renaming would
603    result in a duplicate variable name, returns false and stores a
604    name that would be duplicated into *ERR_NAME (if ERR_NAME is
605    non-null).  Otherwise, the renaming is successful, and true
606    is returned. */
607 bool
608 dict_rename_vars (struct dictionary *d,
609                   struct variable **vars, char **new_names,
610                   size_t count, char **err_name) 
611 {
612   char **old_names;
613   size_t i;
614   bool success = true;
615
616   assert (d != NULL);
617   assert (count == 0 || vars != NULL);
618   assert (count == 0 || new_names != NULL);
619
620   /* Remove the variables to be renamed from the name hash,
621      save their names, and rename them. */
622   old_names = xnmalloc (count, sizeof *old_names);
623   for (i = 0; i < count; i++) 
624     {
625       assert (d->var[vars[i]->index] == vars[i]);
626       assert (var_is_plausible_name (new_names[i], false));
627       hsh_force_delete (d->name_tab, vars[i]);
628       old_names[i] = xstrdup (vars[i]->name);
629       strcpy (vars[i]->name, new_names[i]);
630     }
631
632   /* Add the renamed variables back into the name hash,
633      checking for conflicts. */
634   for (i = 0; i < count; i++)
635     {
636       assert (new_names[i] != NULL);
637       assert (*new_names[i] != '\0');
638       assert (strlen (new_names[i]) >= 1);
639       assert (strlen (new_names[i]) <= LONG_NAME_LEN);
640
641       if (hsh_insert (d->name_tab, vars[i]) != NULL)
642         {
643           /* There is a name conflict.
644              Back out all the name changes that have already
645              taken place, and indicate failure. */
646           size_t fail_idx = i;
647           if (err_name != NULL) 
648             *err_name = new_names[i];
649
650           for (i = 0; i < fail_idx; i++)
651             hsh_force_delete (d->name_tab, vars[i]);
652           
653           for (i = 0; i < count; i++)
654             {
655               strcpy (vars[i]->name, old_names[i]);
656               hsh_force_insert (d->name_tab, vars[i]);
657             }
658
659           success = false;
660           goto done;
661         }
662     }
663
664   /* Clear short names. */
665   if (get_algorithm () == ENHANCED)
666     for (i = 0; i < count; i++)
667       var_clear_short_name (vars[i]);
668
669  done:
670   /* Free the old names we kept around. */
671   for (i = 0; i < count; i++)
672     free (old_names[i]);
673   free (old_names);
674
675   return success;
676 }
677
678 /* Returns the weighting variable in dictionary D, or a null
679    pointer if the dictionary is unweighted. */
680 struct variable *
681 dict_get_weight (const struct dictionary *d) 
682 {
683   assert (d != NULL);
684   assert (d->weight == NULL || dict_contains_var (d, d->weight));
685   
686   return d->weight;
687 }
688
689 /* Returns the value of D's weighting variable in case C, except that a
690    negative weight is returned as 0.  Returns 1 if the dictionary is
691    unweighted. Will warn about missing, negative, or zero values if
692    warn_on_invalid is true. The function will set warn_on_invalid to false
693    if an invalid weight is found. */
694 double
695 dict_get_case_weight (const struct dictionary *d, const struct ccase *c, 
696                       bool *warn_on_invalid)
697 {
698   assert (d != NULL);
699   assert (c != NULL);
700
701   if (d->weight == NULL)
702     return 1.0;
703   else 
704     {
705       double w = case_num (c, d->weight->fv);
706       if (w < 0.0 || mv_is_num_missing (&d->weight->miss, w))
707         w = 0.0;
708       if ( w == 0.0 && *warn_on_invalid ) {
709           *warn_on_invalid = false;
710           msg (SW, _("At least one case in the data file had a weight value "
711                      "that was user-missing, system-missing, zero, or "
712                      "negative.  These case(s) were ignored."));
713       }
714       return w;
715     }
716 }
717
718 /* Sets the weighting variable of D to V, or turning off
719    weighting if V is a null pointer. */
720 void
721 dict_set_weight (struct dictionary *d, struct variable *v) 
722 {
723   assert (d != NULL);
724   assert (v == NULL || dict_contains_var (d, v));
725   assert (v == NULL || v->type == NUMERIC);
726
727   d->weight = v;
728 }
729
730 /* Returns the filter variable in dictionary D (see cmd_filter())
731    or a null pointer if the dictionary is unfiltered. */
732 struct variable *
733 dict_get_filter (const struct dictionary *d) 
734 {
735   assert (d != NULL);
736   assert (d->filter == NULL || dict_contains_var (d, d->filter));
737   
738   return d->filter;
739 }
740
741 /* Sets V as the filter variable for dictionary D.  Passing a
742    null pointer for V turn off filtering. */
743 void
744 dict_set_filter (struct dictionary *d, struct variable *v)
745 {
746   assert (d != NULL);
747   assert (v == NULL || dict_contains_var (d, v));
748
749   d->filter = v;
750 }
751
752 /* Returns the case limit for dictionary D, or zero if the number
753    of cases is unlimited. */
754 size_t
755 dict_get_case_limit (const struct dictionary *d) 
756 {
757   assert (d != NULL);
758
759   return d->case_limit;
760 }
761
762 /* Sets CASE_LIMIT as the case limit for dictionary D.  Use
763    0 for CASE_LIMIT to indicate no limit. */
764 void
765 dict_set_case_limit (struct dictionary *d, size_t case_limit) 
766 {
767   assert (d != NULL);
768
769   d->case_limit = case_limit;
770 }
771
772 /* Returns the index of the next value to be added to D.  This
773    value is the number of `union value's that need to be
774    allocated to store a case for dictionary D. */
775 int
776 dict_get_next_value_idx (const struct dictionary *d) 
777 {
778   assert (d != NULL);
779
780   return d->next_value_idx;
781 }
782
783 /* Returns the number of bytes needed to store a case for
784    dictionary D. */
785 size_t
786 dict_get_case_size (const struct dictionary *d) 
787 {
788   assert (d != NULL);
789
790   return sizeof (union value) * dict_get_next_value_idx (d);
791 }
792
793 /* Deletes scratch variables in dictionary D and reassigns values
794    so that fragmentation is eliminated. */
795 void
796 dict_compact_values (struct dictionary *d) 
797 {
798   size_t i;
799
800   d->next_value_idx = 0;
801   for (i = 0; i < d->var_cnt; )
802     {
803       struct variable *v = d->var[i];
804
805       if (dict_class_from_id (v->name) != DC_SCRATCH) 
806         {
807           v->fv = d->next_value_idx;
808           d->next_value_idx += v->nv;
809           i++;
810         }
811       else
812         dict_delete_var (d, v);
813     }
814 }
815
816 /* Returns the number of values that would be used by a case if
817    dict_compact_values() were called. */
818 size_t
819 dict_get_compacted_value_cnt (const struct dictionary *d) 
820 {
821   size_t i;
822   size_t cnt;
823
824   cnt = 0;
825   for (i = 0; i < d->var_cnt; i++)
826     if (dict_class_from_id (d->var[i]->name) != DC_SCRATCH) 
827       cnt += d->var[i]->nv;
828   return cnt;
829 }
830
831 /* Creates and returns an array mapping from a dictionary index
832    to the `fv' that the corresponding variable will have after
833    calling dict_compact_values().  Scratch variables receive -1
834    for `fv' because dict_compact_values() will delete them. */
835 int *
836 dict_get_compacted_idx_to_fv (const struct dictionary *d) 
837 {
838   size_t i;
839   size_t next_value_idx;
840   int *idx_to_fv;
841   
842   idx_to_fv = xnmalloc (d->var_cnt, sizeof *idx_to_fv);
843   next_value_idx = 0;
844   for (i = 0; i < d->var_cnt; i++)
845     {
846       struct variable *v = d->var[i];
847
848       if (dict_class_from_id (v->name) != DC_SCRATCH) 
849         {
850           idx_to_fv[i] = next_value_idx;
851           next_value_idx += v->nv;
852         }
853       else 
854         idx_to_fv[i] = -1;
855     }
856   return idx_to_fv;
857 }
858
859 /* Returns true if a case for dictionary D would be smaller after
860    compacting, false otherwise.  Compacting a case eliminates
861    "holes" between values and after the last value.  Holes are
862    created by deleting variables (or by scratch variables).
863
864    The return value may differ from whether compacting a case
865    from dictionary D would *change* the case: compacting could
866    rearrange values even if it didn't reduce space
867    requirements. */
868 bool
869 dict_compacting_would_shrink (const struct dictionary *d) 
870 {
871   return dict_get_compacted_value_cnt (d) < dict_get_next_value_idx (d);
872 }
873
874 /* Returns true if a case for dictionary D would change after
875    compacting, false otherwise.  Compacting a case eliminates
876    "holes" between values and after the last value.  Holes are
877    created by deleting variables (or by scratch variables).
878
879    The return value may differ from whether compacting a case
880    from dictionary D would *shrink* the case: compacting could
881    rearrange values without reducing space requirements. */
882 bool
883 dict_compacting_would_change (const struct dictionary *d) 
884 {
885   size_t case_idx;
886   size_t i;
887
888   case_idx = 0;
889   for (i = 0; i < dict_get_var_cnt (d); i++) 
890     {
891       struct variable *v = dict_get_var (d, i);
892       if (v->fv != case_idx)
893         return true;
894       case_idx += v->nv;
895     }
896   return false;
897 }
898 \f
899 /* How to copy a contiguous range of values between cases. */
900 struct copy_map
901   {
902     size_t src_idx;             /* Starting value index in source case. */
903     size_t dst_idx;             /* Starting value index in target case. */
904     size_t cnt;                 /* Number of values. */
905   };
906
907 /* How to compact a case. */
908 struct dict_compactor 
909   {
910     struct copy_map *maps;      /* Array of mappings. */
911     size_t map_cnt;             /* Number of mappings. */
912   };
913
914 /* Creates and returns a dict_compactor that can be used to
915    compact cases for dictionary D.
916
917    Compacting a case eliminates "holes" between values and after
918    the last value.  Holes are created by deleting variables (or
919    by scratch variables). */
920 struct dict_compactor *
921 dict_make_compactor (const struct dictionary *d)
922 {
923   struct dict_compactor *compactor;
924   struct copy_map *map;
925   size_t map_allocated;
926   size_t value_idx;
927   size_t i;
928
929   compactor = xmalloc (sizeof *compactor);
930   compactor->maps = NULL;
931   compactor->map_cnt = 0;
932   map_allocated = 0;
933
934   value_idx = 0;
935   map = NULL;
936   for (i = 0; i < d->var_cnt; i++) 
937     {
938       struct variable *v = d->var[i];
939
940       if (dict_class_from_id (v->name) == DC_SCRATCH)
941         continue;
942       if (map != NULL && map->src_idx + map->cnt == v->fv) 
943         map->cnt += v->nv;
944       else 
945         {
946           if (compactor->map_cnt == map_allocated)
947             compactor->maps = x2nrealloc (compactor->maps, &map_allocated,
948                                           sizeof *compactor->maps);
949           map = &compactor->maps[compactor->map_cnt++];
950           map->src_idx = v->fv;
951           map->dst_idx = value_idx;
952           map->cnt = v->nv;
953         }
954       value_idx += v->nv;
955     }
956
957   return compactor;
958 }
959
960 /* Compacts SRC by copying it to DST according to the scheme in
961    COMPACTOR.
962
963    Compacting a case eliminates "holes" between values and after
964    the last value.  Holes are created by deleting variables (or
965    by scratch variables). */
966 void
967 dict_compactor_compact (const struct dict_compactor *compactor,
968                         struct ccase *dst, const struct ccase *src) 
969 {
970   size_t i;
971
972   for (i = 0; i < compactor->map_cnt; i++) 
973     {
974       const struct copy_map *map = &compactor->maps[i];
975       case_copy (dst, map->dst_idx, src, map->src_idx, map->cnt);
976     }
977 }
978
979 /* Destroys COMPACTOR. */
980 void
981 dict_compactor_destroy (struct dict_compactor *compactor) 
982 {
983   if (compactor != NULL) 
984     {
985       free (compactor->maps);
986       free (compactor);
987     }
988 }
989
990 /* Returns the SPLIT FILE vars (see cmd_split_file()).  Call
991    dict_get_split_cnt() to determine how many SPLIT FILE vars
992    there are.  Returns a null pointer if and only if there are no
993    SPLIT FILE vars. */
994 struct variable *const *
995 dict_get_split_vars (const struct dictionary *d) 
996 {
997   assert (d != NULL);
998   
999   return d->split;
1000 }
1001
1002 /* Returns the number of SPLIT FILE vars. */
1003 size_t
1004 dict_get_split_cnt (const struct dictionary *d) 
1005 {
1006   assert (d != NULL);
1007
1008   return d->split_cnt;
1009 }
1010
1011 /* Sets CNT split vars SPLIT in dictionary D. */
1012 void
1013 dict_set_split_vars (struct dictionary *d,
1014                      struct variable *const *split, size_t cnt)
1015 {
1016   assert (d != NULL);
1017   assert (cnt == 0 || split != NULL);
1018
1019   d->split_cnt = cnt;
1020   d->split = xnrealloc (d->split, cnt, sizeof *d->split);
1021   memcpy (d->split, split, cnt * sizeof *d->split);
1022 }
1023
1024 /* Returns the file label for D, or a null pointer if D is
1025    unlabeled (see cmd_file_label()). */
1026 const char *
1027 dict_get_label (const struct dictionary *d) 
1028 {
1029   assert (d != NULL);
1030
1031   return d->label;
1032 }
1033
1034 /* Sets D's file label to LABEL, truncating it to a maximum of 60
1035    characters. */
1036 void
1037 dict_set_label (struct dictionary *d, const char *label) 
1038 {
1039   assert (d != NULL);
1040
1041   free (d->label);
1042   if (label == NULL)
1043     d->label = NULL;
1044   else if (strlen (label) < 60)
1045     d->label = xstrdup (label);
1046   else 
1047     {
1048       d->label = xmalloc (61);
1049       memcpy (d->label, label, 60);
1050       d->label[60] = '\0';
1051     }
1052 }
1053
1054 /* Returns the documents for D, or a null pointer if D has no
1055    documents (see cmd_document()).. */
1056 const char *
1057 dict_get_documents (const struct dictionary *d) 
1058 {
1059   assert (d != NULL);
1060
1061   return d->documents;
1062 }
1063
1064 /* Sets the documents for D to DOCUMENTS, or removes D's
1065    documents if DOCUMENT is a null pointer. */
1066 void
1067 dict_set_documents (struct dictionary *d, const char *documents)
1068 {
1069   assert (d != NULL);
1070
1071   free (d->documents);
1072   if (documents == NULL)
1073     d->documents = NULL;
1074   else
1075     d->documents = xstrdup (documents);
1076 }
1077
1078 /* Creates in D a vector named NAME that contains CNT variables
1079    VAR (see cmd_vector()).  Returns true if successful, or
1080    false if a vector named NAME already exists in D. */
1081 bool
1082 dict_create_vector (struct dictionary *d,
1083                     const char *name,
1084                     struct variable **var, size_t cnt) 
1085 {
1086   struct vector *vector;
1087   size_t i;
1088
1089   assert (d != NULL);
1090   assert (name != NULL);
1091   assert (var_is_plausible_name (name, false));
1092   assert (var != NULL);
1093   assert (cnt > 0);
1094   
1095   if (dict_lookup_vector (d, name) != NULL)
1096     return false;
1097
1098   d->vector = xnrealloc (d->vector, d->vector_cnt + 1, sizeof *d->vector);
1099   vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector);
1100   vector->idx = d->vector_cnt++;
1101   str_copy_trunc (vector->name, sizeof vector->name, name);
1102   vector->var = xnmalloc (cnt, sizeof *var);
1103   for (i = 0; i < cnt; i++)
1104     {
1105       assert (dict_contains_var (d, var[i]));
1106       vector->var[i] = var[i];
1107     }
1108   vector->cnt = cnt;
1109   
1110   return true;
1111 }
1112
1113 /* Returns the vector in D with index IDX, which must be less
1114    than dict_get_vector_cnt (D). */
1115 const struct vector *
1116 dict_get_vector (const struct dictionary *d, size_t idx) 
1117 {
1118   assert (d != NULL);
1119   assert (idx < d->vector_cnt);
1120
1121   return d->vector[idx];
1122 }
1123
1124 /* Returns the number of vectors in D. */
1125 size_t
1126 dict_get_vector_cnt (const struct dictionary *d) 
1127 {
1128   assert (d != NULL);
1129
1130   return d->vector_cnt;
1131 }
1132
1133 /* Looks up and returns the vector within D with the given
1134    NAME. */
1135 const struct vector *
1136 dict_lookup_vector (const struct dictionary *d, const char *name) 
1137 {
1138   size_t i;
1139
1140   assert (d != NULL);
1141   assert (name != NULL);
1142
1143   for (i = 0; i < d->vector_cnt; i++)
1144     if (!strcasecmp (d->vector[i]->name, name))
1145       return d->vector[i];
1146   return NULL;
1147 }
1148
1149 /* Deletes all vectors from D. */
1150 void
1151 dict_clear_vectors (struct dictionary *d) 
1152 {
1153   size_t i;
1154   
1155   assert (d != NULL);
1156
1157   for (i = 0; i < d->vector_cnt; i++) 
1158     {
1159       free (d->vector[i]->var);
1160       free (d->vector[i]);
1161     }
1162   free (d->vector);
1163   d->vector = NULL;
1164   d->vector_cnt = 0;
1165 }
1166
1167 /* Compares two strings. */
1168 static int
1169 compare_strings (const void *a, const void *b, const void *aux UNUSED) 
1170 {
1171   return strcmp (a, b);
1172 }
1173
1174 /* Hashes a string. */
1175 static unsigned
1176 hash_string (const void *s, const void *aux UNUSED) 
1177 {
1178   return hsh_hash_string (s);
1179 }
1180
1181 /* Assigns a valid, unique short_name[] to each variable in D.
1182    Each variable whose actual name is short has highest priority
1183    for that short name.  Otherwise, variables with an existing
1184    short_name[] have the next highest priority for a given short
1185    name; if it is already taken, then the variable is treated as
1186    if short_name[] had been empty.  Otherwise, long names are
1187    truncated to form short names.  If that causes conflicts,
1188    variables are renamed as PREFIX_A, PREFIX_B, and so on. */
1189 void
1190 dict_assign_short_names (struct dictionary *d) 
1191 {
1192   struct hsh_table *short_names;
1193   size_t i;
1194
1195   /* Give variables whose names are short the corresponding short
1196      names, and clear short_names[] that conflict with a variable
1197      name. */
1198   for (i = 0; i < d->var_cnt; i++)
1199     {
1200       struct variable *v = d->var[i];
1201       if (strlen (v->name) <= SHORT_NAME_LEN)
1202         var_set_short_name (v, v->name);
1203       else if (dict_lookup_var (d, v->short_name) != NULL)
1204         var_clear_short_name (v);
1205     }
1206
1207   /* Each variable with an assigned short_name[] now gets it
1208      unless there is a conflict. */
1209   short_names = hsh_create (d->var_cnt, compare_strings, hash_string,
1210                             NULL, NULL);
1211   for (i = 0; i < d->var_cnt; i++)
1212     {
1213       struct variable *v = d->var[i];
1214       if (v->short_name[0] && hsh_insert (short_names, v->short_name) != NULL)
1215         var_clear_short_name (v);
1216     }
1217   
1218   /* Now assign short names to remaining variables. */
1219   for (i = 0; i < d->var_cnt; i++)
1220     {
1221       struct variable *v = d->var[i];
1222       if (v->short_name[0] == '\0') 
1223         {
1224           int sfx;
1225
1226           /* Form initial short_name. */
1227           var_set_short_name (v, v->name);
1228
1229           /* Try _A, _B, ... _AA, _AB, etc., if needed. */
1230           for (sfx = 0; hsh_insert (short_names, v->short_name) != NULL; sfx++)
1231             var_set_short_name_suffix (v, v->name, sfx);
1232         } 
1233     }
1234
1235   /* Get rid of hash table. */
1236   hsh_destroy (short_names);
1237 }