Got rid of "struct long_vec", envector(), devector(), etc.
[pspp-builds.git] / src / dictionary.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18    02111-1307, USA. */
19
20 #include <config.h>
21 #include <assert.h>
22 #include <stdlib.h>
23 #include "algorithm.h"
24 #include "alloc.h"
25 #include "hash.h"
26 #include "misc.h"
27 #include "str.h"
28 #include "value-labels.h"
29 #include "var.h"
30
31 /* A dictionary. */
32 struct dictionary
33   {
34     struct variable **var;      /* Variables. */
35     size_t var_cnt, var_cap;    /* Number of variables, capacity. */
36     struct hsh_table *name_tab; /* Variable index by name. */
37     int value_cnt;              /* Number of `union value's per case. */
38     struct variable **split;    /* SPLIT FILE vars. */
39     size_t split_cnt;           /* SPLIT FILE count. */
40     struct variable *weight;    /* WEIGHT variable. */
41     struct variable *filter;    /* FILTER variable. */
42     int case_limit;             /* Current case limit (N command). */
43     char *label;                /* File label. */
44     char *documents;            /* Documents, as a string. */
45     struct vector **vector;     /* Vectors of variables. */
46     size_t vector_cnt;          /* Number of vectors. */
47   };
48
49 struct dictionary *
50 dict_create (void) 
51 {
52   struct dictionary *d = xmalloc (sizeof *d);
53   
54   d->var = NULL;
55   d->var_cnt = d->var_cap = 0;
56   d->name_tab = hsh_create (8, compare_variables, hash_variable, NULL, NULL);
57   d->value_cnt = 0;
58   d->split = NULL;
59   d->split_cnt = 0;
60   d->weight = NULL;
61   d->filter = NULL;
62   d->case_limit = 0;
63   d->label = NULL;
64   d->documents = NULL;
65   d->vector = NULL;
66   d->vector_cnt = 0;
67
68   return d;
69 }
70
71 struct dictionary *
72 dict_clone (const struct dictionary *s) 
73 {
74   struct dictionary *d;
75   size_t i;
76   
77   assert (s != NULL);
78   
79   d = dict_create ();
80   for (i = 0; i < s->var_cnt; i++)
81     dict_clone_var (d, s->var[i], s->var[i]->name);
82   d->value_cnt = s->value_cnt;
83
84   d->split_cnt = s->split_cnt;
85   if (d->split_cnt > 0) 
86     {
87       d->split = xmalloc (d->split_cnt * sizeof *d->split);
88       for (i = 0; i < d->split_cnt; i++) 
89         d->split[i] = dict_lookup_var_assert (d, s->split[i]->name);
90     }
91
92   if (s->weight != NULL) 
93     d->weight = dict_lookup_var_assert (d, s->weight->name);
94
95   if (s->filter != NULL) 
96     d->filter = dict_lookup_var_assert (d, s->filter->name);
97
98   d->case_limit = s->case_limit;
99   dict_set_label (d, dict_get_label (s));
100   dict_set_documents (d, dict_get_documents (s));
101
102   for (i = 0; i < s->vector_cnt; i++) 
103     dict_create_vector (d, s->vector[i]->name,
104                         s->vector[i]->var, s->vector[i]->cnt);
105
106   return d;
107 }
108
109 void
110 dict_clear (struct dictionary *d) 
111 {
112   /* FIXME?  Should we really clear case_limit, label, documents?
113      Others are necessarily cleared by deleting all the variables.*/
114   int i;
115
116   assert (d != NULL);
117
118   for (i = 0; i < d->var_cnt; i++) 
119     {
120       struct variable *v = d->var[i];
121       val_labs_destroy (v->val_labs);
122       free (v->label);
123       free (v); 
124     }
125   free (d->var);
126   d->var = NULL;
127   d->var_cnt = d->var_cap = 0;
128   hsh_clear (d->name_tab);
129   d->value_cnt = 0;
130   free (d->split);
131   d->split = NULL;
132   d->split_cnt = 0;
133   d->weight = NULL;
134   d->filter = NULL;
135   d->case_limit = 0;
136   free (d->label);
137   d->label = NULL;
138   free (d->documents);
139   d->documents = NULL;
140   dict_clear_vectors (d);
141 }
142
143 void
144 dict_destroy (struct dictionary *d)
145 {
146   if (d != NULL) 
147     {
148       dict_clear (d);
149       hsh_destroy (d->name_tab);
150       free (d);
151     }
152 }
153
154 size_t
155 dict_get_var_cnt (const struct dictionary *d) 
156 {
157   assert (d != NULL);
158
159   return d->var_cnt;
160 }
161
162 struct variable *
163 dict_get_var (const struct dictionary *d, size_t idx) 
164 {
165   assert (d != NULL);
166   assert (idx < d->var_cnt);
167
168   return d->var[idx];
169 }
170
171 void
172 dict_get_vars (const struct dictionary *d, struct variable ***vars,
173                size_t *cnt, unsigned exclude_classes)
174 {
175   size_t count;
176   size_t i;
177   
178   assert (d != NULL);
179   assert (vars != NULL);
180   assert (cnt != NULL);
181   assert ((exclude_classes & ~((1u << DC_ORDINARY)
182                                | (1u << DC_SYSTEM)
183                                | (1u << DC_SCRATCH))) == 0);
184   
185   count = 0;
186   for (i = 0; i < d->var_cnt; i++)
187     if (!(exclude_classes & (1u << dict_class_from_id (d->var[i]->name))))
188       count++;
189
190   *vars = xmalloc (count * sizeof **vars);
191   *cnt = 0;
192   for (i = 0; i < d->var_cnt; i++)
193     if (!(exclude_classes & (1u << dict_class_from_id (d->var[i]->name))))
194       (*vars)[(*cnt)++] = d->var[i];
195   assert (*cnt == count);
196 }
197
198 struct variable *
199 dict_create_var (struct dictionary *d, const char *name, int width) 
200 {
201   struct variable *v;
202
203   assert (d != NULL);
204   assert (name != NULL);
205   assert (strlen (name) >= 1 && strlen (name) <= 8);
206   assert (width >= 0 && width < 256);
207
208   /* Make sure there's not already a variable by that name. */
209   if (dict_lookup_var (d, name) != NULL)
210     return NULL;
211
212   /* Allocate and initialize variable. */
213   v = xmalloc (sizeof *v);
214   strncpy (v->name, name, sizeof v->name);
215   v->name[8] = '\0';
216   v->index = d->var_cnt;
217   v->type = width == 0 ? NUMERIC : ALPHA;
218   v->width = width;
219   v->fv = d->value_cnt;
220   v->nv = width == 0 ? 1 : DIV_RND_UP (width, 8);
221   v->init = 1;
222   v->reinit = name[0] != '#';
223   v->miss_type = MISSING_NONE;
224   if (v->type == NUMERIC)
225     {
226       v->print.type = FMT_F;
227       v->print.w = 8;
228       v->print.d = 2;
229     }
230   else
231     {
232       v->print.type = FMT_A;
233       v->print.w = v->width;
234       v->print.d = 0;
235     }
236   v->val_labs = val_labs_create (v->width);
237   v->label = NULL;
238
239   /* Update dictionary. */
240   if (d->var_cnt >= d->var_cap) 
241     {
242       d->var_cap = 8 + 2 * d->var_cap; 
243       d->var = xrealloc (d->var, d->var_cap * sizeof *d->var);
244     }
245   d->var[v->index] = v;
246   d->var_cnt++;
247   hsh_force_insert (d->name_tab, v);
248   d->value_cnt += v->nv;
249
250   return v;
251 }
252
253 struct variable *
254 dict_create_var_assert (struct dictionary *d, const char *name, int width) 
255 {
256   struct variable *v = dict_create_var (d, name, width);
257   assert (v != NULL);
258   return v;
259 }
260
261 struct variable *
262 dict_clone_var (struct dictionary *d, const struct variable *ov,
263                 const char *name)
264 {
265   struct variable *nv;
266
267   assert (d != NULL);
268   assert (ov != NULL);
269   assert (name != NULL);
270   assert (strlen (name) >= 1 && strlen (name) <= 8);
271
272   nv = dict_create_var (d, name, ov->width);
273   if (nv == NULL)
274     return NULL;
275
276   nv->init = 1;
277   nv->reinit = ov->reinit;
278   nv->miss_type = ov->miss_type;
279   memcpy (nv->missing, ov->missing, sizeof nv->missing);
280   nv->print = ov->print;
281   nv->write = ov->write;
282   val_labs_destroy (nv->val_labs);
283   nv->val_labs = val_labs_copy (ov->val_labs);
284   if (ov->label != NULL)
285     nv->label = xstrdup (ov->label);
286
287   return nv;
288 }
289
290 void 
291 dict_rename_var (struct dictionary *d, struct variable *v,
292                  const char *new_name) 
293 {
294   assert (d != NULL);
295   assert (v != NULL);
296   assert (new_name != NULL);
297   assert (strlen (new_name) >= 1 && strlen (new_name) <= 8);
298
299   if (!strcmp (v->name, new_name))
300     return;
301
302   assert (dict_lookup_var (d, new_name) == NULL);
303
304   hsh_force_delete (d->name_tab, v);
305   strncpy (v->name, new_name, sizeof v->name);
306   v->name[8] = '\0';
307   hsh_force_insert (d->name_tab, v);
308 }
309
310 struct variable *
311 dict_lookup_var (const struct dictionary *d, const char *name)
312 {
313   struct variable v;
314   
315   assert (d != NULL);
316   assert (name != NULL);
317   assert (strlen (name) >= 1 && strlen (name) <= 8);
318
319   strncpy (v.name, name, sizeof v.name);
320   v.name[8] = '\0';
321
322   return hsh_find (d->name_tab, &v);
323 }
324
325 struct variable *
326 dict_lookup_var_assert (const struct dictionary *d, const char *name)
327 {
328   struct variable *v = dict_lookup_var (d, name);
329   assert (v != NULL);
330   return v;
331 }
332
333 int
334 dict_contains_var (const struct dictionary *d, const struct variable *v)
335 {
336   assert (d != NULL);
337   assert (v != NULL);
338
339   return dict_lookup_var (d, v->name) == v;
340 }
341
342 static int
343 compare_variable_dblptrs (const void *a_, const void *b_, void *aux UNUSED) 
344 {
345   struct variable *const *a = a_;
346   struct variable *const *b = b_;
347
348   if (a > b)
349     return 1;
350   else if (a < b)
351     return -1;
352   else
353     return 0;
354 }
355
356 void
357 dict_delete_var (struct dictionary *d, struct variable *v) 
358 {
359   size_t i;
360
361   /* FIXME?  Does not sync d->value_cnt. */
362   assert (d != NULL);
363   assert (v != NULL);
364   assert (dict_contains_var (d, v));
365   assert (d->var[v->index] == v);
366
367   /* Remove v from splits, weight, filter variables. */
368   d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
369                                &v,
370                                compare_variable_dblptrs, NULL);
371   if (d->weight == v)
372     d->weight = NULL;
373   if (d->filter == v)
374     d->filter = NULL;
375   dict_clear_vectors (d);
376
377   /* Remove v from var array. */
378   d->var_cnt--;
379   memmove (d->var + v->index, d->var + v->index + 1,
380            (d->var_cnt - v->index) * sizeof *d->var);
381
382   /* Update index. */
383   for (i = v->index; i < d->var_cnt; i++)
384     d->var[i]->index = i;
385
386   /* Update name hash. */
387   hsh_force_delete (d->name_tab, v);
388
389   /* Free memory. */
390   val_labs_destroy (v->val_labs);
391   free (v->label);
392   free (v);
393
394 }
395
396 void 
397 dict_delete_vars (struct dictionary *d,
398                   struct variable *const *vars, size_t count) 
399 {
400   /* FIXME: this can be done in O(count) time, but this algorithm
401      is O(count**2). */
402   assert (d != NULL);
403   assert (count == 0 || vars != NULL);
404
405   while (count-- > 0)
406     dict_delete_var (d, *vars++);
407 }
408
409 void 
410 dict_reorder_vars (struct dictionary *d,
411                    struct variable *const *order, size_t count) 
412 {
413   struct variable **new_var;
414   size_t i;
415   
416   assert (d != NULL);
417   assert (count == 0 || order != NULL);
418   assert (count <= d->var_cnt);
419
420   new_var = xmalloc (d->var_cnt * sizeof *new_var);
421   memcpy (new_var, order, count * sizeof *new_var);
422   for (i = 0; i < count; i++) 
423     {
424       assert (d->var[order[i]->index] != NULL);
425       d->var[order[i]->index] = NULL;
426       order[i]->index = i;
427     }
428   for (i = 0; i < d->var_cnt; i++)
429     if (d->var[i] != NULL)
430       {
431         assert (count < d->var_cnt);
432         new_var[count] = d->var[i];
433         new_var[count]->index = count;
434         count++;
435       }
436   free (d->var);
437   d->var = new_var;
438 }
439
440 int
441 dict_rename_vars (struct dictionary *d,
442                   struct variable **vars, char **new_names,
443                   size_t count, char **err_name) 
444 {
445   char **old_names;
446   size_t i;
447   int success = 1;
448
449   assert (d != NULL);
450   assert (count == 0 || vars != NULL);
451   assert (count == 0 || new_names != NULL);
452
453   old_names = xmalloc (count * sizeof *old_names);
454   for (i = 0; i < count; i++) 
455     {
456       assert (d->var[vars[i]->index] == vars[i]);
457       hsh_force_delete (d->name_tab, vars[i]);
458       old_names[i] = xstrdup (vars[i]->name);
459     }
460   
461   for (i = 0; i < count; i++)
462     {
463       assert (new_names[i] != NULL);
464       assert (strlen (new_names[i]) < 9);
465       strcpy (vars[i]->name, new_names[i]);
466       if (hsh_insert (d->name_tab, vars[i]) != NULL) 
467         {
468           size_t fail_idx = i;
469           if (err_name != NULL) 
470             *err_name = new_names[i];
471
472           for (i = 0; i < fail_idx; i++)
473             hsh_force_delete (d->name_tab, vars[i]);
474           
475           for (i = 0; i < count; i++)
476             {
477               strcpy (vars[i]->name, old_names[i]);
478               hsh_force_insert (d->name_tab, vars[i]);
479             }
480
481           success = 0;
482           break;
483         }
484     }
485
486   for (i = 0; i < count; i++)
487     free (old_names[i]);
488   free (old_names);
489
490   return success;
491 }
492
493 struct variable *
494 dict_get_weight (const struct dictionary *d) 
495 {
496   assert (d != NULL);
497   assert (d->weight == NULL || dict_contains_var (d, d->weight));
498   
499   return d->weight;
500 }
501
502 double
503 dict_get_case_weight (const struct dictionary *d, const struct ccase *c)
504 {
505   assert (d != NULL);
506   assert (c != NULL);
507
508   if (d->weight == NULL)
509     return 1.0;
510   else 
511     {
512       double w = c->data[d->weight->fv].f;
513       if (w < 0.0)
514         w = 0.0;
515       return w;
516     }
517 }
518
519 void
520 dict_set_weight (struct dictionary *d, struct variable *v) 
521 {
522   assert (d != NULL);
523   assert (v == NULL || dict_contains_var (d, v));
524   assert (v == NULL || v->type == NUMERIC);
525
526   d->weight = v;
527 }
528
529 struct variable *
530 dict_get_filter (const struct dictionary *d) 
531 {
532   assert (d != NULL);
533   assert (d->filter == NULL || dict_contains_var (d, d->filter));
534   
535   return d->filter;
536 }
537
538 void
539 dict_set_filter (struct dictionary *d, struct variable *v)
540 {
541   assert (d != NULL);
542   assert (v == NULL || dict_contains_var (d, v));
543
544   d->filter = v;
545 }
546
547 int
548 dict_get_case_limit (const struct dictionary *d) 
549 {
550   assert (d != NULL);
551
552   return d->case_limit;
553 }
554
555 void
556 dict_set_case_limit (struct dictionary *d, int case_limit) 
557 {
558   assert (d != NULL);
559   assert (case_limit >= 0);
560
561   d->case_limit = case_limit;
562 }
563
564 int
565 dict_get_value_cnt (const struct dictionary *d) 
566 {
567   assert (d != NULL);
568
569   return d->value_cnt;
570 }
571
572 void
573 dict_compact_values (struct dictionary *d) 
574 {
575   size_t i;
576
577   d->value_cnt = 0;
578   for (i = 0; i < d->var_cnt; i++)
579     {
580       struct variable *v = d->var[i];
581
582       v->fv = d->value_cnt;
583       d->value_cnt += v->nv;
584     }
585 }
586
587 struct variable *const *
588 dict_get_split_vars (const struct dictionary *d) 
589 {
590   assert (d != NULL);
591   
592   return d->split;
593 }
594
595 size_t
596 dict_get_split_cnt (const struct dictionary *d) 
597 {
598   assert (d != NULL);
599
600   return d->split_cnt;
601 }
602
603 void
604 dict_set_split_vars (struct dictionary *d,
605                      struct variable *const *split, size_t cnt)
606 {
607   assert (d != NULL);
608   assert (cnt == 0 || split != NULL);
609
610   d->split_cnt = cnt;
611   d->split = xrealloc (d->split, cnt * sizeof *d->split);
612   memcpy (d->split, split, cnt * sizeof *d->split);
613 }
614
615 const char *
616 dict_get_label (const struct dictionary *d) 
617 {
618   assert (d != NULL);
619
620   return d->label;
621 }
622
623 void
624 dict_set_label (struct dictionary *d, const char *label) 
625 {
626   assert (d != NULL);
627
628   free (d->label);
629   if (label == NULL)
630     d->label = NULL;
631   else if (strlen (label) < 60)
632     d->label = xstrdup (label);
633   else 
634     {
635       d->label = xmalloc (61);
636       memcpy (d->label, label, 60);
637       d->label[60] = '\0';
638     }
639 }
640
641 const char *
642 dict_get_documents (const struct dictionary *d) 
643 {
644   assert (d != NULL);
645
646   return d->documents;
647 }
648
649 void
650 dict_set_documents (struct dictionary *d, const char *documents)
651 {
652   assert (d != NULL);
653
654   free (d->documents);
655   if (documents == NULL)
656     d->documents = NULL;
657   else
658     d->documents = xstrdup (documents);
659 }
660
661 int
662 dict_create_vector (struct dictionary *d,
663                     const char *name,
664                     struct variable **var, size_t cnt) 
665 {
666   struct vector *vector;
667
668   assert (d != NULL);
669   assert (name != NULL);
670   assert (strlen (name) > 0 && strlen (name) < 9);
671   assert (var != NULL);
672   assert (cnt > 0);
673   
674   if (dict_lookup_vector (d, name) != NULL)
675     return 0;
676
677   d->vector = xrealloc (d->vector, (d->vector_cnt + 1) * sizeof *d->vector);
678   vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector);
679   vector->idx = d->vector_cnt++;
680   strncpy (vector->name, name, 8);
681   vector->name[8] = '\0';
682   vector->var = xmalloc (cnt * sizeof *var);
683   memcpy (vector->var, var, cnt * sizeof *var);
684   vector->cnt = cnt;
685   
686   return 1;
687 }
688
689 const struct vector *
690 dict_get_vector (const struct dictionary *d, size_t idx) 
691 {
692   assert (d != NULL);
693   assert (idx < d->vector_cnt);
694
695   return d->vector[idx];
696 }
697
698 size_t
699 dict_get_vector_cnt (const struct dictionary *d) 
700 {
701   assert (d != NULL);
702
703   return d->vector_cnt;
704 }
705
706 const struct vector *
707 dict_lookup_vector (const struct dictionary *d, const char *name) 
708 {
709   size_t i;
710
711   assert (d != NULL);
712   assert (name != NULL);
713
714   for (i = 0; i < d->vector_cnt; i++)
715     if (!strcmp (d->vector[i]->name, name))
716       return d->vector[i];
717   return NULL;
718 }
719
720 void
721 dict_clear_vectors (struct dictionary *d) 
722 {
723   size_t i;
724   
725   assert (d != NULL);
726
727   for (i = 0; i < d->vector_cnt; i++) 
728     {
729       free (d->vector[i]->var);
730       free (d->vector[i]);
731     }
732   free (d->vector);
733   d->vector = NULL;
734   d->vector_cnt = 0;
735 }