d1807b96f301000f807ccc87fb696d735562530e
[pspp-builds.git] / src / data / mrset.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2010 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 "data/mrset.h"
20
21 #include <stdlib.h>
22
23 #include "data/dictionary.h"
24 #include "data/val-type.h"
25 #include "data/variable.h"
26
27 #include "gl/xalloc.h"
28
29 /* Creates and returns a clone of OLD.  The caller is responsible for freeing
30    the new multiple response set (using mrset_destroy()). */
31 struct mrset *
32 mrset_clone (const struct mrset *old)
33 {
34   struct mrset *new;
35
36   new = xmalloc (sizeof *new);
37   new->name = xstrdup (old->name);
38   new->label = old->label != NULL ? xstrdup (old->label) : NULL;
39   new->type = old->type;
40   new->vars = xmemdup (old->vars, old->n_vars * sizeof *old->vars);
41   new->n_vars = old->n_vars;
42
43   new->cat_source = old->cat_source;
44   new->label_from_var_label = old->label_from_var_label;
45   value_clone (&new->counted, &old->counted, old->width);
46   new->width = old->width;
47
48   return new;
49 }
50
51 /* Frees MRSET and the data that it contains. */
52 void
53 mrset_destroy (struct mrset *mrset)
54 {
55   if (mrset != NULL)
56     {
57       free (mrset->name);
58       free (mrset->label);
59       free (mrset->vars);
60       value_destroy (&mrset->counted, mrset->width);
61       free (mrset);
62     }
63 }
64
65 /* Checks various constraints on MRSET:
66
67    - MRSET has a valid name for a multiple response set (beginning with '$').
68
69    - MRSET has a valid type.
70
71    - MRSET has at least 2 variables.
72
73    - All of MRSET's variables are in DICT.
74
75    - All of MRSET's variables are the same type (numeric or string).
76
77    - If MRSET is a multiple dichotomy set, its counted value has the same type
78      as and is no wider than its narrowest variable.
79
80    Returns true if all the constraints are satisfied, otherwise false. */
81 bool
82 mrset_ok (const struct mrset *mrset, const struct dictionary *dict)
83 {
84   enum val_type type;
85   size_t i;
86
87   if (mrset->name == NULL
88       || mrset->name[0] != '$'
89       || (mrset->type != MRSET_MD && mrset->type != MRSET_MC)
90       || mrset->vars == NULL
91       || mrset->n_vars < 2)
92     return false;
93
94   type = var_get_type (mrset->vars[0]);
95   if (mrset->type == MRSET_MD && type != val_type_from_width (mrset->width))
96     return false;
97   for (i = 0; i < mrset->n_vars; i++)
98     if (!dict_contains_var (dict, mrset->vars[i])
99         || type != var_get_type (mrset->vars[i])
100         || (mrset->type == MRSET_MD
101             && mrset->width > var_get_width (mrset->vars[i])))
102       return false;
103
104   return true;
105 }