1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2004, 2007, 2009 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 <data/case.h>
26 #include <data/value.h>
27 #include <data/variable.h>
28 #include <libpspp/str.h>
33 /* Returns the number of bytes needed by a case with N_VALUES
36 case_size (size_t n_values)
38 return offsetof (struct ccase, values) + n_values * sizeof (union value);
41 /* Returns true if case C contains COUNT cases starting at index
42 OFS, false if any of those values are out of range for case
44 static inline bool UNUSED
45 range_is_valid (const struct ccase *c, size_t ofs, size_t count)
47 return (count <= c->n_values
49 && ofs + count <= c->n_values);
52 /* Creates and returns a new case that can store N_VALUES values.
53 The values have indeterminate contents until explicitly
56 case_create (size_t n_values)
58 struct ccase *c = case_try_create (n_values);
64 /* Like case_create, but returns a null pointer if not enough
65 memory is available. */
67 case_try_create (size_t n_values)
69 struct ccase *c = malloc (case_size (n_values));
72 c->n_values = n_values;
78 /* Resizes case C, which must not be shared, to N_VALUES union
79 values. If N_VALUES is greater than the current size of case
80 C, then the newly added values have indeterminate content that
81 the caller is responsible for initializing. Returns the new
84 case_resize (struct ccase *c, size_t n_values)
86 assert (!case_is_shared (c));
87 if (n_values != c->n_values)
89 c->n_values = n_values;
90 return xrealloc (c, case_size (n_values));
96 /* case_unshare_and_resize(C, N) is equivalent to
97 case_resize(case_unshare(C), N), but it is faster if case C is
100 Returns the new case.*/
102 case_unshare_and_resize (struct ccase *c, size_t n_values)
104 if (!case_is_shared (c))
105 return case_resize (c, n_values);
108 struct ccase *new = case_create (n_values);
109 case_copy (new, 0, c, 0, MIN (n_values, c->n_values));
115 /* Copies N_VALUES values from SRC (starting at SRC_IDX) to DST
116 (starting at DST_IDX).
118 DST must not be shared. */
120 case_copy (struct ccase *dst, size_t dst_idx,
121 const struct ccase *src, size_t src_idx,
124 assert (!case_is_shared (dst));
125 assert (range_is_valid (dst, dst_idx, n_values));
126 assert (range_is_valid (src, src_idx, n_values));
128 if (dst != src || dst_idx != src_idx)
129 memmove (dst->values + dst_idx, src->values + src_idx,
130 sizeof *dst->values * n_values);
133 /* Copies N_VALUES values out of case C to VALUES, starting at
134 the given START_IDX. */
136 case_copy_out (const struct ccase *c,
137 size_t start_idx, union value *values, size_t n_values)
139 assert (range_is_valid (c, start_idx, n_values));
140 memcpy (values, c->values + start_idx, n_values * sizeof *values);
143 /* Copies N_VALUES values from VALUES into case C, starting at
146 C must not be shared. */
148 case_copy_in (struct ccase *c,
149 size_t start_idx, const union value *values, size_t n_values)
151 assert (!case_is_shared (c));
152 assert (range_is_valid (c, start_idx, n_values));
153 memcpy (c->values + start_idx, values, n_values * sizeof *values);
156 /* Returns a pointer to the `union value' used for the
157 element of C for variable V.
158 Case C must be drawn from V's dictionary.
159 The caller must not modify the returned data. */
161 case_data (const struct ccase *c, const struct variable *v)
163 return case_data_idx (c, var_get_case_index (v));
166 /* Returns a pointer to the `union value' used for the element of
167 C numbered IDX. The caller must not modify the returned
170 case_data_idx (const struct ccase *c, size_t idx)
172 assert (idx < c->n_values);
173 return &c->values[idx];
176 /* Returns a pointer to the `union value' used for the element of
177 C for variable V. Case C must be drawn from V's dictionary.
178 The caller is allowed to modify the returned data.
180 Case C must not be shared. */
182 case_data_rw (struct ccase *c, const struct variable *v)
184 return case_data_rw_idx (c, var_get_case_index (v));
187 /* Returns a pointer to the `union value' used for the
188 element of C numbered IDX.
189 The caller is allowed to modify the returned data.
191 Case C must not be shared. */
193 case_data_rw_idx (struct ccase *c, size_t idx)
195 assert (!case_is_shared (c));
196 assert (idx < c->n_values);
197 return &c->values[idx];
200 /* Returns the numeric value of the `union value' in C for
202 Case C must be drawn from V's dictionary. */
204 case_num (const struct ccase *c, const struct variable *v)
206 return case_num_idx (c, var_get_case_index (v));
209 /* Returns the numeric value of the `union value' in C numbered
212 case_num_idx (const struct ccase *c, size_t idx)
214 assert (idx < c->n_values);
215 return c->values[idx].f;
218 /* Returns the string value of the `union value' in C for
219 variable V. Case C must be drawn from V's dictionary. The
220 caller must not modify the return value.
222 Like all "union value"s, the return value is not
225 case_str (const struct ccase *c, const struct variable *v)
227 return case_str_idx (c, var_get_case_index (v));
230 /* Returns the string value of the `union value' in C numbered
231 IDX. The caller must not modify the return value.
233 Like all "union value"s, the return value is not
236 case_str_idx (const struct ccase *c, size_t idx)
238 assert (idx < c->n_values);
239 return c->values[idx].s;
242 /* Compares the values of the N_VARS variables in VP
243 in cases A and B and returns a strcmp()-type result. */
245 case_compare (const struct ccase *a, const struct ccase *b,
246 const struct variable *const *vp, size_t n_vars)
248 return case_compare_2dict (a, b, vp, vp, n_vars);
251 /* Compares the values of the N_VARS variables in VAP in case CA
252 to the values of the N_VARS variables in VBP in CB
253 and returns a strcmp()-type result. */
255 case_compare_2dict (const struct ccase *ca, const struct ccase *cb,
256 const struct variable *const *vap,
257 const struct variable *const *vbp,
260 for (; n_vars-- > 0; vap++, vbp++)
262 const struct variable *va = *vap;
263 const struct variable *vb = *vbp;
265 assert (var_get_width (va) == var_get_width (vb));
267 if (var_get_width (va) == 0)
269 double af = case_num (ca, va);
270 double bf = case_num (cb, vb);
273 return af > bf ? 1 : -1;
277 const char *as = case_str (ca, va);
278 const char *bs = case_str (cb, vb);
279 int cmp = memcmp (as, bs, var_get_width (va));
288 /* Returns a pointer to the array of `union value's used for C.
289 The caller must *not* modify the returned data.
291 This function breaks the case abstraction. It should *not* be
292 commonly used. Prefer the other case functions. */
294 case_data_all (const struct ccase *c)
299 /* Returns a pointer to the array of `union value's used for C.
300 The caller is allowed to modify the returned data.
302 Case C must not be shared.
304 This function breaks the case abstraction. It should *not* be
305 commonly used. Prefer the other case functions. */
307 case_data_all_rw (struct ccase *c)
309 assert (!case_is_shared (c));
313 /* Internal helper function for case_unshare. */
315 case_unshare__ (struct ccase *old)
317 struct ccase *new = case_create (old->n_values);
318 memcpy (new->values, old->values, old->n_values * sizeof old->values[0]);