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>
25 #include <data/value.h>
26 #include <data/variable.h>
27 #include <libpspp/assertion.h>
28 #include <libpspp/str.h>
33 static size_t case_size (const struct caseproto *);
34 static bool variable_matches_case (const struct ccase *,
35 const struct variable *);
36 static void copy_forward (struct ccase *dst, size_t dst_idx,
37 const struct ccase *src, size_t src_idx,
39 static void copy_backward (struct ccase *dst, size_t dst_idx,
40 const struct ccase *src, size_t src_idx,
43 /* Creates and returns a new case that stores data of the form
44 specified by PROTO. The data in the case have indeterminate
45 contents until explicitly written.
47 The caller retains ownership of PROTO. */
49 case_create (const struct caseproto *proto)
51 struct ccase *c = case_try_create (proto);
57 /* Like case_create, but returns a null pointer if not enough
58 memory is available. */
60 case_try_create (const struct caseproto *proto)
62 struct ccase *c = malloc (case_size (proto));
65 if (caseproto_try_init_values (proto, c->values))
67 c->proto = caseproto_ref (proto);
76 /* Creates and returns an unshared copy of case C. */
78 case_clone (const struct ccase *c)
80 return case_unshare (case_ref (c));
83 /* Returns an estimate of the number of bytes of memory that
84 would be consumed in creating a case based on PROTO. The
85 estimate includes typical overhead from malloc() in addition
86 to the actual size of data. */
88 case_get_cost (const struct caseproto *proto)
90 /* FIXME: improve approximation? */
91 return (1 + caseproto_get_n_widths (proto)
92 + 3 * caseproto_get_n_long_strings (proto)) * sizeof (union value);
95 /* Changes the prototype for case C, which must not be shared.
96 The new PROTO must be conformable with C's current prototype
97 (as defined by caseproto_is_conformable).
99 Any new values created by this function have indeterminate
100 content that the caller is responsible for initializing.
102 The caller retains ownership of PROTO.
104 Returns a new case that replaces C, which is freed. */
106 case_resize (struct ccase *c, const struct caseproto *new_proto)
108 struct caseproto *old_proto = c->proto;
109 size_t old_n_widths = caseproto_get_n_widths (old_proto);
110 size_t new_n_widths = caseproto_get_n_widths (new_proto);
112 assert (!case_is_shared (c));
113 expensive_assert (caseproto_is_conformable (old_proto, new_proto));
115 if (old_n_widths != new_n_widths)
117 if (new_n_widths < old_n_widths)
118 caseproto_reinit_values (old_proto, new_proto, c->values);
119 c = xrealloc (c, case_size (new_proto));
120 if (new_n_widths > old_n_widths)
121 caseproto_reinit_values (old_proto, new_proto, c->values);
123 caseproto_unref (old_proto);
124 c->proto = caseproto_ref (new_proto);
130 /* case_unshare_and_resize(C, PROTO) is equivalent to
131 case_resize(case_unshare(C), PROTO), but it is faster if case
134 Any new values created by this function have indeterminate
135 content that the caller is responsible for initializing.
137 The caller retains ownership of PROTO.
139 Returns the new case that replaces C, which is freed. */
141 case_unshare_and_resize (struct ccase *c, const struct caseproto *proto)
143 if (!case_is_shared (c))
144 return case_resize (c, proto);
147 struct ccase *new = case_create (proto);
148 size_t old_n_values = caseproto_get_n_widths (c->proto);
149 size_t new_n_values = caseproto_get_n_widths (proto);
150 case_copy (new, 0, c, 0, MIN (old_n_values, new_n_values));
156 /* Sets all of the numeric values in case C to the system-missing
157 value, and all of the string values to spaces. */
159 case_set_missing (struct ccase *c)
163 assert (!case_is_shared (c));
164 for (i = 0; i < caseproto_get_n_widths (c->proto); i++)
165 value_set_missing (&c->values[i], caseproto_get_width (c->proto, i));
168 /* Copies N_VALUES values from SRC (starting at SRC_IDX) to DST
169 (starting at DST_IDX). Each value that is copied into must
170 have the same width as the value that it is copied from.
172 Properly handles overlapping ranges when DST == SRC.
174 DST must not be shared. */
176 case_copy (struct ccase *dst, size_t dst_idx,
177 const struct ccase *src, size_t src_idx,
180 assert (!case_is_shared (dst));
181 assert (caseproto_range_is_valid (dst->proto, dst_idx, n_values));
182 assert (caseproto_range_is_valid (src->proto, src_idx, n_values));
183 assert (caseproto_equal (dst->proto, dst_idx, src->proto, src_idx,
188 if (!dst->proto->n_long_strings || !src->proto->n_long_strings)
189 memcpy (&dst->values[dst_idx], &src->values[src_idx],
190 sizeof dst->values[0] * n_values);
192 copy_forward (dst, dst_idx, src, src_idx, n_values);
194 else if (dst_idx != src_idx)
196 if (!dst->proto->n_long_strings)
197 memmove (&dst->values[dst_idx], &src->values[src_idx],
198 sizeof dst->values[0] * n_values);
199 else if (dst_idx < src_idx)
200 copy_forward (dst, dst_idx, src, src_idx, n_values);
201 else /* dst_idx > src_idx */
202 copy_backward (dst, dst_idx, src, src_idx, n_values);
206 /* Copies N_VALUES values out of case C to VALUES, starting at
207 the given START_IDX. */
209 case_copy_out (const struct ccase *c,
210 size_t start_idx, union value *values, size_t n_values)
214 assert (caseproto_range_is_valid (c->proto, start_idx, n_values));
216 for (i = 0; i < n_values; i++)
217 value_copy (&values[i], &c->values[start_idx + i],
218 caseproto_get_width (c->proto, start_idx + i));
221 /* Copies N_VALUES values from VALUES into case C, starting at
224 C must not be shared. */
226 case_copy_in (struct ccase *c,
227 size_t start_idx, const union value *values, size_t n_values)
231 assert (!case_is_shared (c));
232 assert (caseproto_range_is_valid (c->proto, start_idx, n_values));
234 for (i = 0; i < n_values; i++)
235 value_copy (&c->values[start_idx + i], &values[i],
236 caseproto_get_width (c->proto, start_idx + i));
239 /* Returns a pointer to the `union value' used for the
240 element of C for variable V.
241 Case C must be drawn from V's dictionary.
242 The caller must not modify the returned data. */
244 case_data (const struct ccase *c, const struct variable *v)
246 assert (variable_matches_case (c, v));
247 return &c->values[var_get_case_index (v)];
250 /* Returns a pointer to the `union value' used for the element of
251 C numbered IDX. The caller must not modify the returned
254 case_data_idx (const struct ccase *c, size_t idx)
256 assert (idx < c->proto->n_widths);
257 return &c->values[idx];
260 /* Returns a pointer to the `union value' used for the element of
261 C for variable V. Case C must be drawn from V's dictionary.
262 The caller is allowed to modify the returned data.
264 Case C must not be shared. */
266 case_data_rw (struct ccase *c, const struct variable *v)
268 assert (variable_matches_case (c, v));
269 assert (!case_is_shared (c));
270 return &c->values[var_get_case_index (v)];
273 /* Returns a pointer to the `union value' used for the
274 element of C numbered IDX.
275 The caller is allowed to modify the returned data.
277 Case C must not be shared. */
279 case_data_rw_idx (struct ccase *c, size_t idx)
281 assert (idx < c->proto->n_widths);
282 assert (!case_is_shared (c));
283 return &c->values[idx];
286 /* Returns the numeric value of the `union value' in C for
288 Case C must be drawn from V's dictionary. */
290 case_num (const struct ccase *c, const struct variable *v)
292 assert (variable_matches_case (c, v));
293 return c->values[var_get_case_index (v)].f;
296 /* Returns the numeric value of the `union value' in C numbered
299 case_num_idx (const struct ccase *c, size_t idx)
301 assert (idx < c->proto->n_widths);
302 return c->values[idx].f;
305 /* Returns the string value of the `union value' in C for
306 variable V. Case C must be drawn from V's dictionary. The
307 caller must not modify the return value.
309 Like the strings embedded in all "union value"s, the return
310 value is not null-terminated. */
312 case_str (const struct ccase *c, const struct variable *v)
314 size_t idx = var_get_case_index (v);
315 assert (variable_matches_case (c, v));
316 return value_str (&c->values[idx], caseproto_get_width (c->proto, idx));
319 /* Returns the string value of the `union value' in C numbered
320 IDX. The caller must not modify the return value.
322 Like the strings embedded in all "union value"s, the return
323 value is not null-terminated. */
325 case_str_idx (const struct ccase *c, size_t idx)
327 assert (idx < c->proto->n_widths);
328 return value_str (&c->values[idx], caseproto_get_width (c->proto, idx));
331 /* Returns the string value of the `union value' in C for
332 variable V. Case C must be drawn from V's dictionary. The
333 caller may modify the return value.
335 Case C must not be shared.
337 Like the strings embedded in all "union value"s, the return
338 value is not null-terminated. */
340 case_str_rw (struct ccase *c, const struct variable *v)
342 size_t idx = var_get_case_index (v);
343 assert (variable_matches_case (c, v));
344 assert (!case_is_shared (c));
345 return value_str_rw (&c->values[idx], caseproto_get_width (c->proto, idx));
348 /* Returns the string value of the `union value' in C numbered
349 IDX. The caller may modify the return value.
351 Case C must not be shared.
353 Like the strings embedded in all "union value"s, the return
354 value is not null-terminated. */
356 case_str_rw_idx (struct ccase *c, size_t idx)
358 assert (idx < c->proto->n_widths);
359 assert (!case_is_shared (c));
360 return value_str_rw (&c->values[idx], caseproto_get_width (c->proto, idx));
363 /* Compares the values of the N_VARS variables in VP
364 in cases A and B and returns a strcmp()-type result. */
366 case_compare (const struct ccase *a, const struct ccase *b,
367 const struct variable *const *vp, size_t n_vars)
369 return case_compare_2dict (a, b, vp, vp, n_vars);
372 /* Compares the values of the N_VARS variables in VAP in case CA
373 to the values of the N_VARS variables in VBP in CB
374 and returns a strcmp()-type result. */
376 case_compare_2dict (const struct ccase *ca, const struct ccase *cb,
377 const struct variable *const *vap,
378 const struct variable *const *vbp,
382 for (; !cmp && n_vars-- > 0; vap++, vbp++)
384 const union value *va = case_data (ca, *vap);
385 const union value *vb = case_data (cb, *vbp);
386 assert (var_get_width (*vap) == var_get_width (*vbp));
387 cmp = value_compare_3way (va, vb, var_get_width (*vap));
392 /* Returns a pointer to the array of `union value's used for C.
393 The caller must *not* modify the returned data.
395 This function breaks the case abstraction. It should *not* be
396 commonly used. Prefer the other case functions. */
398 case_data_all (const struct ccase *c)
403 /* Returns a pointer to the array of `union value's used for C.
404 The caller is allowed to modify the returned data.
406 Case C must not be shared.
408 This function breaks the case abstraction. It should *not* be
409 commonly used. Prefer the other case functions. */
411 case_data_all_rw (struct ccase *c)
413 assert (!case_is_shared (c));
417 /* Internal helper function for case_unshare. */
419 case_unshare__ (struct ccase *old)
421 struct ccase *new = case_create (old->proto);
422 case_copy (new, 0, old, 0, caseproto_get_n_widths (new->proto));
427 /* Internal helper function for case_unref. */
429 case_unref__ (struct ccase *c)
431 caseproto_destroy_values (c->proto, c->values);
432 caseproto_unref (c->proto);
436 /* Returns the number of bytes needed by a case for case
439 case_size (const struct caseproto *proto)
441 return (offsetof (struct ccase, values)
442 + caseproto_get_n_widths (proto) * sizeof (union value));
445 /* Returns true if C contains a value at V's case index with the
446 same width as V; that is, if V may plausibly be used to read
449 Useful in assertions. */
451 variable_matches_case (const struct ccase *c, const struct variable *v)
453 size_t case_idx = var_get_case_index (v);
454 return (case_idx < caseproto_get_n_widths (c->proto)
455 && caseproto_get_width (c->proto, case_idx) == var_get_width (v));
458 /* Internal helper function for case_copy(). */
460 copy_forward (struct ccase *dst, size_t dst_idx,
461 const struct ccase *src, size_t src_idx,
466 for (i = 0; i < n_values; i++)
467 value_copy (&dst->values[dst_idx + i], &src->values[src_idx + i],
468 caseproto_get_width (dst->proto, dst_idx + i));
471 /* Internal helper function for case_copy(). */
473 copy_backward (struct ccase *dst, size_t dst_idx,
474 const struct ccase *src, size_t src_idx,
479 for (i = n_values; i-- != 0; )
480 value_copy (&dst->values[dst_idx + i], &src->values[src_idx + i],
481 caseproto_get_width (dst->proto, dst_idx + i));