* psppire-dict.c (psppire_dict_dump): Don't use
[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       size_t i;
118
119       for (i = 0; i < var_get_short_name_cnt (sv); i++)
120         var_set_short_name (dv, i, var_get_short_name (sv, i));
121     }
122
123   d->next_value_idx = s->next_value_idx;
124
125   d->split_cnt = s->split_cnt;
126   if (d->split_cnt > 0)
127     {
128       d->split = xnmalloc (d->split_cnt, sizeof *d->split);
129       for (i = 0; i < d->split_cnt; i++)
130         d->split[i] = dict_lookup_var_assert (d, var_get_name (s->split[i]));
131     }
132
133   if (s->weight != NULL)
134     dict_set_weight (d, dict_lookup_var_assert (d, var_get_name (s->weight)));
135
136   if (s->filter != NULL)
137     dict_set_filter (d, dict_lookup_var_assert (d, var_get_name (s->filter)));
138
139   d->case_limit = s->case_limit;
140   dict_set_label (d, dict_get_label (s));
141   dict_set_documents (d, dict_get_documents (s));
142
143   d->vector_cnt = s->vector_cnt;
144   d->vector = xnmalloc (d->vector_cnt, sizeof *d->vector);
145   for (i = 0; i < s->vector_cnt; i++)
146     d->vector[i] = vector_clone (s->vector[i], s, d);
147
148   return d;
149 }
150
151 /* Clears the contents from a dictionary without destroying the
152    dictionary itself. */
153 void
154 dict_clear (struct dictionary *d)
155 {
156   /* FIXME?  Should we really clear case_limit, label, documents?
157      Others are necessarily cleared by deleting all the variables.*/
158   assert (d != NULL);
159
160   while (d->var_cnt > 0 )
161     {
162       struct variable *v = d->var[d->var_cnt - 1];
163       int dict_index = var_get_dict_index (v);
164       int case_index = var_get_case_index (v);
165       int val_cnt = var_get_value_cnt (v);
166
167       var_clear_vardict (v);
168       var_destroy (v);
169
170       d->var_cnt--;
171
172       if (d->callbacks &&  d->callbacks->var_deleted )
173         d->callbacks->var_deleted (d,
174                                    dict_index, case_index, val_cnt,
175                                    d->cb_data);
176     }
177
178   free (d->var);
179   d->var = NULL;
180   d->var_cnt = d->var_cap = 0;
181   hsh_clear (d->name_tab);
182   d->next_value_idx = 0;
183   dict_set_split_vars (d, NULL, 0);
184   dict_set_weight (d, NULL);
185   dict_set_filter (d, NULL);
186   d->case_limit = 0;
187   free (d->label);
188   d->label = NULL;
189   ds_destroy (&d->documents);
190   dict_clear_vectors (d);
191 }
192
193 /* Destroys the aux data for every variable in D, by calling
194    var_clear_aux() for each variable. */
195 void
196 dict_clear_aux (struct dictionary *d)
197 {
198   int i;
199
200   assert (d != NULL);
201
202   for (i = 0; i < d->var_cnt; i++)
203     var_clear_aux (d->var[i]);
204 }
205
206 /* Clears a dictionary and destroys it. */
207 void
208 dict_destroy (struct dictionary *d)
209 {
210   if (d != NULL)
211     {
212       /* In general, we don't want callbacks occuring, if the dictionary
213          is being destroyed */
214       d->callbacks  = NULL ;
215
216       dict_clear (d);
217       hsh_destroy (d->name_tab);
218       free (d);
219     }
220 }
221
222 /* Returns the number of variables in D. */
223 size_t
224 dict_get_var_cnt (const struct dictionary *d)
225 {
226   assert (d != NULL);
227
228   return d->var_cnt;
229 }
230
231 /* Returns the variable in D with dictionary index IDX, which
232    must be between 0 and the count returned by
233    dict_get_var_cnt(), exclusive. */
234 struct variable *
235 dict_get_var (const struct dictionary *d, size_t idx)
236 {
237   assert (d != NULL);
238   assert (idx < d->var_cnt);
239
240   return d->var[idx];
241 }
242
243 inline void
244 dict_get_vars (const struct dictionary *d, const struct variable ***vars,
245                size_t *cnt, unsigned exclude_classes)
246 {
247   dict_get_vars_mutable (d, (struct variable ***) vars, cnt, exclude_classes);
248 }
249
250 /* Sets *VARS to an array of pointers to variables in D and *CNT
251    to the number of variables in *D.  All variables are returned
252    if EXCLUDE_CLASSES is 0, or it may contain one or more of (1u
253    << DC_ORDINARY), (1u << DC_SYSTEM), or (1u << DC_SCRATCH) to
254    exclude the corresponding type of variable. */
255 void
256 dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
257                size_t *cnt, unsigned exclude_classes)
258 {
259   size_t count;
260   size_t i;
261
262   assert (d != NULL);
263   assert (vars != NULL);
264   assert (cnt != NULL);
265   assert ((exclude_classes & ~((1u << DC_ORDINARY)
266                                | (1u << DC_SYSTEM)
267                                | (1u << DC_SCRATCH))) == 0);
268
269   count = 0;
270   for (i = 0; i < d->var_cnt; i++)
271     {
272       enum dict_class class = dict_class_from_id (var_get_name (d->var[i]));
273       if (!(exclude_classes & (1u << class)))
274         count++;
275     }
276
277   *vars = xnmalloc (count, sizeof **vars);
278   *cnt = 0;
279   for (i = 0; i < d->var_cnt; i++)
280     {
281       enum dict_class class = dict_class_from_id (var_get_name (d->var[i]));
282       if (!(exclude_classes & (1u << class)))
283         (*vars)[(*cnt)++] = d->var[i];
284     }
285   assert (*cnt == count);
286 }
287
288 static struct variable *
289 add_var (struct dictionary *d, struct variable *v)
290 {
291   /* Add dictionary info to variable. */
292   struct vardict_info vdi;
293   vdi.case_index = d->next_value_idx;
294   vdi.dict_index = d->var_cnt;
295   vdi.dict = d;
296   var_set_vardict (v, &vdi);
297
298   /* Update dictionary. */
299   if (d->var_cnt >= d->var_cap)
300     {
301       d->var_cap = 8 + 2 * d->var_cap;
302       d->var = xnrealloc (d->var, d->var_cap, sizeof *d->var);
303     }
304   d->var[d->var_cnt++] = v;
305   hsh_force_insert (d->name_tab, v);
306
307   if ( d->callbacks &&  d->callbacks->var_added )
308     d->callbacks->var_added (d, var_get_dict_index (v), d->cb_data);
309
310   d->next_value_idx += var_get_value_cnt (v);
311
312   return v;
313 }
314
315 /* Creates and returns a new variable in D with the given NAME
316    and WIDTH.  Returns a null pointer if the given NAME would
317    duplicate that of an existing variable in the dictionary. */
318 struct variable *
319 dict_create_var (struct dictionary *d, const char *name, int width)
320 {
321   return (dict_lookup_var (d, name) == NULL
322           ? dict_create_var_assert (d, name, width)
323           : NULL);
324 }
325
326 /* Creates and returns a new variable in D with the given NAME
327    and WIDTH.  Assert-fails if the given NAME would duplicate
328    that of an existing variable in the dictionary. */
329 struct variable *
330 dict_create_var_assert (struct dictionary *d, const char *name, int width)
331 {
332   assert (dict_lookup_var (d, name) == NULL);
333   return add_var (d, var_create (name, width));
334 }
335
336 /* Creates and returns a new variable in D with name NAME, as a
337    copy of existing variable OLD_VAR, which need not be in D or
338    in any dictionary.  Returns a null pointer if the given NAME
339    would duplicate that of an existing variable in the
340    dictionary. */
341 struct variable *
342 dict_clone_var (struct dictionary *d, const struct variable *old_var,
343                 const char *name)
344 {
345   return (dict_lookup_var (d, name) == NULL
346           ? dict_clone_var_assert (d, old_var, name)
347           : NULL);
348 }
349
350 /* Creates and returns a new variable in D with name NAME, as a
351    copy of existing variable OLD_VAR, which need not be in D or
352    in any dictionary.  Assert-fails if the given NAME would
353    duplicate that of an existing variable in the dictionary. */
354 struct variable *
355 dict_clone_var_assert (struct dictionary *d, const struct variable *old_var,
356                        const char *name)
357 {
358   struct variable *new_var = var_clone (old_var);
359   assert (dict_lookup_var (d, name) == NULL);
360   var_set_name (new_var, name);
361   return add_var (d, new_var);
362 }
363
364 /* Returns the variable named NAME in D, or a null pointer if no
365    variable has that name. */
366 struct variable *
367 dict_lookup_var (const struct dictionary *d, const char *name)
368 {
369   struct variable *target ;
370   struct variable *result ;
371
372   if ( ! var_is_valid_name (name, false))
373     return NULL;
374
375   target = var_create (name, 0);
376   result = hsh_find (d->name_tab, target);
377   var_destroy (target);
378
379   return result;
380 }
381
382 /* Returns the variable named NAME in D.  Assert-fails if no
383    variable has that name. */
384 struct variable *
385 dict_lookup_var_assert (const struct dictionary *d, const char *name)
386 {
387   struct variable *v = dict_lookup_var (d, name);
388   assert (v != NULL);
389   return v;
390 }
391
392 /* Returns true if variable V is in dictionary D,
393    false otherwise. */
394 bool
395 dict_contains_var (const struct dictionary *d, const struct variable *v)
396 {
397   if (var_has_vardict (v))
398     {
399       const struct vardict_info *vdi = var_get_vardict (v);
400       return (vdi->dict_index >= 0
401               && vdi->dict_index < d->var_cnt
402               && d->var[vdi->dict_index] == v);
403     }
404   else
405     return false;
406 }
407
408 /* Compares two double pointers to variables, which should point
409    to elements of a struct dictionary's `var' member array. */
410 static int
411 compare_var_ptrs (const void *a_, const void *b_, const void *aux UNUSED)
412 {
413   struct variable *const *a = a_;
414   struct variable *const *b = b_;
415
416   return *a < *b ? -1 : *a > *b;
417 }
418
419 /* Sets the dict_index in V's vardict to DICT_INDEX. */
420 static void
421 set_var_dict_index (struct variable *v, int dict_index)
422 {
423   struct vardict_info vdi = *var_get_vardict (v);
424   struct dictionary *d = vdi.dict;
425   vdi.dict_index = dict_index;
426   var_set_vardict (v, &vdi);
427
428   if ( d->callbacks &&  d->callbacks->var_changed )
429     d->callbacks->var_changed (d, dict_index, d->cb_data);
430 }
431
432 /* Sets the case_index in V's vardict to CASE_INDEX. */
433 static void
434 set_var_case_index (struct variable *v, int case_index)
435 {
436   struct vardict_info vdi = *var_get_vardict (v);
437   vdi.case_index = case_index;
438   var_set_vardict (v, &vdi);
439 }
440
441 /* Re-sets the dict_index in the dictionary variables with
442    indexes from FROM to TO (exclusive). */
443 static void
444 reindex_vars (struct dictionary *d, size_t from, size_t to)
445 {
446   size_t i;
447
448   for (i = from; i < to; i++)
449     set_var_dict_index (d->var[i], i);
450 }
451
452 /* Deletes variable V from dictionary D and frees V.
453
454    This is a very bad idea if there might be any pointers to V
455    from outside D.  In general, no variable in the active file's
456    dictionary should be deleted when any transformations are
457    active on the dictionary's dataset, because those
458    transformations might reference the deleted variable.  The
459    safest time to delete a variable is just after a procedure has
460    been executed, as done by MODIFY VARS.
461
462    Pointers to V within D are not a problem, because
463    dict_delete_var() knows to remove V from split variables,
464    weights, filters, etc. */
465 void
466 dict_delete_var (struct dictionary *d, struct variable *v)
467 {
468   int dict_index = var_get_dict_index (v);
469   const int case_index = var_get_case_index (v);
470   const int val_cnt = var_get_value_cnt (v);
471
472   assert (dict_contains_var (d, v));
473
474   /* Delete aux data. */
475   var_clear_aux (v);
476
477   dict_unset_split_var (d, v);
478
479   if (d->weight == v)
480     dict_set_weight (d, NULL);
481
482   if (d->filter == v)
483     dict_set_filter (d, NULL);
484
485   dict_clear_vectors (d);
486
487   /* Remove V from var array. */
488   remove_element (d->var, d->var_cnt, sizeof *d->var, dict_index);
489   d->var_cnt--;
490
491   /* Update dict_index for each affected variable. */
492   reindex_vars (d, dict_index, d->var_cnt);
493
494   /* Update name hash. */
495   hsh_force_delete (d->name_tab, v);
496
497
498   /* Free memory. */
499   var_clear_vardict (v);
500   var_destroy (v);
501
502   if (d->callbacks &&  d->callbacks->var_deleted )
503     d->callbacks->var_deleted (d, dict_index, case_index, val_cnt, d->cb_data);
504 }
505
506 /* Deletes the COUNT variables listed in VARS from D.  This is
507    unsafe; see the comment on dict_delete_var() for details. */
508 void
509 dict_delete_vars (struct dictionary *d,
510                   struct variable *const *vars, size_t count)
511 {
512   /* FIXME: this can be done in O(count) time, but this algorithm
513      is O(count**2). */
514   assert (d != NULL);
515   assert (count == 0 || vars != NULL);
516
517   while (count-- > 0)
518     dict_delete_var (d, *vars++);
519 }
520
521 /* Deletes the COUNT variables in D starting at index IDX.  This
522    is unsafe; see the comment on dict_delete_var() for
523    details. */
524 void
525 dict_delete_consecutive_vars (struct dictionary *d, size_t idx, size_t count)
526 {
527   /* FIXME: this can be done in O(count) time, but this algorithm
528      is O(count**2). */
529   assert (idx + count <= d->var_cnt);
530
531   while (count-- > 0)
532     dict_delete_var (d, d->var[idx]);
533 }
534
535 /* Deletes scratch variables from dictionary D. */
536 void
537 dict_delete_scratch_vars (struct dictionary *d)
538 {
539   int i;
540
541   /* FIXME: this can be done in O(count) time, but this algorithm
542      is O(count**2). */
543   assert (d != NULL);
544
545   for (i = 0; i < d->var_cnt; )
546     if (dict_class_from_id (var_get_name (d->var[i])) == DC_SCRATCH)
547       dict_delete_var (d, d->var[i]);
548     else
549       i++;
550 }
551
552 /* Moves V to 0-based position IDX in D.  Other variables in D,
553    if any, retain their relative positions.  Runs in time linear
554    in the distance moved. */
555 void
556 dict_reorder_var (struct dictionary *d, struct variable *v, size_t new_index)
557 {
558   size_t old_index = var_get_dict_index (v);
559
560   assert (new_index < d->var_cnt);
561   move_element (d->var, d->var_cnt, sizeof *d->var, old_index, new_index);
562   reindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1);
563 }
564
565 /* Reorders the variables in D, placing the COUNT variables
566    listed in ORDER in that order at the beginning of D.  The
567    other variables in D, if any, retain their relative
568    positions. */
569 void
570 dict_reorder_vars (struct dictionary *d,
571                    struct variable *const *order, size_t count)
572 {
573   struct variable **new_var;
574   size_t i;
575
576   assert (d != NULL);
577   assert (count == 0 || order != NULL);
578   assert (count <= d->var_cnt);
579
580   new_var = xnmalloc (d->var_cnt, sizeof *new_var);
581   memcpy (new_var, order, count * sizeof *new_var);
582   for (i = 0; i < count; i++)
583     {
584       size_t index = var_get_dict_index (order[i]);
585       assert (d->var[index] == order[i]);
586       d->var[index] = NULL;
587       set_var_dict_index (order[i], i);
588     }
589   for (i = 0; i < d->var_cnt; i++)
590     if (d->var[i] != NULL)
591       {
592         assert (count < d->var_cnt);
593         new_var[count] = d->var[i];
594         set_var_dict_index (new_var[count], count);
595         count++;
596       }
597   free (d->var);
598   d->var = new_var;
599 }
600
601 /* Changes the name of variable V in dictionary D to NEW_NAME. */
602 static void
603 rename_var (struct dictionary *d, struct variable *v, const char *new_name)
604 {
605   struct vardict_info vdi;
606
607   assert (dict_contains_var (d, v));
608
609   vdi = *var_get_vardict (v);
610   var_clear_vardict (v);
611   var_set_name (v, new_name);
612   var_set_vardict (v, &vdi);
613 }
614
615 /* Changes the name of V in D to name NEW_NAME.  Assert-fails if
616    a variable named NEW_NAME is already in D, except that
617    NEW_NAME may be the same as V's existing name. */
618 void
619 dict_rename_var (struct dictionary *d, struct variable *v,
620                  const char *new_name)
621 {
622   assert (!strcasecmp (var_get_name (v), new_name)
623           || dict_lookup_var (d, new_name) == NULL);
624
625   hsh_force_delete (d->name_tab, v);
626   rename_var (d, v, new_name);
627   hsh_force_insert (d->name_tab, v);
628
629   if (get_algorithm () == ENHANCED)
630     var_clear_short_names (v);
631
632   if ( d->callbacks &&  d->callbacks->var_changed )
633     d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data);
634 }
635
636 /* Renames COUNT variables specified in VARS to the names given
637    in NEW_NAMES within dictionary D.  If the renaming would
638    result in a duplicate variable name, returns false and stores a
639    name that would be duplicated into *ERR_NAME (if ERR_NAME is
640    non-null).  Otherwise, the renaming is successful, and true
641    is returned. */
642 bool
643 dict_rename_vars (struct dictionary *d,
644                   struct variable **vars, char **new_names, size_t count,
645                   char **err_name)
646 {
647   struct pool *pool;
648   char **old_names;
649   size_t i;
650
651   assert (count == 0 || vars != NULL);
652   assert (count == 0 || new_names != NULL);
653
654   /* Save the names of the variables to be renamed. */
655   pool = pool_create ();
656   old_names = pool_nalloc (pool, count, sizeof *old_names);
657   for (i = 0; i < count; i++)
658     old_names[i] = pool_strdup (pool, var_get_name (vars[i]));
659
660   /* Remove the variables to be renamed from the name hash,
661      and rename them. */
662   for (i = 0; i < count; i++)
663     {
664       hsh_force_delete (d->name_tab, vars[i]);
665       rename_var (d, vars[i], new_names[i]);
666     }
667
668   /* Add the renamed variables back into the name hash,
669      checking for conflicts. */
670   for (i = 0; i < count; i++)
671     if (hsh_insert (d->name_tab, vars[i]) != NULL)
672       {
673         /* There is a name conflict.
674            Back out all the name changes that have already
675            taken place, and indicate failure. */
676         size_t fail_idx = i;
677         if (err_name != NULL)
678           *err_name = new_names[i];
679
680         for (i = 0; i < fail_idx; i++)
681           hsh_force_delete (d->name_tab, vars[i]);
682
683         for (i = 0; i < count; i++)
684           {
685             rename_var (d, vars[i], old_names[i]);
686             hsh_force_insert (d->name_tab, vars[i]);
687           }
688
689         pool_destroy (pool);
690         return false;
691       }
692
693   /* Clear short names. */
694   if (get_algorithm () == ENHANCED)
695     for (i = 0; i < count; i++)
696       var_clear_short_names (vars[i]);
697
698   pool_destroy (pool);
699   return true;
700 }
701
702 /* Returns the weighting variable in dictionary D, or a null
703    pointer if the dictionary is unweighted. */
704 struct variable *
705 dict_get_weight (const struct dictionary *d)
706 {
707   assert (d != NULL);
708   assert (d->weight == NULL || dict_contains_var (d, d->weight));
709
710   return d->weight;
711 }
712
713 /* Returns the value of D's weighting variable in case C, except that a
714    negative weight is returned as 0.  Returns 1 if the dictionary is
715    unweighted. Will warn about missing, negative, or zero values if
716    warn_on_invalid is true. The function will set warn_on_invalid to false
717    if an invalid weight is found. */
718 double
719 dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
720                       bool *warn_on_invalid)
721 {
722   assert (d != NULL);
723   assert (c != NULL);
724
725   if (d->weight == NULL)
726     return 1.0;
727   else
728     {
729       double w = case_num (c, d->weight);
730       if (w < 0.0 || var_is_num_missing (d->weight, w, MV_ANY))
731         w = 0.0;
732       if ( w == 0.0 && warn_on_invalid != NULL && *warn_on_invalid ) {
733           *warn_on_invalid = false;
734           msg (SW, _("At least one case in the data file had a weight value "
735                      "that was user-missing, system-missing, zero, or "
736                      "negative.  These case(s) were ignored."));
737       }
738       return w;
739     }
740 }
741
742 /* Sets the weighting variable of D to V, or turning off
743    weighting if V is a null pointer. */
744 void
745 dict_set_weight (struct dictionary *d, struct variable *v)
746 {
747   assert (d != NULL);
748   assert (v == NULL || dict_contains_var (d, v));
749   assert (v == NULL || var_is_numeric (v));
750
751   d->weight = v;
752
753   if ( d->callbacks &&  d->callbacks->weight_changed )
754     d->callbacks->weight_changed (d,
755                                   v ? var_get_dict_index (v) : -1,
756                                   d->cb_data);
757 }
758
759 /* Returns the filter variable in dictionary D (see cmd_filter())
760    or a null pointer if the dictionary is unfiltered. */
761 struct variable *
762 dict_get_filter (const struct dictionary *d)
763 {
764   assert (d != NULL);
765   assert (d->filter == NULL || dict_contains_var (d, d->filter));
766
767   return d->filter;
768 }
769
770 /* Sets V as the filter variable for dictionary D.  Passing a
771    null pointer for V turn off filtering. */
772 void
773 dict_set_filter (struct dictionary *d, struct variable *v)
774 {
775   assert (d != NULL);
776   assert (v == NULL || dict_contains_var (d, v));
777
778   d->filter = v;
779
780   if ( d->callbacks && d->callbacks->filter_changed )
781     d->callbacks->filter_changed (d,
782                                   v ? var_get_dict_index (v) : -1,
783                                   d->cb_data);
784 }
785
786 /* Returns the case limit for dictionary D, or zero if the number
787    of cases is unlimited. */
788 size_t
789 dict_get_case_limit (const struct dictionary *d)
790 {
791   assert (d != NULL);
792
793   return d->case_limit;
794 }
795
796 /* Sets CASE_LIMIT as the case limit for dictionary D.  Use
797    0 for CASE_LIMIT to indicate no limit. */
798 void
799 dict_set_case_limit (struct dictionary *d, size_t case_limit)
800 {
801   assert (d != NULL);
802
803   d->case_limit = case_limit;
804 }
805
806 /* Returns the case index of the next value to be added to D.
807    This value is the number of `union value's that need to be
808    allocated to store a case for dictionary D. */
809 int
810 dict_get_next_value_idx (const struct dictionary *d)
811 {
812   assert (d != NULL);
813
814   return d->next_value_idx;
815 }
816
817 /* Returns the number of bytes needed to store a case for
818    dictionary D. */
819 size_t
820 dict_get_case_size (const struct dictionary *d)
821 {
822   assert (d != NULL);
823
824   return sizeof (union value) * dict_get_next_value_idx (d);
825 }
826
827 /* Reassigns values in dictionary D so that fragmentation is
828    eliminated. */
829 void
830 dict_compact_values (struct dictionary *d)
831 {
832   size_t i;
833
834   d->next_value_idx = 0;
835   for (i = 0; i < d->var_cnt; i++)
836     {
837       struct variable *v = d->var[i];
838       set_var_case_index (v, d->next_value_idx);
839       d->next_value_idx += var_get_value_cnt (v);
840     }
841 }
842
843 /*
844    Reassigns case indices for D, increasing each index above START by
845    the value PADDING.
846 */
847 static void
848 dict_pad_values (struct dictionary *d, int start, int padding)
849 {
850   size_t i;
851
852   if ( padding <= 0 ) 
853         return;
854
855   for (i = 0; i < d->var_cnt; ++i)
856     {
857       struct variable *v = d->var[i];
858
859       int index = var_get_case_index (v);
860
861       if ( index >= start)
862         set_var_case_index (v, index + padding);
863     }
864
865   d->next_value_idx += padding;
866 }
867
868
869 /* Returns the number of values occupied by the variables in
870    dictionary D.  All variables are considered if EXCLUDE_CLASSES
871    is 0, or it may contain one or more of (1u << DC_ORDINARY),
872    (1u << DC_SYSTEM), or (1u << DC_SCRATCH) to exclude the
873    corresponding type of variable.
874
875    The return value may be less than the number of values in one
876    of dictionary D's cases (as returned by
877    dict_get_next_value_idx) even if E is 0, because there may be
878    gaps in D's cases due to deleted variables. */
879 size_t
880 dict_count_values (const struct dictionary *d, unsigned int exclude_classes)
881 {
882   size_t i;
883   size_t cnt;
884
885   assert ((exclude_classes & ~((1u << DC_ORDINARY)
886                                | (1u << DC_SYSTEM)
887                                | (1u << DC_SCRATCH))) == 0);
888
889   cnt = 0;
890   for (i = 0; i < d->var_cnt; i++)
891     {
892       enum dict_class class = dict_class_from_id (var_get_name (d->var[i]));
893       if (!(exclude_classes & (1u << class)))
894         cnt += var_get_value_cnt (d->var[i]);
895     }
896   return cnt;
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.)
919
920    All variables are compacted if EXCLUDE_CLASSES is 0, or it may
921    contain one or more of (1u << DC_ORDINARY), (1u << DC_SYSTEM),
922    or (1u << DC_SCRATCH) to cause the corresponding type of
923    variable to be deleted during compaction. */
924 struct dict_compactor *
925 dict_make_compactor (const struct dictionary *d, unsigned int exclude_classes)
926 {
927   struct dict_compactor *compactor;
928   struct copy_map *map;
929   size_t map_allocated;
930   size_t value_idx;
931   size_t i;
932
933   assert ((exclude_classes & ~((1u << DC_ORDINARY)
934                                | (1u << DC_SYSTEM)
935                                | (1u << DC_SCRATCH))) == 0);
936
937   compactor = xmalloc (sizeof *compactor);
938   compactor->maps = NULL;
939   compactor->map_cnt = 0;
940   map_allocated = 0;
941
942   value_idx = 0;
943   map = NULL;
944   for (i = 0; i < d->var_cnt; i++)
945     {
946       struct variable *v = d->var[i];
947       enum dict_class class = dict_class_from_id (var_get_name (v));
948       if (exclude_classes & (1u << class))
949         continue;
950
951       if (map != NULL && map->src_idx + map->cnt == var_get_case_index (v))
952         map->cnt += var_get_value_cnt (v);
953       else
954         {
955           if (compactor->map_cnt == map_allocated)
956             compactor->maps = x2nrealloc (compactor->maps, &map_allocated,
957                                           sizeof *compactor->maps);
958           map = &compactor->maps[compactor->map_cnt++];
959           map->src_idx = var_get_case_index (v);
960           map->dst_idx = value_idx;
961           map->cnt = var_get_value_cnt (v);
962         }
963       value_idx += var_get_value_cnt (v);
964     }
965
966   return compactor;
967 }
968
969 /* Compacts SRC by copying it to DST according to the scheme in
970    COMPACTOR.
971
972    Compacting a case eliminates "holes" between values and after
973    the last value.  (Holes are created by deleting variables.) */
974 void
975 dict_compactor_compact (const struct dict_compactor *compactor,
976                         struct ccase *dst, const struct ccase *src)
977 {
978   size_t i;
979
980   for (i = 0; i < compactor->map_cnt; i++)
981     {
982       const struct copy_map *map = &compactor->maps[i];
983       case_copy (dst, map->dst_idx, src, map->src_idx, map->cnt);
984     }
985 }
986
987 /* Destroys COMPACTOR. */
988 void
989 dict_compactor_destroy (struct dict_compactor *compactor)
990 {
991   if (compactor != NULL)
992     {
993       free (compactor->maps);
994       free (compactor);
995     }
996 }
997
998 /* Returns the SPLIT FILE vars (see cmd_split_file()).  Call
999    dict_get_split_cnt() to determine how many SPLIT FILE vars
1000    there are.  Returns a null pointer if and only if there are no
1001    SPLIT FILE vars. */
1002 const struct variable *const *
1003 dict_get_split_vars (const struct dictionary *d)
1004 {
1005   assert (d != NULL);
1006
1007   return d->split;
1008 }
1009
1010 /* Returns the number of SPLIT FILE vars. */
1011 size_t
1012 dict_get_split_cnt (const struct dictionary *d)
1013 {
1014   assert (d != NULL);
1015
1016   return d->split_cnt;
1017 }
1018
1019 /* Removes variable V from the set of split variables in dictionary D */
1020 void
1021 dict_unset_split_var (struct dictionary *d,
1022                       struct variable *v)
1023 {
1024   const int count = d->split_cnt;
1025   d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
1026                                &v, compare_var_ptrs, NULL);
1027
1028   if ( count == d->split_cnt)
1029     return;
1030
1031   if ( d->callbacks &&  d->callbacks->split_changed )
1032     d->callbacks->split_changed (d, d->cb_data);
1033 }
1034
1035 /* Sets CNT split vars SPLIT in dictionary D. */
1036 void
1037 dict_set_split_vars (struct dictionary *d,
1038                      struct variable *const *split, size_t cnt)
1039 {
1040   assert (d != NULL);
1041   assert (cnt == 0 || split != NULL);
1042
1043   d->split_cnt = cnt;
1044   d->split = cnt > 0 ? xnrealloc (d->split, cnt, sizeof *d->split) : NULL;
1045   memcpy (d->split, split, cnt * sizeof *d->split);
1046
1047   if ( d->callbacks &&  d->callbacks->split_changed )
1048     d->callbacks->split_changed (d, d->cb_data);
1049 }
1050
1051 /* Returns the file label for D, or a null pointer if D is
1052    unlabeled (see cmd_file_label()). */
1053 const char *
1054 dict_get_label (const struct dictionary *d)
1055 {
1056   assert (d != NULL);
1057
1058   return d->label;
1059 }
1060
1061 /* Sets D's file label to LABEL, truncating it to a maximum of 60
1062    characters. */
1063 void
1064 dict_set_label (struct dictionary *d, const char *label)
1065 {
1066   assert (d != NULL);
1067
1068   free (d->label);
1069   if (label == NULL)
1070     d->label = NULL;
1071   else if (strlen (label) < 60)
1072     d->label = xstrdup (label);
1073   else
1074     {
1075       d->label = xmalloc (61);
1076       memcpy (d->label, label, 60);
1077       d->label[60] = '\0';
1078     }
1079 }
1080
1081 /* Returns the documents for D, or a null pointer if D has no
1082    documents.  If the return value is nonnull, then the string
1083    will be an exact multiple of DOC_LINE_LENGTH bytes in length,
1084    with each segment corresponding to one line. */
1085 const char *
1086 dict_get_documents (const struct dictionary *d)
1087 {
1088   return ds_is_empty (&d->documents) ? NULL : ds_cstr (&d->documents);
1089 }
1090
1091 /* Sets the documents for D to DOCUMENTS, or removes D's
1092    documents if DOCUMENT is a null pointer.  If DOCUMENTS is
1093    nonnull, then it should be an exact multiple of
1094    DOC_LINE_LENGTH bytes in length, with each segment
1095    corresponding to one line. */
1096 void
1097 dict_set_documents (struct dictionary *d, const char *documents)
1098 {
1099   size_t remainder;
1100
1101   ds_assign_cstr (&d->documents, documents != NULL ? documents : "");
1102
1103   /* In case the caller didn't get it quite right, pad out the
1104      final line with spaces. */
1105   remainder = ds_length (&d->documents) % DOC_LINE_LENGTH;
1106   if (remainder != 0)
1107     ds_put_char_multiple (&d->documents, ' ', DOC_LINE_LENGTH - remainder);
1108 }
1109
1110 /* Drops the documents from dictionary D. */
1111 void
1112 dict_clear_documents (struct dictionary *d)
1113 {
1114   ds_clear (&d->documents);
1115 }
1116
1117 /* Appends LINE to the documents in D.  LINE will be truncated or
1118    padded on the right with spaces to make it exactly
1119    DOC_LINE_LENGTH bytes long. */
1120 void
1121 dict_add_document_line (struct dictionary *d, const char *line)
1122 {
1123   if (strlen (line) > DOC_LINE_LENGTH)
1124     {
1125       /* Note to translators: "bytes" is correct, not characters */
1126       msg (SW, _("Truncating document line to %d bytes."), DOC_LINE_LENGTH);
1127     }
1128   buf_copy_str_rpad (ds_put_uninit (&d->documents, DOC_LINE_LENGTH),
1129                      DOC_LINE_LENGTH, line);
1130 }
1131
1132 /* Returns the number of document lines in dictionary D. */
1133 size_t
1134 dict_get_document_line_cnt (const struct dictionary *d)
1135 {
1136   return ds_length (&d->documents) / DOC_LINE_LENGTH;
1137 }
1138
1139 /* Copies document line number IDX from dictionary D into
1140    LINE, trimming off any trailing white space. */
1141 void
1142 dict_get_document_line (const struct dictionary *d,
1143                         size_t idx, struct string *line)
1144 {
1145   assert (idx < dict_get_document_line_cnt (d));
1146   ds_assign_substring (line, ds_substr (&d->documents, idx * DOC_LINE_LENGTH,
1147                                         DOC_LINE_LENGTH));
1148   ds_rtrim (line, ss_cstr (CC_SPACES));
1149 }
1150
1151 /* Creates in D a vector named NAME that contains the CNT
1152    variables in VAR.  Returns true if successful, or false if a
1153    vector named NAME already exists in D. */
1154 bool
1155 dict_create_vector (struct dictionary *d,
1156                     const char *name,
1157                     struct variable **var, size_t cnt)
1158 {
1159   size_t i;
1160
1161   assert (var != NULL);
1162   assert (cnt > 0);
1163   for (i = 0; i < cnt; i++)
1164     assert (dict_contains_var (d, var[i]));
1165
1166   if (dict_lookup_vector (d, name) == NULL)
1167     {
1168       d->vector = xnrealloc (d->vector, d->vector_cnt + 1, sizeof *d->vector);
1169       d->vector[d->vector_cnt++] = vector_create (name, var, cnt);
1170       return true;
1171     }
1172   else
1173     return false;
1174 }
1175
1176 /* Creates in D a vector named NAME that contains the CNT
1177    variables in VAR.  A vector named NAME must not already exist
1178    in D. */
1179 void
1180 dict_create_vector_assert (struct dictionary *d,
1181                            const char *name,
1182                            struct variable **var, size_t cnt)
1183 {
1184   assert (dict_lookup_vector (d, name) == NULL);
1185   dict_create_vector (d, name, var, cnt);
1186 }
1187
1188 /* Returns the vector in D with index IDX, which must be less
1189    than dict_get_vector_cnt (D). */
1190 const struct vector *
1191 dict_get_vector (const struct dictionary *d, size_t idx)
1192 {
1193   assert (d != NULL);
1194   assert (idx < d->vector_cnt);
1195
1196   return d->vector[idx];
1197 }
1198
1199 /* Returns the number of vectors in D. */
1200 size_t
1201 dict_get_vector_cnt (const struct dictionary *d)
1202 {
1203   assert (d != NULL);
1204
1205   return d->vector_cnt;
1206 }
1207
1208 /* Looks up and returns the vector within D with the given
1209    NAME. */
1210 const struct vector *
1211 dict_lookup_vector (const struct dictionary *d, const char *name)
1212 {
1213   size_t i;
1214   for (i = 0; i < d->vector_cnt; i++)
1215     if (!strcasecmp (vector_get_name (d->vector[i]), name))
1216       return d->vector[i];
1217   return NULL;
1218 }
1219
1220 /* Deletes all vectors from D. */
1221 void
1222 dict_clear_vectors (struct dictionary *d)
1223 {
1224   size_t i;
1225
1226   for (i = 0; i < d->vector_cnt; i++)
1227     vector_destroy (d->vector[i]);
1228   free (d->vector);
1229
1230   d->vector = NULL;
1231   d->vector_cnt = 0;
1232 }
1233
1234 /* Called from variable.c to notify the dictionary that some property of
1235    the variable has changed */
1236 void
1237 dict_var_changed (const struct variable *v)
1238 {
1239   if ( var_has_vardict (v))
1240     {
1241       const struct vardict_info *vdi = var_get_vardict (v);
1242       struct dictionary *d;
1243
1244       d = vdi->dict;
1245
1246       if ( d->callbacks && d->callbacks->var_changed )
1247         d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data);
1248     }
1249 }
1250
1251
1252 /* Called from variable.c to notify the dictionary that the variable's width
1253    has changed */
1254 void
1255 dict_var_resized (const struct variable *v, int delta)
1256 {
1257   if ( var_has_vardict (v))
1258     {
1259       const struct vardict_info *vdi = var_get_vardict (v);
1260       struct dictionary *d;
1261
1262       d = vdi->dict;
1263
1264       dict_pad_values (d, var_get_case_index(v) + 1, delta);
1265
1266       if ( d->callbacks && d->callbacks->var_resized )
1267         d->callbacks->var_resized (d, var_get_dict_index (v), delta, d->cb_data);
1268     }
1269 }