Independent Samples T-Test Dialog: Fix Crash
[pspp.git] / src / data / mrset.c
blobc5e00439d55e755877e14257bde78079c9fa6a0f
1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2010, 2011 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/>. */
17 #include <config.h>
19 #include "data/mrset.h"
21 #include <stdlib.h>
23 #include "data/dictionary.h"
24 #include "data/identifier.h"
25 #include "data/val-type.h"
26 #include "data/variable.h"
27 #include "libpspp/message.h"
29 #include "gl/xalloc.h"
31 #include "gettext.h"
32 #define _(msgid) gettext (msgid)
34 /* Creates and returns a clone of OLD. The caller is responsible for freeing
35 the new multiple response set (using mrset_destroy()). */
36 struct mrset *
37 mrset_clone (const struct mrset *old)
39 struct mrset *new;
41 new = xmalloc (sizeof *new);
42 new->name = xstrdup (old->name);
43 new->label = xstrdup_if_nonnull (old->label);
44 new->type = old->type;
45 new->vars = xmemdup (old->vars, old->n_vars * sizeof *old->vars);
46 new->n_vars = old->n_vars;
48 new->cat_source = old->cat_source;
49 new->label_from_var_label = old->label_from_var_label;
50 value_clone (&new->counted, &old->counted, old->width);
51 new->width = old->width;
53 return new;
56 /* Frees MRSET and the data that it contains. */
57 void
58 mrset_destroy (struct mrset *mrset)
60 if (mrset != NULL)
62 free (mrset->name);
63 free (mrset->label);
64 free (mrset->vars);
65 value_destroy (&mrset->counted, mrset->width);
66 free (mrset);
70 /* Checks whether the UTF-8 encoded NAME is a valid name for a multiple
71 response set in a dictionary encoded in DICT_ENCODING. Return NULL if it
72 is, otherwise an error message that the caller must free(). */
73 char * WARN_UNUSED_RESULT
74 mrset_is_valid_name__ (const char *name, const char *dict_encoding)
76 return id_is_valid__ (name, dict_encoding, DC_SYSTEM);
79 static bool
80 error_to_bool (char *error)
82 if (error)
84 free (error);
85 return false;
87 else
88 return true;
91 /* Returns true if the UTF-8 encoded NAME is a valid name for a multiple
92 response set in a dictionary encoded in DICT_ENCODING, false otherwise. */
93 bool
94 mrset_is_valid_name (const char *name, const char *dict_encoding)
96 return error_to_bool (mrset_is_valid_name__ (name, dict_encoding));
99 /* Checks various constraints on MRSET:
101 - MRSET's name begins with '$' and is valid as an identifier in DICT.
103 - MRSET has a valid type.
105 - MRSET has at least 2 variables.
107 - All of MRSET's variables are in DICT.
109 - All of MRSET's variables are the same type (numeric or string).
111 - If MRSET is a multiple dichotomy set, its counted value has the same type
112 as and is no wider than its narrowest variable.
114 Returns true if all the constraints are satisfied, otherwise false. */
115 bool
116 mrset_ok (const struct mrset *mrset, const struct dictionary *dict)
118 enum val_type type;
119 size_t i;
121 if (mrset->name == NULL
122 || !mrset_is_valid_name (mrset->name, dict_get_encoding (dict))
123 || (mrset->type != MRSET_MD && mrset->type != MRSET_MC)
124 || mrset->vars == NULL
125 || mrset->n_vars < 2)
126 return false;
128 type = var_get_type (mrset->vars[0]);
129 if (mrset->type == MRSET_MD && type != val_type_from_width (mrset->width))
130 return false;
131 for (i = 0; i < mrset->n_vars; i++)
132 if (!dict_contains_var (dict, mrset->vars[i])
133 || type != var_get_type (mrset->vars[i])
134 || (mrset->type == MRSET_MD
135 && mrset->width > var_get_width (mrset->vars[i])))
136 return false;
138 return true;