1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
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.
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.
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/>. */
19 #include "dictionary.h"
27 #include "value-labels.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>
43 #define _(msgid) gettext (msgid)
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
63 void *cb_data ; /* Data passed to callbacks */
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.
73 dict_set_callbacks (struct dictionary *dict,
74 const struct dict_callbacks *callbacks,
77 dict->callbacks = callbacks;
78 dict->cb_data = callback_data;
81 /* Shallow copy the callbacks from SRC to DEST */
83 dict_copy_callbacks (struct dictionary *dest,
84 const struct dictionary *src)
86 dest->callbacks = src->callbacks;
87 dest->cb_data = src->cb_data;
90 /* Creates and returns a new dictionary. */
94 struct dictionary *d = xzalloc (sizeof *d);
96 d->name_tab = hsh_create (8, compare_vars_by_name, hash_var_by_name,
101 /* Creates and returns a (deep) copy of an existing
104 dict_clone (const struct dictionary *s)
106 struct dictionary *d;
113 for (i = 0; i < s->var_cnt; i++)
115 struct variable *sv = s->var[i];
116 struct variable *dv = dict_clone_var_assert (d, sv, var_get_name (sv));
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));
123 d->next_value_idx = s->next_value_idx;
125 d->split_cnt = s->split_cnt;
126 if (d->split_cnt > 0)
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]));
133 if (s->weight != NULL)
134 dict_set_weight (d, dict_lookup_var_assert (d, var_get_name (s->weight)));
136 if (s->filter != NULL)
137 dict_set_filter (d, dict_lookup_var_assert (d, var_get_name (s->filter)));
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));
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);
151 /* Clears the contents from a dictionary without destroying the
152 dictionary itself. */
154 dict_clear (struct dictionary *d)
156 /* FIXME? Should we really clear case_limit, label, documents?
157 Others are necessarily cleared by deleting all the variables.*/
160 while (d->var_cnt > 0 )
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);
167 var_clear_vardict (v);
172 if (d->callbacks && d->callbacks->var_deleted )
173 d->callbacks->var_deleted (d,
174 dict_index, case_index, val_cnt,
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);
189 ds_destroy (&d->documents);
190 dict_clear_vectors (d);
193 /* Destroys the aux data for every variable in D, by calling
194 var_clear_aux() for each variable. */
196 dict_clear_aux (struct dictionary *d)
202 for (i = 0; i < d->var_cnt; i++)
203 var_clear_aux (d->var[i]);
206 /* Clears a dictionary and destroys it. */
208 dict_destroy (struct dictionary *d)
212 /* In general, we don't want callbacks occuring, if the dictionary
213 is being destroyed */
214 d->callbacks = NULL ;
217 hsh_destroy (d->name_tab);
222 /* Returns the number of variables in D. */
224 dict_get_var_cnt (const struct dictionary *d)
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. */
235 dict_get_var (const struct dictionary *d, size_t idx)
238 assert (idx < d->var_cnt);
244 dict_get_vars (const struct dictionary *d, const struct variable ***vars,
245 size_t *cnt, unsigned exclude_classes)
247 dict_get_vars_mutable (d, (struct variable ***) vars, cnt, exclude_classes);
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. */
256 dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
257 size_t *cnt, unsigned exclude_classes)
263 assert (vars != NULL);
264 assert (cnt != NULL);
265 assert ((exclude_classes & ~((1u << DC_ORDINARY)
267 | (1u << DC_SCRATCH))) == 0);
270 for (i = 0; i < d->var_cnt; i++)
272 enum dict_class class = dict_class_from_id (var_get_name (d->var[i]));
273 if (!(exclude_classes & (1u << class)))
277 *vars = xnmalloc (count, sizeof **vars);
279 for (i = 0; i < d->var_cnt; i++)
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];
285 assert (*cnt == count);
288 static struct variable *
289 add_var (struct dictionary *d, struct variable *v)
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;
296 var_set_vardict (v, &vdi);
298 /* Update dictionary. */
299 if (d->var_cnt >= d->var_cap)
301 d->var_cap = 8 + 2 * d->var_cap;
302 d->var = xnrealloc (d->var, d->var_cap, sizeof *d->var);
304 d->var[d->var_cnt++] = v;
305 hsh_force_insert (d->name_tab, v);
307 if ( d->callbacks && d->callbacks->var_added )
308 d->callbacks->var_added (d, var_get_dict_index (v), d->cb_data);
310 d->next_value_idx += var_get_value_cnt (v);
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. */
319 dict_create_var (struct dictionary *d, const char *name, int width)
321 return (dict_lookup_var (d, name) == NULL
322 ? dict_create_var_assert (d, name, width)
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. */
330 dict_create_var_assert (struct dictionary *d, const char *name, int width)
332 assert (dict_lookup_var (d, name) == NULL);
333 return add_var (d, var_create (name, width));
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
342 dict_clone_var (struct dictionary *d, const struct variable *old_var,
345 return (dict_lookup_var (d, name) == NULL
346 ? dict_clone_var_assert (d, old_var, name)
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. */
355 dict_clone_var_assert (struct dictionary *d, const struct variable *old_var,
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);
364 /* Returns the variable named NAME in D, or a null pointer if no
365 variable has that name. */
367 dict_lookup_var (const struct dictionary *d, const char *name)
369 struct variable *target ;
370 struct variable *result ;
372 if ( ! var_is_valid_name (name, false))
375 target = var_create (name, 0);
376 result = hsh_find (d->name_tab, target);
377 var_destroy (target);
382 /* Returns the variable named NAME in D. Assert-fails if no
383 variable has that name. */
385 dict_lookup_var_assert (const struct dictionary *d, const char *name)
387 struct variable *v = dict_lookup_var (d, name);
392 /* Returns true if variable V is in dictionary D,
395 dict_contains_var (const struct dictionary *d, const struct variable *v)
397 if (var_has_vardict (v))
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);
408 /* Compares two double pointers to variables, which should point
409 to elements of a struct dictionary's `var' member array. */
411 compare_var_ptrs (const void *a_, const void *b_, const void *aux UNUSED)
413 struct variable *const *a = a_;
414 struct variable *const *b = b_;
416 return *a < *b ? -1 : *a > *b;
419 /* Sets the dict_index in V's vardict to DICT_INDEX. */
421 set_var_dict_index (struct variable *v, int dict_index)
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);
428 if ( d->callbacks && d->callbacks->var_changed )
429 d->callbacks->var_changed (d, dict_index, d->cb_data);
432 /* Sets the case_index in V's vardict to CASE_INDEX. */
434 set_var_case_index (struct variable *v, int case_index)
436 struct vardict_info vdi = *var_get_vardict (v);
437 vdi.case_index = case_index;
438 var_set_vardict (v, &vdi);
441 /* Re-sets the dict_index in the dictionary variables with
442 indexes from FROM to TO (exclusive). */
444 reindex_vars (struct dictionary *d, size_t from, size_t to)
448 for (i = from; i < to; i++)
449 set_var_dict_index (d->var[i], i);
452 /* Deletes variable V from dictionary D and frees V.
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.
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. */
466 dict_delete_var (struct dictionary *d, struct variable *v)
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);
472 assert (dict_contains_var (d, v));
474 /* Delete aux data. */
477 dict_unset_split_var (d, v);
480 dict_set_weight (d, NULL);
483 dict_set_filter (d, NULL);
485 dict_clear_vectors (d);
487 /* Remove V from var array. */
488 remove_element (d->var, d->var_cnt, sizeof *d->var, dict_index);
491 /* Update dict_index for each affected variable. */
492 reindex_vars (d, dict_index, d->var_cnt);
494 /* Update name hash. */
495 hsh_force_delete (d->name_tab, v);
499 var_clear_vardict (v);
502 if (d->callbacks && d->callbacks->var_deleted )
503 d->callbacks->var_deleted (d, dict_index, case_index, val_cnt, d->cb_data);
506 /* Deletes the COUNT variables listed in VARS from D. This is
507 unsafe; see the comment on dict_delete_var() for details. */
509 dict_delete_vars (struct dictionary *d,
510 struct variable *const *vars, size_t count)
512 /* FIXME: this can be done in O(count) time, but this algorithm
515 assert (count == 0 || vars != NULL);
518 dict_delete_var (d, *vars++);
521 /* Deletes the COUNT variables in D starting at index IDX. This
522 is unsafe; see the comment on dict_delete_var() for
525 dict_delete_consecutive_vars (struct dictionary *d, size_t idx, size_t count)
527 /* FIXME: this can be done in O(count) time, but this algorithm
529 assert (idx + count <= d->var_cnt);
532 dict_delete_var (d, d->var[idx]);
535 /* Deletes scratch variables from dictionary D. */
537 dict_delete_scratch_vars (struct dictionary *d)
541 /* FIXME: this can be done in O(count) time, but this algorithm
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]);
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. */
556 dict_reorder_var (struct dictionary *d, struct variable *v, size_t new_index)
558 size_t old_index = var_get_dict_index (v);
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);
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
570 dict_reorder_vars (struct dictionary *d,
571 struct variable *const *order, size_t count)
573 struct variable **new_var;
577 assert (count == 0 || order != NULL);
578 assert (count <= d->var_cnt);
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++)
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);
589 for (i = 0; i < d->var_cnt; i++)
590 if (d->var[i] != NULL)
592 assert (count < d->var_cnt);
593 new_var[count] = d->var[i];
594 set_var_dict_index (new_var[count], count);
601 /* Changes the name of variable V in dictionary D to NEW_NAME. */
603 rename_var (struct dictionary *d, struct variable *v, const char *new_name)
605 struct vardict_info vdi;
607 assert (dict_contains_var (d, v));
609 vdi = *var_get_vardict (v);
610 var_clear_vardict (v);
611 var_set_name (v, new_name);
612 var_set_vardict (v, &vdi);
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. */
619 dict_rename_var (struct dictionary *d, struct variable *v,
620 const char *new_name)
622 assert (!strcasecmp (var_get_name (v), new_name)
623 || dict_lookup_var (d, new_name) == NULL);
625 hsh_force_delete (d->name_tab, v);
626 rename_var (d, v, new_name);
627 hsh_force_insert (d->name_tab, v);
629 if (get_algorithm () == ENHANCED)
630 var_clear_short_names (v);
632 if ( d->callbacks && d->callbacks->var_changed )
633 d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data);
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
643 dict_rename_vars (struct dictionary *d,
644 struct variable **vars, char **new_names, size_t count,
651 assert (count == 0 || vars != NULL);
652 assert (count == 0 || new_names != NULL);
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]));
660 /* Remove the variables to be renamed from the name hash,
662 for (i = 0; i < count; i++)
664 hsh_force_delete (d->name_tab, vars[i]);
665 rename_var (d, vars[i], new_names[i]);
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)
673 /* There is a name conflict.
674 Back out all the name changes that have already
675 taken place, and indicate failure. */
677 if (err_name != NULL)
678 *err_name = new_names[i];
680 for (i = 0; i < fail_idx; i++)
681 hsh_force_delete (d->name_tab, vars[i]);
683 for (i = 0; i < count; i++)
685 rename_var (d, vars[i], old_names[i]);
686 hsh_force_insert (d->name_tab, vars[i]);
693 /* Clear short names. */
694 if (get_algorithm () == ENHANCED)
695 for (i = 0; i < count; i++)
696 var_clear_short_names (vars[i]);
702 /* Returns the weighting variable in dictionary D, or a null
703 pointer if the dictionary is unweighted. */
705 dict_get_weight (const struct dictionary *d)
708 assert (d->weight == NULL || dict_contains_var (d, d->weight));
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. */
719 dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
720 bool *warn_on_invalid)
725 if (d->weight == NULL)
729 double w = case_num (c, d->weight);
730 if (w < 0.0 || var_is_num_missing (d->weight, w, MV_ANY))
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."));
742 /* Sets the weighting variable of D to V, or turning off
743 weighting if V is a null pointer. */
745 dict_set_weight (struct dictionary *d, struct variable *v)
748 assert (v == NULL || dict_contains_var (d, v));
749 assert (v == NULL || var_is_numeric (v));
753 if ( d->callbacks && d->callbacks->weight_changed )
754 d->callbacks->weight_changed (d,
755 v ? var_get_dict_index (v) : -1,
759 /* Returns the filter variable in dictionary D (see cmd_filter())
760 or a null pointer if the dictionary is unfiltered. */
762 dict_get_filter (const struct dictionary *d)
765 assert (d->filter == NULL || dict_contains_var (d, d->filter));
770 /* Sets V as the filter variable for dictionary D. Passing a
771 null pointer for V turn off filtering. */
773 dict_set_filter (struct dictionary *d, struct variable *v)
776 assert (v == NULL || dict_contains_var (d, v));
780 if ( d->callbacks && d->callbacks->filter_changed )
781 d->callbacks->filter_changed (d,
782 v ? var_get_dict_index (v) : -1,
786 /* Returns the case limit for dictionary D, or zero if the number
787 of cases is unlimited. */
789 dict_get_case_limit (const struct dictionary *d)
793 return d->case_limit;
796 /* Sets CASE_LIMIT as the case limit for dictionary D. Use
797 0 for CASE_LIMIT to indicate no limit. */
799 dict_set_case_limit (struct dictionary *d, size_t case_limit)
803 d->case_limit = case_limit;
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. */
810 dict_get_next_value_idx (const struct dictionary *d)
814 return d->next_value_idx;
817 /* Returns the number of bytes needed to store a case for
820 dict_get_case_size (const struct dictionary *d)
824 return sizeof (union value) * dict_get_next_value_idx (d);
827 /* Deletes scratch variables in dictionary D and reassigns values
828 so that fragmentation is eliminated. */
830 dict_compact_values (struct dictionary *d)
834 d->next_value_idx = 0;
835 for (i = 0; i < d->var_cnt; )
837 struct variable *v = d->var[i];
839 if (dict_class_from_id (var_get_name (v)) != DC_SCRATCH)
841 set_var_case_index (v, d->next_value_idx);
842 d->next_value_idx += var_get_value_cnt (v);
846 dict_delete_var (d, v);
852 Reassigns case indices for D, increasing each index above START by
856 dict_pad_values (struct dictionary *d, int start, int padding)
863 for (i = 0; i < d->var_cnt; ++i)
865 struct variable *v = d->var[i];
867 int index = var_get_case_index (v);
870 set_var_case_index (v, index + padding);
873 d->next_value_idx += padding;
877 /* Returns the number of values that would be used by a case if
878 dict_compact_values() were called. */
880 dict_get_compacted_value_cnt (const struct dictionary *d)
886 for (i = 0; i < d->var_cnt; i++)
887 if (dict_class_from_id (var_get_name (d->var[i])) != DC_SCRATCH)
888 cnt += var_get_value_cnt (d->var[i]);
892 /* Creates and returns an array mapping from a dictionary index
893 to the case index that the corresponding variable will have
894 after calling dict_compact_values(). Scratch variables
895 receive -1 for case index because dict_compact_values() will
898 dict_get_compacted_dict_index_to_case_index (const struct dictionary *d)
901 size_t next_value_idx;
904 map = xnmalloc (d->var_cnt, sizeof *map);
906 for (i = 0; i < d->var_cnt; i++)
908 struct variable *v = d->var[i];
910 if (dict_class_from_id (var_get_name (v)) != DC_SCRATCH)
912 map[i] = next_value_idx;
913 next_value_idx += var_get_value_cnt (v);
921 /* Returns true if a case for dictionary D would be smaller after
922 compacting, false otherwise. Compacting a case eliminates
923 "holes" between values and after the last value. Holes are
924 created by deleting variables (or by scratch variables).
926 The return value may differ from whether compacting a case
927 from dictionary D would *change* the case: compacting could
928 rearrange values even if it didn't reduce space
931 dict_compacting_would_shrink (const struct dictionary *d)
933 return dict_get_compacted_value_cnt (d) < dict_get_next_value_idx (d);
936 /* Returns true if a case for dictionary D would change after
937 compacting, false otherwise. Compacting a case eliminates
938 "holes" between values and after the last value. Holes are
939 created by deleting variables (or by scratch variables).
941 The return value may differ from whether compacting a case
942 from dictionary D would *shrink* the case: compacting could
943 rearrange values without reducing space requirements. */
945 dict_compacting_would_change (const struct dictionary *d)
951 for (i = 0; i < dict_get_var_cnt (d); i++)
953 struct variable *v = dict_get_var (d, i);
954 if (var_get_case_index (v) != case_idx)
956 case_idx += var_get_value_cnt (v);
961 /* How to copy a contiguous range of values between cases. */
964 size_t src_idx; /* Starting value index in source case. */
965 size_t dst_idx; /* Starting value index in target case. */
966 size_t cnt; /* Number of values. */
969 /* How to compact a case. */
970 struct dict_compactor
972 struct copy_map *maps; /* Array of mappings. */
973 size_t map_cnt; /* Number of mappings. */
976 /* Creates and returns a dict_compactor that can be used to
977 compact cases for dictionary D.
979 Compacting a case eliminates "holes" between values and after
980 the last value. Holes are created by deleting variables (or
981 by scratch variables). */
982 struct dict_compactor *
983 dict_make_compactor (const struct dictionary *d)
985 struct dict_compactor *compactor;
986 struct copy_map *map;
987 size_t map_allocated;
991 compactor = xmalloc (sizeof *compactor);
992 compactor->maps = NULL;
993 compactor->map_cnt = 0;
998 for (i = 0; i < d->var_cnt; i++)
1000 struct variable *v = d->var[i];
1002 if (dict_class_from_id (var_get_name (v)) == DC_SCRATCH)
1004 if (map != NULL && map->src_idx + map->cnt == var_get_case_index (v))
1005 map->cnt += var_get_value_cnt (v);
1008 if (compactor->map_cnt == map_allocated)
1009 compactor->maps = x2nrealloc (compactor->maps, &map_allocated,
1010 sizeof *compactor->maps);
1011 map = &compactor->maps[compactor->map_cnt++];
1012 map->src_idx = var_get_case_index (v);
1013 map->dst_idx = value_idx;
1014 map->cnt = var_get_value_cnt (v);
1016 value_idx += var_get_value_cnt (v);
1022 /* Compacts SRC by copying it to DST according to the scheme in
1025 Compacting a case eliminates "holes" between values and after
1026 the last value. Holes are created by deleting variables (or
1027 by scratch variables). */
1029 dict_compactor_compact (const struct dict_compactor *compactor,
1030 struct ccase *dst, const struct ccase *src)
1034 for (i = 0; i < compactor->map_cnt; i++)
1036 const struct copy_map *map = &compactor->maps[i];
1037 case_copy (dst, map->dst_idx, src, map->src_idx, map->cnt);
1041 /* Destroys COMPACTOR. */
1043 dict_compactor_destroy (struct dict_compactor *compactor)
1045 if (compactor != NULL)
1047 free (compactor->maps);
1052 /* Returns the SPLIT FILE vars (see cmd_split_file()). Call
1053 dict_get_split_cnt() to determine how many SPLIT FILE vars
1054 there are. Returns a null pointer if and only if there are no
1056 const struct variable *const *
1057 dict_get_split_vars (const struct dictionary *d)
1064 /* Returns the number of SPLIT FILE vars. */
1066 dict_get_split_cnt (const struct dictionary *d)
1070 return d->split_cnt;
1073 /* Removes variable V from the set of split variables in dictionary D */
1075 dict_unset_split_var (struct dictionary *d,
1078 const int count = d->split_cnt;
1079 d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
1080 &v, compare_var_ptrs, NULL);
1082 if ( count == d->split_cnt)
1085 if ( d->callbacks && d->callbacks->split_changed )
1086 d->callbacks->split_changed (d, d->cb_data);
1089 /* Sets CNT split vars SPLIT in dictionary D. */
1091 dict_set_split_vars (struct dictionary *d,
1092 struct variable *const *split, size_t cnt)
1095 assert (cnt == 0 || split != NULL);
1098 d->split = cnt > 0 ? xnrealloc (d->split, cnt, sizeof *d->split) : NULL;
1099 memcpy (d->split, split, cnt * sizeof *d->split);
1101 if ( d->callbacks && d->callbacks->split_changed )
1102 d->callbacks->split_changed (d, d->cb_data);
1105 /* Returns the file label for D, or a null pointer if D is
1106 unlabeled (see cmd_file_label()). */
1108 dict_get_label (const struct dictionary *d)
1115 /* Sets D's file label to LABEL, truncating it to a maximum of 60
1118 dict_set_label (struct dictionary *d, const char *label)
1125 else if (strlen (label) < 60)
1126 d->label = xstrdup (label);
1129 d->label = xmalloc (61);
1130 memcpy (d->label, label, 60);
1131 d->label[60] = '\0';
1135 /* Returns the documents for D, or a null pointer if D has no
1136 documents. If the return value is nonnull, then the string
1137 will be an exact multiple of DOC_LINE_LENGTH bytes in length,
1138 with each segment corresponding to one line. */
1140 dict_get_documents (const struct dictionary *d)
1142 return ds_is_empty (&d->documents) ? NULL : ds_cstr (&d->documents);
1145 /* Sets the documents for D to DOCUMENTS, or removes D's
1146 documents if DOCUMENT is a null pointer. If DOCUMENTS is
1147 nonnull, then it should be an exact multiple of
1148 DOC_LINE_LENGTH bytes in length, with each segment
1149 corresponding to one line. */
1151 dict_set_documents (struct dictionary *d, const char *documents)
1155 ds_assign_cstr (&d->documents, documents != NULL ? documents : "");
1157 /* In case the caller didn't get it quite right, pad out the
1158 final line with spaces. */
1159 remainder = ds_length (&d->documents) % DOC_LINE_LENGTH;
1161 ds_put_char_multiple (&d->documents, ' ', DOC_LINE_LENGTH - remainder);
1164 /* Drops the documents from dictionary D. */
1166 dict_clear_documents (struct dictionary *d)
1168 ds_clear (&d->documents);
1171 /* Appends LINE to the documents in D. LINE will be truncated or
1172 padded on the right with spaces to make it exactly
1173 DOC_LINE_LENGTH bytes long. */
1175 dict_add_document_line (struct dictionary *d, const char *line)
1177 if (strlen (line) > DOC_LINE_LENGTH)
1179 /* Note to translators: "bytes" is correct, not characters */
1180 msg (SW, _("Truncating document line to %d bytes."), DOC_LINE_LENGTH);
1182 buf_copy_str_rpad (ds_put_uninit (&d->documents, DOC_LINE_LENGTH),
1183 DOC_LINE_LENGTH, line);
1186 /* Returns the number of document lines in dictionary D. */
1188 dict_get_document_line_cnt (const struct dictionary *d)
1190 return ds_length (&d->documents) / DOC_LINE_LENGTH;
1193 /* Copies document line number IDX from dictionary D into
1194 LINE, trimming off any trailing white space. */
1196 dict_get_document_line (const struct dictionary *d,
1197 size_t idx, struct string *line)
1199 assert (idx < dict_get_document_line_cnt (d));
1200 ds_assign_substring (line, ds_substr (&d->documents, idx * DOC_LINE_LENGTH,
1202 ds_rtrim (line, ss_cstr (CC_SPACES));
1205 /* Creates in D a vector named NAME that contains the CNT
1206 variables in VAR. Returns true if successful, or false if a
1207 vector named NAME already exists in D. */
1209 dict_create_vector (struct dictionary *d,
1211 struct variable **var, size_t cnt)
1215 assert (var != NULL);
1217 for (i = 0; i < cnt; i++)
1218 assert (dict_contains_var (d, var[i]));
1220 if (dict_lookup_vector (d, name) == NULL)
1222 d->vector = xnrealloc (d->vector, d->vector_cnt + 1, sizeof *d->vector);
1223 d->vector[d->vector_cnt++] = vector_create (name, var, cnt);
1230 /* Creates in D a vector named NAME that contains the CNT
1231 variables in VAR. A vector named NAME must not already exist
1234 dict_create_vector_assert (struct dictionary *d,
1236 struct variable **var, size_t cnt)
1238 assert (dict_lookup_vector (d, name) == NULL);
1239 dict_create_vector (d, name, var, cnt);
1242 /* Returns the vector in D with index IDX, which must be less
1243 than dict_get_vector_cnt (D). */
1244 const struct vector *
1245 dict_get_vector (const struct dictionary *d, size_t idx)
1248 assert (idx < d->vector_cnt);
1250 return d->vector[idx];
1253 /* Returns the number of vectors in D. */
1255 dict_get_vector_cnt (const struct dictionary *d)
1259 return d->vector_cnt;
1262 /* Looks up and returns the vector within D with the given
1264 const struct vector *
1265 dict_lookup_vector (const struct dictionary *d, const char *name)
1268 for (i = 0; i < d->vector_cnt; i++)
1269 if (!strcasecmp (vector_get_name (d->vector[i]), name))
1270 return d->vector[i];
1274 /* Deletes all vectors from D. */
1276 dict_clear_vectors (struct dictionary *d)
1280 for (i = 0; i < d->vector_cnt; i++)
1281 vector_destroy (d->vector[i]);
1288 /* Called from variable.c to notify the dictionary that some property of
1289 the variable has changed */
1291 dict_var_changed (const struct variable *v)
1293 if ( var_has_vardict (v))
1295 const struct vardict_info *vdi = var_get_vardict (v);
1296 struct dictionary *d;
1300 if ( d->callbacks && d->callbacks->var_changed )
1301 d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data);
1306 /* Called from variable.c to notify the dictionary that the variable's width
1309 dict_var_resized (const struct variable *v, int delta)
1311 if ( var_has_vardict (v))
1313 const struct vardict_info *vdi = var_get_vardict (v);
1314 struct dictionary *d;
1318 dict_pad_values (d, var_get_case_index(v) + 1, delta);
1320 if ( d->callbacks && d->callbacks->var_resized )
1321 d->callbacks->var_resized (d, var_get_dict_index (v), delta, d->cb_data);