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