Added the ability to resize string variables from the GUI. Thanks to
[pspp-builds.git] / src / data / dictionary.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "dictionary.h"
20
21 #include <stdlib.h>
22 #include <ctype.h>
23
24 #include "case.h"
25 #include "category.h"
26 #include "settings.h"
27 #include "value-labels.h"
28 #include "vardict.h"
29 #include "variable.h"
30 #include "vector.h"
31 #include <libpspp/alloc.h>
32 #include <libpspp/array.h>
33 #include <libpspp/compiler.h>
34 #include <libpspp/hash.h>
35 #include <libpspp/message.h>
36 #include <libpspp/misc.h>
37 #include <libpspp/pool.h>
38 #include <libpspp/str.h>
39
40 #include "minmax.h"
41
42 #include "gettext.h"
43 #define _(msgid) gettext (msgid)
44
45 /* A dictionary. */
46 struct dictionary
47   {
48     struct variable **var;      /* Variables. */
49     size_t var_cnt, var_cap;    /* Number of variables, capacity. */
50     struct hsh_table *name_tab; /* Variable index by name. */
51     int next_value_idx;         /* Index of next `union value' to allocate. */
52     const struct variable **split;    /* SPLIT FILE vars. */
53     size_t split_cnt;           /* SPLIT FILE count. */
54     struct variable *weight;    /* WEIGHT variable. */
55     struct variable *filter;    /* FILTER variable. */
56     size_t case_limit;          /* Current case limit (N command). */
57     char *label;                /* File label. */
58     struct string documents;    /* Documents, as a string. */
59     struct vector **vector;     /* Vectors of variables. */
60     size_t vector_cnt;          /* Number of vectors. */
61     const struct dict_callbacks *callbacks; /* Callbacks on dictionary
62                                                modification */
63     void *cb_data ;                  /* Data passed to callbacks */
64   };
65
66
67 /* Associate CALLBACKS with DICT.  Callbacks will be invoked whenever
68    the dictionary or any of the variables it contains are modified.
69    Each callback will get passed CALLBACK_DATA.
70    Any callback may be NULL, in which case it'll be ignored.
71 */
72 void
73 dict_set_callbacks (struct dictionary *dict,
74                     const struct dict_callbacks *callbacks,
75                     void *callback_data)
76 {
77   dict->callbacks = callbacks;
78   dict->cb_data = callback_data;
79 }
80
81 /* Shallow copy the callbacks from SRC to DEST */
82 void
83 dict_copy_callbacks (struct dictionary *dest,
84                      const struct dictionary *src)
85 {
86   dest->callbacks = src->callbacks;
87   dest->cb_data = src->cb_data;
88 }
89
90 /* Creates and returns a new dictionary. */
91 struct dictionary *
92 dict_create (void)
93 {
94   struct dictionary *d = xzalloc (sizeof *d);
95
96   d->name_tab = hsh_create (8, compare_vars_by_name, hash_var_by_name,
97                             NULL, NULL);
98   return d;
99 }
100
101 /* Creates and returns a (deep) copy of an existing
102    dictionary. */
103 struct dictionary *
104 dict_clone (const struct dictionary *s)
105 {
106   struct dictionary *d;
107   size_t i;
108
109   assert (s != NULL);
110
111   d = dict_create ();
112
113   for (i = 0; i < s->var_cnt; i++)
114     {
115       struct variable *sv = s->var[i];
116       struct variable *dv = dict_clone_var_assert (d, sv, var_get_name (sv));
117       var_set_short_name (dv, var_get_short_name (sv));
118     }
119
120   d->next_value_idx = s->next_value_idx;
121
122   d->split_cnt = s->split_cnt;
123   if (d->split_cnt > 0)
124     {
125       d->split = xnmalloc (d->split_cnt, sizeof *d->split);
126       for (i = 0; i < d->split_cnt; i++)
127         d->split[i] = dict_lookup_var_assert (d, var_get_name (s->split[i]));
128     }
129
130   if (s->weight != NULL)
131     dict_set_weight (d, dict_lookup_var_assert (d, var_get_name (s->weight)));
132
133   if (s->filter != NULL)
134     dict_set_filter (d, dict_lookup_var_assert (d, var_get_name (s->filter)));
135
136   d->case_limit = s->case_limit;
137   dict_set_label (d, dict_get_label (s));
138   dict_set_documents (d, dict_get_documents (s));
139
140   d->vector_cnt = s->vector_cnt;
141   d->vector = xnmalloc (d->vector_cnt, sizeof *d->vector);
142   for (i = 0; i < s->vector_cnt; i++)
143     d->vector[i] = vector_clone (s->vector[i], s, d);
144
145   return d;
146 }
147
148 /* Clears the contents from a dictionary without destroying the
149    dictionary itself. */
150 void
151 dict_clear (struct dictionary *d)
152 {
153   /* FIXME?  Should we really clear case_limit, label, documents?
154      Others are necessarily cleared by deleting all the variables.*/
155   assert (d != NULL);
156
157   while (d->var_cnt > 0 )
158     {
159       struct variable *v = d->var[d->var_cnt - 1];
160       int dict_index = var_get_dict_index (v);
161       int case_index = var_get_case_index (v);
162       int val_cnt = var_get_value_cnt (v);
163
164       var_clear_vardict (v);
165       var_destroy (v);
166
167       d->var_cnt--;
168
169       if (d->callbacks &&  d->callbacks->var_deleted )
170         d->callbacks->var_deleted (d,
171                                    dict_index, case_index, val_cnt,
172                                    d->cb_data);
173     }
174
175   free (d->var);
176   d->var = NULL;
177   d->var_cnt = d->var_cap = 0;
178   hsh_clear (d->name_tab);
179   d->next_value_idx = 0;
180   dict_set_split_vars (d, NULL, 0);
181   dict_set_weight (d, NULL);
182   dict_set_filter (d, NULL);
183   d->case_limit = 0;
184   free (d->label);
185   d->label = NULL;
186   ds_destroy (&d->documents);
187   dict_clear_vectors (d);
188 }
189
190 /* Destroys the aux data for every variable in D, by calling
191    var_clear_aux() for each variable. */
192 void
193 dict_clear_aux (struct dictionary *d)
194 {
195   int i;
196
197   assert (d != NULL);
198
199   for (i = 0; i < d->var_cnt; i++)
200     var_clear_aux (d->var[i]);
201 }
202
203 /* Clears a dictionary and destroys it. */
204 void
205 dict_destroy (struct dictionary *d)
206 {
207   if (d != NULL)
208     {
209       /* In general, we don't want callbacks occuring, if the dictionary
210          is being destroyed */
211       d->callbacks  = NULL ;
212
213       dict_clear (d);
214       hsh_destroy (d->name_tab);
215       free (d);
216     }
217 }
218
219 /* Returns the number of variables in D. */
220 size_t
221 dict_get_var_cnt (const struct dictionary *d)
222 {
223   assert (d != NULL);
224
225   return d->var_cnt;
226 }
227
228 /* Returns the variable in D with dictionary index IDX, which
229    must be between 0 and the count returned by
230    dict_get_var_cnt(), exclusive. */
231 struct variable *
232 dict_get_var (const struct dictionary *d, size_t idx)
233 {
234   assert (d != NULL);
235   assert (idx < d->var_cnt);
236
237   return d->var[idx];
238 }
239
240 inline void
241 dict_get_vars (const struct dictionary *d, const struct variable ***vars,
242                size_t *cnt, unsigned exclude_classes)
243 {
244   dict_get_vars_mutable (d, (struct variable ***) vars, cnt, exclude_classes);
245 }
246
247 /* Sets *VARS to an array of pointers to variables in D and *CNT
248    to the number of variables in *D.  All variables are returned
249    if EXCLUDE_CLASSES is 0, or it may contain one or more of (1u
250    << DC_ORDINARY), (1u << DC_SYSTEM), or (1u << DC_SCRATCH) to
251    exclude the corresponding type of variable. */
252 void
253 dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
254                size_t *cnt, unsigned exclude_classes)
255 {
256   size_t count;
257   size_t i;
258
259   assert (d != NULL);
260   assert (vars != NULL);
261   assert (cnt != NULL);
262   assert ((exclude_classes & ~((1u << DC_ORDINARY)
263                                | (1u << DC_SYSTEM)
264                                | (1u << DC_SCRATCH))) == 0);
265
266   count = 0;
267   for (i = 0; i < d->var_cnt; i++)
268     {
269       enum dict_class class = dict_class_from_id (var_get_name (d->var[i]));
270       if (!(exclude_classes & (1u << class)))
271         count++;
272     }
273
274   *vars = xnmalloc (count, sizeof **vars);
275   *cnt = 0;
276   for (i = 0; i < d->var_cnt; i++)
277     {
278       enum dict_class class = dict_class_from_id (var_get_name (d->var[i]));
279       if (!(exclude_classes & (1u << class)))
280         (*vars)[(*cnt)++] = d->var[i];
281     }
282   assert (*cnt == count);
283 }
284
285 static struct variable *
286 add_var (struct dictionary *d, struct variable *v)
287 {
288   /* Add dictionary info to variable. */
289   struct vardict_info vdi;
290   vdi.case_index = d->next_value_idx;
291   vdi.dict_index = d->var_cnt;
292   vdi.dict = d;
293   var_set_vardict (v, &vdi);
294
295   /* Update dictionary. */
296   if (d->var_cnt >= d->var_cap)
297     {
298       d->var_cap = 8 + 2 * d->var_cap;
299       d->var = xnrealloc (d->var, d->var_cap, sizeof *d->var);
300     }
301   d->var[d->var_cnt++] = v;
302   hsh_force_insert (d->name_tab, v);
303
304   if ( d->callbacks &&  d->callbacks->var_added )
305     d->callbacks->var_added (d, var_get_dict_index (v), d->cb_data);
306
307   d->next_value_idx += var_get_value_cnt (v);
308
309   return v;
310 }
311
312 /* Creates and returns a new variable in D with the given NAME
313    and WIDTH.  Returns a null pointer if the given NAME would
314    duplicate that of an existing variable in the dictionary. */
315 struct variable *
316 dict_create_var (struct dictionary *d, const char *name, int width)
317 {
318   return (dict_lookup_var (d, name) == NULL
319           ? dict_create_var_assert (d, name, width)
320           : NULL);
321 }
322
323 /* Creates and returns a new variable in D with the given NAME
324    and WIDTH.  Assert-fails if the given NAME would duplicate
325    that of an existing variable in the dictionary. */
326 struct variable *
327 dict_create_var_assert (struct dictionary *d, const char *name, int width)
328 {
329   assert (dict_lookup_var (d, name) == NULL);
330   return add_var (d, var_create (name, width));
331 }
332
333 /* Creates and returns a new variable in D with name NAME, as a
334    copy of existing variable OLD_VAR, which need not be in D or
335    in any dictionary.  Returns a null pointer if the given NAME
336    would duplicate that of an existing variable in the
337    dictionary. */
338 struct variable *
339 dict_clone_var (struct dictionary *d, const struct variable *old_var,
340                 const char *name)
341 {
342   return (dict_lookup_var (d, name) == NULL
343           ? dict_clone_var_assert (d, old_var, name)
344           : NULL);
345 }
346
347 /* Creates and returns a new variable in D with name NAME, as a
348    copy of existing variable OLD_VAR, which need not be in D or
349    in any dictionary.  Assert-fails if the given NAME would
350    duplicate that of an existing variable in the dictionary. */
351 struct variable *
352 dict_clone_var_assert (struct dictionary *d, const struct variable *old_var,
353                        const char *name)
354 {
355   struct variable *new_var = var_clone (old_var);
356   assert (dict_lookup_var (d, name) == NULL);
357   var_set_name (new_var, name);
358   return add_var (d, new_var);
359 }
360
361 /* Returns the variable named NAME in D, or a null pointer if no
362    variable has that name. */
363 struct variable *
364 dict_lookup_var (const struct dictionary *d, const char *name)
365 {
366   struct variable *target ;
367   struct variable *result ;
368
369   if ( ! var_is_valid_name (name, false))
370     return NULL;
371
372   target = var_create (name, 0);
373   result = hsh_find (d->name_tab, target);
374   var_destroy (target);
375
376   return result;
377 }
378
379 /* Returns the variable named NAME in D.  Assert-fails if no
380    variable has that name. */
381 struct variable *
382 dict_lookup_var_assert (const struct dictionary *d, const char *name)
383 {
384   struct variable *v = dict_lookup_var (d, name);
385   assert (v != NULL);
386   return v;
387 }
388
389 /* Returns true if variable V is in dictionary D,
390    false otherwise. */
391 bool
392 dict_contains_var (const struct dictionary *d, const struct variable *v)
393 {
394   if (var_has_vardict (v))
395     {
396       const struct vardict_info *vdi = var_get_vardict (v);
397       return (vdi->dict_index >= 0
398               && vdi->dict_index < d->var_cnt
399               && d->var[vdi->dict_index] == v);
400     }
401   else
402     return false;
403 }
404
405 /* Compares two double pointers to variables, which should point
406    to elements of a struct dictionary's `var' member array. */
407 static int
408 compare_var_ptrs (const void *a_, const void *b_, const void *aux UNUSED)
409 {
410   struct variable *const *a = a_;
411   struct variable *const *b = b_;
412
413   return *a < *b ? -1 : *a > *b;
414 }
415
416 /* Sets the dict_index in V's vardict to DICT_INDEX. */
417 static void
418 set_var_dict_index (struct variable *v, int dict_index)
419 {
420   struct vardict_info vdi = *var_get_vardict (v);
421   struct dictionary *d = vdi.dict;
422   vdi.dict_index = dict_index;
423   var_set_vardict (v, &vdi);
424
425   if ( d->callbacks &&  d->callbacks->var_changed )
426     d->callbacks->var_changed (d, dict_index, d->cb_data);
427 }
428
429 /* Sets the case_index in V's vardict to CASE_INDEX. */
430 static void
431 set_var_case_index (struct variable *v, int case_index)
432 {
433   struct vardict_info vdi = *var_get_vardict (v);
434   vdi.case_index = case_index;
435   var_set_vardict (v, &vdi);
436 }
437
438 /* Re-sets the dict_index in the dictionary variables with
439    indexes from FROM to TO (exclusive). */
440 static void
441 reindex_vars (struct dictionary *d, size_t from, size_t to)
442 {
443   size_t i;
444
445   for (i = from; i < to; i++)
446     set_var_dict_index (d->var[i], i);
447 }
448
449 /* Deletes variable V from dictionary D and frees V.
450
451    This is a very bad idea if there might be any pointers to V
452    from outside D.  In general, no variable in the active file's
453    dictionary should be deleted when any transformations are
454    active on the dictionary's dataset, because those
455    transformations might reference the deleted variable.  The
456    safest time to delete a variable is just after a procedure has
457    been executed, as done by MODIFY VARS.
458
459    Pointers to V within D are not a problem, because
460    dict_delete_var() knows to remove V from split variables,
461    weights, filters, etc. */
462 void
463 dict_delete_var (struct dictionary *d, struct variable *v)
464 {
465   int dict_index = var_get_dict_index (v);
466   const int case_index = var_get_case_index (v);
467   const int val_cnt = var_get_value_cnt (v);
468
469   assert (dict_contains_var (d, v));
470
471   /* Delete aux data. */
472   var_clear_aux (v);
473
474   dict_unset_split_var (d, v);
475
476   if (d->weight == v)
477     dict_set_weight (d, NULL);
478
479   if (d->filter == v)
480     dict_set_filter (d, NULL);
481
482   dict_clear_vectors (d);
483
484   /* Remove V from var array. */
485   remove_element (d->var, d->var_cnt, sizeof *d->var, dict_index);
486   d->var_cnt--;
487
488   /* Update dict_index for each affected variable. */
489   reindex_vars (d, dict_index, d->var_cnt);
490
491   /* Update name hash. */
492   hsh_force_delete (d->name_tab, v);
493
494
495   /* Free memory. */
496   var_clear_vardict (v);
497   var_destroy (v);
498
499   if (d->callbacks &&  d->callbacks->var_deleted )
500     d->callbacks->var_deleted (d, dict_index, case_index, val_cnt, d->cb_data);
501 }
502
503 /* Deletes the COUNT variables listed in VARS from D.  This is
504    unsafe; see the comment on dict_delete_var() for details. */
505 void
506 dict_delete_vars (struct dictionary *d,
507                   struct variable *const *vars, size_t count)
508 {
509   /* FIXME: this can be done in O(count) time, but this algorithm
510      is O(count**2). */
511   assert (d != NULL);
512   assert (count == 0 || vars != NULL);
513
514   while (count-- > 0)
515     dict_delete_var (d, *vars++);
516 }
517
518 /* Deletes the COUNT variables in D starting at index IDX.  This
519    is unsafe; see the comment on dict_delete_var() for
520    details. */
521 void
522 dict_delete_consecutive_vars (struct dictionary *d, size_t idx, size_t count)
523 {
524   /* FIXME: this can be done in O(count) time, but this algorithm
525      is O(count**2). */
526   assert (idx + count <= d->var_cnt);
527
528   while (count-- > 0)
529     dict_delete_var (d, d->var[idx]);
530 }
531
532 /* Deletes scratch variables from dictionary D. */
533 void
534 dict_delete_scratch_vars (struct dictionary *d)
535 {
536   int i;
537
538   /* FIXME: this can be done in O(count) time, but this algorithm
539      is O(count**2). */
540   assert (d != NULL);
541
542   for (i = 0; i < d->var_cnt; )
543     if (dict_class_from_id (var_get_name (d->var[i])) == DC_SCRATCH)
544       dict_delete_var (d, d->var[i]);
545     else
546       i++;
547 }
548
549 /* Moves V to 0-based position IDX in D.  Other variables in D,
550    if any, retain their relative positions.  Runs in time linear
551    in the distance moved. */
552 void
553 dict_reorder_var (struct dictionary *d, struct variable *v, size_t new_index)
554 {
555   size_t old_index = var_get_dict_index (v);
556
557   assert (new_index < d->var_cnt);
558   move_element (d->var, d->var_cnt, sizeof *d->var, old_index, new_index);
559   reindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1);
560 }
561
562 /* Reorders the variables in D, placing the COUNT variables
563    listed in ORDER in that order at the beginning of D.  The
564    other variables in D, if any, retain their relative
565    positions. */
566 void
567 dict_reorder_vars (struct dictionary *d,
568                    struct variable *const *order, size_t count)
569 {
570   struct variable **new_var;
571   size_t i;
572
573   assert (d != NULL);
574   assert (count == 0 || order != NULL);
575   assert (count <= d->var_cnt);
576
577   new_var = xnmalloc (d->var_cnt, sizeof *new_var);
578   memcpy (new_var, order, count * sizeof *new_var);
579   for (i = 0; i < count; i++)
580     {
581       size_t index = var_get_dict_index (order[i]);
582       assert (d->var[index] == order[i]);
583       d->var[index] = NULL;
584       set_var_dict_index (order[i], i);
585     }
586   for (i = 0; i < d->var_cnt; i++)
587     if (d->var[i] != NULL)
588       {
589         assert (count < d->var_cnt);
590         new_var[count] = d->var[i];
591         set_var_dict_index (new_var[count], count);
592         count++;
593       }
594   free (d->var);
595   d->var = new_var;
596 }
597
598 /* Changes the name of variable V in dictionary D to NEW_NAME. */
599 static void
600 rename_var (struct dictionary *d, struct variable *v, const char *new_name)
601 {
602   struct vardict_info vdi;
603
604   assert (dict_contains_var (d, v));
605
606   vdi = *var_get_vardict (v);
607   var_clear_vardict (v);
608   var_set_name (v, new_name);
609   var_set_vardict (v, &vdi);
610 }
611
612 /* Changes the name of V in D to name NEW_NAME.  Assert-fails if
613    a variable named NEW_NAME is already in D, except that
614    NEW_NAME may be the same as V's existing name. */
615 void
616 dict_rename_var (struct dictionary *d, struct variable *v,
617                  const char *new_name)
618 {
619   assert (!strcasecmp (var_get_name (v), new_name)
620           || dict_lookup_var (d, new_name) == NULL);
621
622   hsh_force_delete (d->name_tab, v);
623   rename_var (d, v, new_name);
624   hsh_force_insert (d->name_tab, v);
625
626   if (get_algorithm () == ENHANCED)
627     var_clear_short_name (v);
628
629   if ( d->callbacks &&  d->callbacks->var_changed )
630     d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data);
631 }
632
633 /* Renames COUNT variables specified in VARS to the names given
634    in NEW_NAMES within dictionary D.  If the renaming would
635    result in a duplicate variable name, returns false and stores a
636    name that would be duplicated into *ERR_NAME (if ERR_NAME is
637    non-null).  Otherwise, the renaming is successful, and true
638    is returned. */
639 bool
640 dict_rename_vars (struct dictionary *d,
641                   struct variable **vars, char **new_names, size_t count,
642                   char **err_name)
643 {
644   struct pool *pool;
645   char **old_names;
646   size_t i;
647
648   assert (count == 0 || vars != NULL);
649   assert (count == 0 || new_names != NULL);
650
651   /* Save the names of the variables to be renamed. */
652   pool = pool_create ();
653   old_names = pool_nalloc (pool, count, sizeof *old_names);
654   for (i = 0; i < count; i++)
655     old_names[i] = pool_strdup (pool, var_get_name (vars[i]));
656
657   /* Remove the variables to be renamed from the name hash,
658      and rename them. */
659   for (i = 0; i < count; i++)
660     {
661       hsh_force_delete (d->name_tab, vars[i]);
662       rename_var (d, vars[i], new_names[i]);
663     }
664
665   /* Add the renamed variables back into the name hash,
666      checking for conflicts. */
667   for (i = 0; i < count; i++)
668     if (hsh_insert (d->name_tab, vars[i]) != NULL)
669       {
670         /* There is a name conflict.
671            Back out all the name changes that have already
672            taken place, and indicate failure. */
673         size_t fail_idx = i;
674         if (err_name != NULL)
675           *err_name = new_names[i];
676
677         for (i = 0; i < fail_idx; i++)
678           hsh_force_delete (d->name_tab, vars[i]);
679
680         for (i = 0; i < count; i++)
681           {
682             rename_var (d, vars[i], old_names[i]);
683             hsh_force_insert (d->name_tab, vars[i]);
684           }
685
686         pool_destroy (pool);
687         return false;
688       }
689
690   /* Clear short names. */
691   if (get_algorithm () == ENHANCED)
692     for (i = 0; i < count; i++)
693       var_clear_short_name (vars[i]);
694
695   pool_destroy (pool);
696   return true;
697 }
698
699 /* Returns the weighting variable in dictionary D, or a null
700    pointer if the dictionary is unweighted. */
701 struct variable *
702 dict_get_weight (const struct dictionary *d)
703 {
704   assert (d != NULL);
705   assert (d->weight == NULL || dict_contains_var (d, d->weight));
706
707   return d->weight;
708 }
709
710 /* Returns the value of D's weighting variable in case C, except that a
711    negative weight is returned as 0.  Returns 1 if the dictionary is
712    unweighted. Will warn about missing, negative, or zero values if
713    warn_on_invalid is true. The function will set warn_on_invalid to false
714    if an invalid weight is found. */
715 double
716 dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
717                       bool *warn_on_invalid)
718 {
719   assert (d != NULL);
720   assert (c != NULL);
721
722   if (d->weight == NULL)
723     return 1.0;
724   else
725     {
726       double w = case_num (c, d->weight);
727       if (w < 0.0 || var_is_num_missing (d->weight, w, MV_ANY))
728         w = 0.0;
729       if ( w == 0.0 && warn_on_invalid != NULL && *warn_on_invalid ) {
730           *warn_on_invalid = false;
731           msg (SW, _("At least one case in the data file had a weight value "
732                      "that was user-missing, system-missing, zero, or "
733                      "negative.  These case(s) were ignored."));
734       }
735       return w;
736     }
737 }
738
739 /* Sets the weighting variable of D to V, or turning off
740    weighting if V is a null pointer. */
741 void
742 dict_set_weight (struct dictionary *d, struct variable *v)
743 {
744   assert (d != NULL);
745   assert (v == NULL || dict_contains_var (d, v));
746   assert (v == NULL || var_is_numeric (v));
747
748   d->weight = v;
749
750   if ( d->callbacks &&  d->callbacks->weight_changed )
751     d->callbacks->weight_changed (d,
752                                   v ? var_get_dict_index (v) : -1,
753                                   d->cb_data);
754 }
755
756 /* Returns the filter variable in dictionary D (see cmd_filter())
757    or a null pointer if the dictionary is unfiltered. */
758 struct variable *
759 dict_get_filter (const struct dictionary *d)
760 {
761   assert (d != NULL);
762   assert (d->filter == NULL || dict_contains_var (d, d->filter));
763
764   return d->filter;
765 }
766
767 /* Sets V as the filter variable for dictionary D.  Passing a
768    null pointer for V turn off filtering. */
769 void
770 dict_set_filter (struct dictionary *d, struct variable *v)
771 {
772   assert (d != NULL);
773   assert (v == NULL || dict_contains_var (d, v));
774
775   d->filter = v;
776
777   if ( d->callbacks && d->callbacks->filter_changed )
778     d->callbacks->filter_changed (d,
779                                   v ? var_get_dict_index (v) : -1,
780                                   d->cb_data);
781 }
782
783 /* Returns the case limit for dictionary D, or zero if the number
784    of cases is unlimited. */
785 size_t
786 dict_get_case_limit (const struct dictionary *d)
787 {
788   assert (d != NULL);
789
790   return d->case_limit;
791 }
792
793 /* Sets CASE_LIMIT as the case limit for dictionary D.  Use
794    0 for CASE_LIMIT to indicate no limit. */
795 void
796 dict_set_case_limit (struct dictionary *d, size_t case_limit)
797 {
798   assert (d != NULL);
799
800   d->case_limit = case_limit;
801 }
802
803 /* Returns the case index of the next value to be added to D.
804    This value is the number of `union value's that need to be
805    allocated to store a case for dictionary D. */
806 int
807 dict_get_next_value_idx (const struct dictionary *d)
808 {
809   assert (d != NULL);
810
811   return d->next_value_idx;
812 }
813
814 /* Returns the number of bytes needed to store a case for
815    dictionary D. */
816 size_t
817 dict_get_case_size (const struct dictionary *d)
818 {
819   assert (d != NULL);
820
821   return sizeof (union value) * dict_get_next_value_idx (d);
822 }
823
824 /* Deletes scratch variables in dictionary D and reassigns values
825    so that fragmentation is eliminated. */
826 void
827 dict_compact_values (struct dictionary *d)
828 {
829   size_t i;
830
831   d->next_value_idx = 0;
832   for (i = 0; i < d->var_cnt; )
833     {
834       struct variable *v = d->var[i];
835
836       if (dict_class_from_id (var_get_name (v)) != DC_SCRATCH)
837         {
838           set_var_case_index (v, d->next_value_idx);
839           d->next_value_idx += var_get_value_cnt (v);
840           i++;
841         }
842       else
843         dict_delete_var (d, v);
844     }
845 }
846
847
848 /*
849    Reassigns case indices for D, increasing each index above START by
850    the value PADDING.
851 */
852 static void
853 dict_pad_values (struct dictionary *d, int start, int padding)
854 {
855   size_t i;
856
857   if ( padding <= 0 ) 
858         return;
859
860   for (i = 0; i < d->var_cnt; ++i)
861     {
862       struct variable *v = d->var[i];
863
864       int index = var_get_case_index (v);
865
866       if ( index >= start)
867         set_var_case_index (v, index + padding);
868     }
869
870   d->next_value_idx += padding;
871 }
872
873
874 /* Returns the number of values that would be used by a case if
875    dict_compact_values() were called. */
876 size_t
877 dict_get_compacted_value_cnt (const struct dictionary *d)
878 {
879   size_t i;
880   size_t cnt;
881
882   cnt = 0;
883   for (i = 0; i < d->var_cnt; i++)
884     if (dict_class_from_id (var_get_name (d->var[i])) != DC_SCRATCH)
885       cnt += var_get_value_cnt (d->var[i]);
886   return cnt;
887 }
888
889 /* Creates and returns an array mapping from a dictionary index
890    to the case index that the corresponding variable will have
891    after calling dict_compact_values().  Scratch variables
892    receive -1 for case index because dict_compact_values() will
893    delete them. */
894 int *
895 dict_get_compacted_dict_index_to_case_index (const struct dictionary *d)
896 {
897   size_t i;
898   size_t next_value_idx;
899   int *map;
900
901   map = xnmalloc (d->var_cnt, sizeof *map);
902   next_value_idx = 0;
903   for (i = 0; i < d->var_cnt; i++)
904     {
905       struct variable *v = d->var[i];
906
907       if (dict_class_from_id (var_get_name (v)) != DC_SCRATCH)
908         {
909           map[i] = next_value_idx;
910           next_value_idx += var_get_value_cnt (v);
911         }
912       else
913         map[i] = -1;
914     }
915   return map;
916 }
917
918 /* Returns true if a case for dictionary D would be smaller after
919    compacting, false otherwise.  Compacting a case eliminates
920    "holes" between values and after the last value.  Holes are
921    created by deleting variables (or by scratch variables).
922
923    The return value may differ from whether compacting a case
924    from dictionary D would *change* the case: compacting could
925    rearrange values even if it didn't reduce space
926    requirements. */
927 bool
928 dict_compacting_would_shrink (const struct dictionary *d)
929 {
930   return dict_get_compacted_value_cnt (d) < dict_get_next_value_idx (d);
931 }
932
933 /* Returns true if a case for dictionary D would change after
934    compacting, false otherwise.  Compacting a case eliminates
935    "holes" between values and after the last value.  Holes are
936    created by deleting variables (or by scratch variables).
937
938    The return value may differ from whether compacting a case
939    from dictionary D would *shrink* the case: compacting could
940    rearrange values without reducing space requirements. */
941 bool
942 dict_compacting_would_change (const struct dictionary *d)
943 {
944   size_t case_idx;
945   size_t i;
946
947   case_idx = 0;
948   for (i = 0; i < dict_get_var_cnt (d); i++)
949     {
950       struct variable *v = dict_get_var (d, i);
951       if (var_get_case_index (v) != case_idx)
952         return true;
953       case_idx += var_get_value_cnt (v);
954     }
955   return false;
956 }
957 \f
958 /* How to copy a contiguous range of values between cases. */
959 struct copy_map
960   {
961     size_t src_idx;             /* Starting value index in source case. */
962     size_t dst_idx;             /* Starting value index in target case. */
963     size_t cnt;                 /* Number of values. */
964   };
965
966 /* How to compact a case. */
967 struct dict_compactor
968   {
969     struct copy_map *maps;      /* Array of mappings. */
970     size_t map_cnt;             /* Number of mappings. */
971   };
972
973 /* Creates and returns a dict_compactor that can be used to
974    compact cases for dictionary D.
975
976    Compacting a case eliminates "holes" between values and after
977    the last value.  Holes are created by deleting variables (or
978    by scratch variables). */
979 struct dict_compactor *
980 dict_make_compactor (const struct dictionary *d)
981 {
982   struct dict_compactor *compactor;
983   struct copy_map *map;
984   size_t map_allocated;
985   size_t value_idx;
986   size_t i;
987
988   compactor = xmalloc (sizeof *compactor);
989   compactor->maps = NULL;
990   compactor->map_cnt = 0;
991   map_allocated = 0;
992
993   value_idx = 0;
994   map = NULL;
995   for (i = 0; i < d->var_cnt; i++)
996     {
997       struct variable *v = d->var[i];
998
999       if (dict_class_from_id (var_get_name (v)) == DC_SCRATCH)
1000         continue;
1001       if (map != NULL && map->src_idx + map->cnt == var_get_case_index (v))
1002         map->cnt += var_get_value_cnt (v);
1003       else
1004         {
1005           if (compactor->map_cnt == map_allocated)
1006             compactor->maps = x2nrealloc (compactor->maps, &map_allocated,
1007                                           sizeof *compactor->maps);
1008           map = &compactor->maps[compactor->map_cnt++];
1009           map->src_idx = var_get_case_index (v);
1010           map->dst_idx = value_idx;
1011           map->cnt = var_get_value_cnt (v);
1012         }
1013       value_idx += var_get_value_cnt (v);
1014     }
1015
1016   return compactor;
1017 }
1018
1019 /* Compacts SRC by copying it to DST according to the scheme in
1020    COMPACTOR.
1021
1022    Compacting a case eliminates "holes" between values and after
1023    the last value.  Holes are created by deleting variables (or
1024    by scratch variables). */
1025 void
1026 dict_compactor_compact (const struct dict_compactor *compactor,
1027                         struct ccase *dst, const struct ccase *src)
1028 {
1029   size_t i;
1030
1031   for (i = 0; i < compactor->map_cnt; i++)
1032     {
1033       const struct copy_map *map = &compactor->maps[i];
1034       case_copy (dst, map->dst_idx, src, map->src_idx, map->cnt);
1035     }
1036 }
1037
1038 /* Destroys COMPACTOR. */
1039 void
1040 dict_compactor_destroy (struct dict_compactor *compactor)
1041 {
1042   if (compactor != NULL)
1043     {
1044       free (compactor->maps);
1045       free (compactor);
1046     }
1047 }
1048
1049 /* Returns the SPLIT FILE vars (see cmd_split_file()).  Call
1050    dict_get_split_cnt() to determine how many SPLIT FILE vars
1051    there are.  Returns a null pointer if and only if there are no
1052    SPLIT FILE vars. */
1053 const struct variable *const *
1054 dict_get_split_vars (const struct dictionary *d)
1055 {
1056   assert (d != NULL);
1057
1058   return d->split;
1059 }
1060
1061 /* Returns the number of SPLIT FILE vars. */
1062 size_t
1063 dict_get_split_cnt (const struct dictionary *d)
1064 {
1065   assert (d != NULL);
1066
1067   return d->split_cnt;
1068 }
1069
1070 /* Removes variable V from the set of split variables in dictionary D */
1071 void
1072 dict_unset_split_var (struct dictionary *d,
1073                       struct variable *v)
1074 {
1075   const int count = d->split_cnt;
1076   d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
1077                                &v, compare_var_ptrs, NULL);
1078
1079   if ( count == d->split_cnt)
1080     return;
1081
1082   if ( d->callbacks &&  d->callbacks->split_changed )
1083     d->callbacks->split_changed (d, d->cb_data);
1084 }
1085
1086 /* Sets CNT split vars SPLIT in dictionary D. */
1087 void
1088 dict_set_split_vars (struct dictionary *d,
1089                      struct variable *const *split, size_t cnt)
1090 {
1091   assert (d != NULL);
1092   assert (cnt == 0 || split != NULL);
1093
1094   d->split_cnt = cnt;
1095   d->split = cnt > 0 ? xnrealloc (d->split, cnt, sizeof *d->split) : NULL;
1096   memcpy (d->split, split, cnt * sizeof *d->split);
1097
1098   if ( d->callbacks &&  d->callbacks->split_changed )
1099     d->callbacks->split_changed (d, d->cb_data);
1100 }
1101
1102 /* Returns the file label for D, or a null pointer if D is
1103    unlabeled (see cmd_file_label()). */
1104 const char *
1105 dict_get_label (const struct dictionary *d)
1106 {
1107   assert (d != NULL);
1108
1109   return d->label;
1110 }
1111
1112 /* Sets D's file label to LABEL, truncating it to a maximum of 60
1113    characters. */
1114 void
1115 dict_set_label (struct dictionary *d, const char *label)
1116 {
1117   assert (d != NULL);
1118
1119   free (d->label);
1120   if (label == NULL)
1121     d->label = NULL;
1122   else if (strlen (label) < 60)
1123     d->label = xstrdup (label);
1124   else
1125     {
1126       d->label = xmalloc (61);
1127       memcpy (d->label, label, 60);
1128       d->label[60] = '\0';
1129     }
1130 }
1131
1132 /* Returns the documents for D, or a null pointer if D has no
1133    documents.  If the return value is nonnull, then the string
1134    will be an exact multiple of DOC_LINE_LENGTH bytes in length,
1135    with each segment corresponding to one line. */
1136 const char *
1137 dict_get_documents (const struct dictionary *d)
1138 {
1139   return ds_is_empty (&d->documents) ? NULL : ds_cstr (&d->documents);
1140 }
1141
1142 /* Sets the documents for D to DOCUMENTS, or removes D's
1143    documents if DOCUMENT is a null pointer.  If DOCUMENTS is
1144    nonnull, then it should be an exact multiple of
1145    DOC_LINE_LENGTH bytes in length, with each segment
1146    corresponding to one line. */
1147 void
1148 dict_set_documents (struct dictionary *d, const char *documents)
1149 {
1150   size_t remainder;
1151
1152   ds_assign_cstr (&d->documents, documents != NULL ? documents : "");
1153
1154   /* In case the caller didn't get it quite right, pad out the
1155      final line with spaces. */
1156   remainder = ds_length (&d->documents) % DOC_LINE_LENGTH;
1157   if (remainder != 0)
1158     ds_put_char_multiple (&d->documents, ' ', DOC_LINE_LENGTH - remainder);
1159 }
1160
1161 /* Drops the documents from dictionary D. */
1162 void
1163 dict_clear_documents (struct dictionary *d)
1164 {
1165   ds_clear (&d->documents);
1166 }
1167
1168 /* Appends LINE to the documents in D.  LINE will be truncated or
1169    padded on the right with spaces to make it exactly
1170    DOC_LINE_LENGTH bytes long. */
1171 void
1172 dict_add_document_line (struct dictionary *d, const char *line)
1173 {
1174   if (strlen (line) > DOC_LINE_LENGTH)
1175     {
1176       /* Note to translators: "bytes" is correct, not characters */
1177       msg (SW, _("Truncating document line to %d bytes."), DOC_LINE_LENGTH);
1178     }
1179   buf_copy_str_rpad (ds_put_uninit (&d->documents, DOC_LINE_LENGTH),
1180                      DOC_LINE_LENGTH, line);
1181 }
1182
1183 /* Returns the number of document lines in dictionary D. */
1184 size_t
1185 dict_get_document_line_cnt (const struct dictionary *d)
1186 {
1187   return ds_length (&d->documents) / DOC_LINE_LENGTH;
1188 }
1189
1190 /* Copies document line number IDX from dictionary D into
1191    LINE, trimming off any trailing white space. */
1192 void
1193 dict_get_document_line (const struct dictionary *d,
1194                         size_t idx, struct string *line)
1195 {
1196   assert (idx < dict_get_document_line_cnt (d));
1197   ds_assign_substring (line, ds_substr (&d->documents, idx * DOC_LINE_LENGTH,
1198                                         DOC_LINE_LENGTH));
1199   ds_rtrim (line, ss_cstr (CC_SPACES));
1200 }
1201
1202 /* Creates in D a vector named NAME that contains the CNT
1203    variables in VAR.  Returns true if successful, or false if a
1204    vector named NAME already exists in D. */
1205 bool
1206 dict_create_vector (struct dictionary *d,
1207                     const char *name,
1208                     struct variable **var, size_t cnt)
1209 {
1210   size_t i;
1211
1212   assert (var != NULL);
1213   assert (cnt > 0);
1214   for (i = 0; i < cnt; i++)
1215     assert (dict_contains_var (d, var[i]));
1216
1217   if (dict_lookup_vector (d, name) == NULL)
1218     {
1219       d->vector = xnrealloc (d->vector, d->vector_cnt + 1, sizeof *d->vector);
1220       d->vector[d->vector_cnt++] = vector_create (name, var, cnt);
1221       return true;
1222     }
1223   else
1224     return false;
1225 }
1226
1227 /* Creates in D a vector named NAME that contains the CNT
1228    variables in VAR.  A vector named NAME must not already exist
1229    in D. */
1230 void
1231 dict_create_vector_assert (struct dictionary *d,
1232                            const char *name,
1233                            struct variable **var, size_t cnt)
1234 {
1235   assert (dict_lookup_vector (d, name) == NULL);
1236   dict_create_vector (d, name, var, cnt);
1237 }
1238
1239 /* Returns the vector in D with index IDX, which must be less
1240    than dict_get_vector_cnt (D). */
1241 const struct vector *
1242 dict_get_vector (const struct dictionary *d, size_t idx)
1243 {
1244   assert (d != NULL);
1245   assert (idx < d->vector_cnt);
1246
1247   return d->vector[idx];
1248 }
1249
1250 /* Returns the number of vectors in D. */
1251 size_t
1252 dict_get_vector_cnt (const struct dictionary *d)
1253 {
1254   assert (d != NULL);
1255
1256   return d->vector_cnt;
1257 }
1258
1259 /* Looks up and returns the vector within D with the given
1260    NAME. */
1261 const struct vector *
1262 dict_lookup_vector (const struct dictionary *d, const char *name)
1263 {
1264   size_t i;
1265   for (i = 0; i < d->vector_cnt; i++)
1266     if (!strcasecmp (vector_get_name (d->vector[i]), name))
1267       return d->vector[i];
1268   return NULL;
1269 }
1270
1271 /* Deletes all vectors from D. */
1272 void
1273 dict_clear_vectors (struct dictionary *d)
1274 {
1275   size_t i;
1276
1277   for (i = 0; i < d->vector_cnt; i++)
1278     vector_destroy (d->vector[i]);
1279   free (d->vector);
1280
1281   d->vector = NULL;
1282   d->vector_cnt = 0;
1283 }
1284
1285 /* Compares two strings. */
1286 static int
1287 compare_strings (const void *a, const void *b, const void *aux UNUSED)
1288 {
1289   return strcmp (a, b);
1290 }
1291
1292 /* Hashes a string. */
1293 static unsigned
1294 hash_string (const void *s, const void *aux UNUSED)
1295 {
1296   return hsh_hash_string (s);
1297 }
1298
1299
1300 /* Sets V's short name to BASE, followed by a suffix of the form
1301    _A, _B, _C, ..., _AA, _AB, etc. according to the value of
1302    SUFFIX_NUMBER.  Truncates BASE as necessary to fit. */
1303 static void
1304 set_var_short_name_suffix (struct variable *v, const char *base,
1305                            int suffix_number)
1306 {
1307   char suffix[SHORT_NAME_LEN + 1];
1308   char short_name[SHORT_NAME_LEN + 1];
1309   char *start, *end;
1310   int len, ofs;
1311
1312   assert (v != NULL);
1313   assert (suffix_number >= 0);
1314
1315   /* Set base name. */
1316   var_set_short_name (v, base);
1317
1318   /* Compose suffix. */
1319   start = end = suffix + sizeof suffix - 1;
1320   *end = '\0';
1321   do
1322     {
1323       *--start = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[suffix_number % 26];
1324       if (start <= suffix + 1)
1325         msg (SE, _("Variable suffix too large."));
1326       suffix_number /= 26;
1327     }
1328   while (suffix_number > 0);
1329   *--start = '_';
1330
1331   /* Append suffix to V's short name. */
1332   str_copy_trunc (short_name, sizeof short_name, base);
1333   len = end - start;
1334   if (len + strlen (short_name) > SHORT_NAME_LEN)
1335     ofs = SHORT_NAME_LEN - len;
1336   else
1337     ofs = strlen (short_name);
1338   strcpy (short_name + ofs, start);
1339
1340   /* Set name. */
1341   var_set_short_name (v, short_name);
1342 }
1343
1344 /* Assigns a valid, unique short_name[] to each variable in D.
1345    Each variable whose actual name is short has highest priority
1346    for that short name.  Otherwise, variables with an existing
1347    short_name[] have the next highest priority for a given short
1348    name; if it is already taken, then the variable is treated as
1349    if short_name[] had been empty.  Otherwise, long names are
1350    truncated to form short names.  If that causes conflicts,
1351    variables are renamed as PREFIX_A, PREFIX_B, and so on. */
1352 void
1353 dict_assign_short_names (struct dictionary *d)
1354 {
1355   struct hsh_table *short_names;
1356   size_t i;
1357
1358   /* Give variables whose names are short the corresponding short
1359      names, and clear short_names[] that conflict with a variable
1360      name. */
1361   for (i = 0; i < d->var_cnt; i++)
1362     {
1363       struct variable *v = d->var[i];
1364       const char *short_name = var_get_short_name (v);
1365       if (strlen (var_get_name (v)) <= SHORT_NAME_LEN)
1366         var_set_short_name (v, var_get_name (v));
1367       else if (short_name != NULL && dict_lookup_var (d, short_name) != NULL)
1368         var_clear_short_name (v);
1369     }
1370
1371   /* Each variable with an assigned short_name[] now gets it
1372      unless there is a conflict. */
1373   short_names = hsh_create (d->var_cnt, compare_strings, hash_string,
1374                             NULL, NULL);
1375   for (i = 0; i < d->var_cnt; i++)
1376     {
1377       struct variable *v = d->var[i];
1378       const char *name = var_get_short_name (v);
1379       if (name != NULL && hsh_insert (short_names, (char *) name) != NULL)
1380         var_clear_short_name (v);
1381     }
1382
1383   /* Now assign short names to remaining variables. */
1384   for (i = 0; i < d->var_cnt; i++)
1385     {
1386       struct variable *v = d->var[i];
1387       const char *name = var_get_short_name (v);
1388       if (name == NULL)
1389         {
1390           /* Form initial short_name from the variable name, then
1391              try _A, _B, ... _AA, _AB, etc., if needed.*/
1392           int trial = 0;
1393           do
1394             {
1395               if (trial == 0)
1396                 var_set_short_name (v, var_get_name (v));
1397               else
1398                 set_var_short_name_suffix (v, var_get_name (v), trial - 1);
1399
1400               trial++;
1401             }
1402           while (hsh_insert (short_names, (char *) var_get_short_name (v))
1403                  != NULL);
1404         }
1405     }
1406
1407   /* Get rid of hash table. */
1408   hsh_destroy (short_names);
1409 }
1410
1411
1412 /* Called from variable.c to notify the dictionary that some property of
1413    the variable has changed */
1414 void
1415 dict_var_changed (const struct variable *v)
1416 {
1417   if ( var_has_vardict (v))
1418     {
1419       const struct vardict_info *vdi = var_get_vardict (v);
1420       struct dictionary *d;
1421
1422       d = vdi->dict;
1423
1424       if ( d->callbacks && d->callbacks->var_changed )
1425         d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data);
1426     }
1427 }
1428
1429
1430 /* Called from variable.c to notify the dictionary that the variable's width
1431    has changed */
1432 void
1433 dict_var_resized (const struct variable *v, int delta)
1434 {
1435   if ( var_has_vardict (v))
1436     {
1437       const struct vardict_info *vdi = var_get_vardict (v);
1438       struct dictionary *d;
1439
1440       d = vdi->dict;
1441
1442       dict_pad_values (d, var_get_case_index(v) + 1, delta);
1443
1444       if ( d->callbacks && d->callbacks->var_resized )
1445         d->callbacks->var_resized (d, var_get_dict_index (v), delta, d->cb_data);
1446     }
1447 }