Change union value type to contain uint8_t types instead of char.
[pspp-builds.git] / src / data / case.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2004, 2007, 2009 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/case.h>
20
21 #include <limits.h>
22 #include <stddef.h>
23 #include <stdlib.h>
24
25 #include <data/value.h>
26 #include <data/variable.h>
27 #include <libpspp/assertion.h>
28 #include <libpspp/str.h>
29
30 #include "minmax.h"
31 #include "xalloc.h"
32
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,
38                           size_t n_values);
39 static void copy_backward (struct ccase *dst, size_t dst_idx,
40                            const struct ccase *src, size_t src_idx,
41                            size_t n_values);
42
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.
46
47    The caller retains ownership of PROTO. */
48 struct ccase *
49 case_create (const struct caseproto *proto)
50 {
51   struct ccase *c = case_try_create (proto);
52   if (c == NULL)
53     xalloc_die ();
54   return c;
55 }
56
57 /* Like case_create, but returns a null pointer if not enough
58    memory is available. */
59 struct ccase *
60 case_try_create (const struct caseproto *proto)
61 {
62   struct ccase *c = malloc (case_size (proto));
63   if (c != NULL)
64     {
65       if (caseproto_try_init_values (proto, c->values))
66         {
67           c->proto = caseproto_ref (proto);
68           c->ref_cnt = 1;
69           return c;
70         }
71       free (c);
72     }
73   return NULL;
74 }
75
76 /* Creates and returns an unshared copy of case C. */
77 struct ccase *
78 case_clone (const struct ccase *c)
79 {
80   return case_unshare (case_ref (c));
81 }
82
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. */
87 size_t
88 case_get_cost (const struct caseproto *proto)
89 {
90   /* FIXME: improve approximation? */
91   return (1 + caseproto_get_n_widths (proto)
92           + 3 * caseproto_get_n_long_strings (proto)) * sizeof (union value);
93 }
94
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).
98
99    Any new values created by this function have indeterminate
100    content that the caller is responsible for initializing.
101
102    The caller retains ownership of PROTO.
103
104    Returns a new case that replaces C, which is freed. */
105 struct ccase *
106 case_resize (struct ccase *c, const struct caseproto *new_proto)
107 {
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);
111
112   assert (!case_is_shared (c));
113   expensive_assert (caseproto_is_conformable (old_proto, new_proto));
114
115   if (old_n_widths != new_n_widths)
116     {
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);
122
123       caseproto_unref (old_proto);
124       c->proto = caseproto_ref (new_proto);
125     }
126
127   return c;
128 }
129
130 /* case_unshare_and_resize(C, PROTO) is equivalent to
131    case_resize(case_unshare(C), PROTO), but it is faster if case
132    C is shared.
133
134    Any new values created by this function have indeterminate
135    content that the caller is responsible for initializing.
136
137    The caller retains ownership of PROTO.
138
139    Returns the new case that replaces C, which is freed. */
140 struct ccase *
141 case_unshare_and_resize (struct ccase *c, const struct caseproto *proto)
142 {
143   if (!case_is_shared (c))
144     return case_resize (c, proto);
145   else
146     {
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));
151       c->ref_cnt--;
152       return new;
153     }
154 }
155
156 /* Sets all of the numeric values in case C to the system-missing
157    value, and all of the string values to spaces. */
158 void
159 case_set_missing (struct ccase *c)
160 {
161   size_t i;
162
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));
166 }
167
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.
171
172    Properly handles overlapping ranges when DST == SRC.
173
174    DST must not be shared. */
175 void
176 case_copy (struct ccase *dst, size_t dst_idx,
177            const struct ccase *src, size_t src_idx,
178            size_t n_values)
179 {
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,
184                            n_values));
185
186   if (dst != src)
187     {
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);
191       else
192         copy_forward (dst, dst_idx, src, src_idx, n_values);
193     }
194   else if (dst_idx != src_idx)
195     {
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);
203     }
204 }
205
206 /* Copies N_VALUES values out of case C to VALUES, starting at
207    the given START_IDX. */
208 void
209 case_copy_out (const struct ccase *c,
210                size_t start_idx, union value *values, size_t n_values)
211 {
212   size_t i;
213
214   assert (caseproto_range_is_valid (c->proto, start_idx, n_values));
215
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));
219 }
220
221 /* Copies N_VALUES values from VALUES into case C, starting at
222    the given START_IDX.
223
224    C must not be shared. */
225 void
226 case_copy_in (struct ccase *c,
227               size_t start_idx, const union value *values, size_t n_values)
228 {
229   size_t i;
230
231   assert (!case_is_shared (c));
232   assert (caseproto_range_is_valid (c->proto, start_idx, n_values));
233
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));
237 }
238
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. */
243 const union value *
244 case_data (const struct ccase *c, const struct variable *v)
245 {
246   assert (variable_matches_case (c, v));
247   return &c->values[var_get_case_index (v)];
248 }
249
250 /* Returns a pointer to the `union value' used for the element of
251    C numbered IDX.  The caller must not modify the returned
252    data. */
253 const union value *
254 case_data_idx (const struct ccase *c, size_t idx)
255 {
256   assert (idx < c->proto->n_widths);
257   return &c->values[idx];
258 }
259
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.
263
264    Case C must not be shared. */
265 union value *
266 case_data_rw (struct ccase *c, const struct variable *v)
267 {
268   assert (variable_matches_case (c, v));
269   assert (!case_is_shared (c));
270   return &c->values[var_get_case_index (v)];
271 }
272
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.
276
277    Case C must not be shared. */
278 union value *
279 case_data_rw_idx (struct ccase *c, size_t idx)
280 {
281   assert (idx < c->proto->n_widths);
282   assert (!case_is_shared (c));
283   return &c->values[idx];
284 }
285
286 /* Returns the numeric value of the `union value' in C for
287    variable V.
288    Case C must be drawn from V's dictionary. */
289 double
290 case_num (const struct ccase *c, const struct variable *v)
291 {
292   assert (variable_matches_case (c, v));
293   return c->values[var_get_case_index (v)].f;
294 }
295
296 /* Returns the numeric value of the `union value' in C numbered
297    IDX. */
298 double
299 case_num_idx (const struct ccase *c, size_t idx)
300 {
301   assert (idx < c->proto->n_widths);
302   return c->values[idx].f;
303 }
304
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.
308
309    Like the strings embedded in all "union value"s, the return
310    value is not null-terminated. */
311 const uint8_t *
312 case_str (const struct ccase *c, const struct variable *v)
313 {
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));
317 }
318
319 /* Returns the string value of the `union value' in C numbered
320    IDX.  The caller must not modify the return value.
321
322    Like the strings embedded in all "union value"s, the return
323    value is not null-terminated. */
324 const uint8_t *
325 case_str_idx (const struct ccase *c, size_t idx)
326 {
327   assert (idx < c->proto->n_widths);
328   return value_str (&c->values[idx], caseproto_get_width (c->proto, idx));
329 }
330
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.
334
335    Case C must not be shared.
336
337    Like the strings embedded in all "union value"s, the return
338    value is not null-terminated. */
339 uint8_t *
340 case_str_rw (struct ccase *c, const struct variable *v)
341 {
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));
346 }
347
348 /* Returns the string value of the `union value' in C numbered
349    IDX.  The caller may modify the return value.
350
351    Case C must not be shared.
352
353    Like the strings embedded in all "union value"s, the return
354    value is not null-terminated. */
355 uint8_t *
356 case_str_rw_idx (struct ccase *c, size_t idx)
357 {
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));
361 }
362
363 /* Compares the values of the N_VARS variables in VP
364    in cases A and B and returns a strcmp()-type result. */
365 int
366 case_compare (const struct ccase *a, const struct ccase *b,
367               const struct variable *const *vp, size_t n_vars)
368 {
369   return case_compare_2dict (a, b, vp, vp, n_vars);
370 }
371
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. */
375 int
376 case_compare_2dict (const struct ccase *ca, const struct ccase *cb,
377                     const struct variable *const *vap,
378                     const struct variable *const *vbp,
379                     size_t n_vars)
380 {
381   int cmp = 0;
382   for (; !cmp && n_vars-- > 0; vap++, vbp++)
383     {
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)); 
388     }
389   return cmp;
390 }
391
392 /* Returns a pointer to the array of `union value's used for C.
393    The caller must *not* modify the returned data.
394
395    This function breaks the case abstraction.  It should *not* be
396    commonly used.  Prefer the other case functions. */
397 const union value *
398 case_data_all (const struct ccase *c)
399 {
400   return c->values;
401 }
402
403 /* Returns a pointer to the array of `union value's used for C.
404    The caller is allowed to modify the returned data.
405
406    Case C must not be shared.
407
408    This function breaks the case abstraction.  It should *not* be
409    commonly used.  Prefer the other case functions. */
410 union value *
411 case_data_all_rw (struct ccase *c)
412 {
413   assert (!case_is_shared (c));
414   return c->values;
415 }
416
417 /* Internal helper function for case_unshare. */
418 struct ccase *
419 case_unshare__ (struct ccase *old)
420 {
421   struct ccase *new = case_create (old->proto);
422   case_copy (new, 0, old, 0, caseproto_get_n_widths (new->proto));
423   --old->ref_cnt;
424   return new;
425 }
426
427 /* Internal helper function for case_unref. */
428 void
429 case_unref__ (struct ccase *c)
430 {
431   caseproto_destroy_values (c->proto, c->values);
432   caseproto_unref (c->proto);
433   free (c);
434 }
435 \f
436 /* Returns the number of bytes needed by a case for case
437    prototype PROTO. */
438 static size_t
439 case_size (const struct caseproto *proto)
440 {
441   return (offsetof (struct ccase, values)
442           + caseproto_get_n_widths (proto) * sizeof (union value));
443 }
444
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
447    or write data in C.
448
449    Useful in assertions. */
450 static bool UNUSED
451 variable_matches_case (const struct ccase *c, const struct variable *v)
452 {
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));
456 }
457
458 /* Internal helper function for case_copy(). */
459 static void
460 copy_forward (struct ccase *dst, size_t dst_idx,
461               const struct ccase *src, size_t src_idx,
462               size_t n_values)
463 {
464   size_t i;
465
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));
469 }
470
471 /* Internal helper function for case_copy(). */
472 static void
473 copy_backward (struct ccase *dst, size_t dst_idx,
474                const struct ccase *src, size_t src_idx,
475                size_t n_values)
476 {
477   size_t i;
478
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));
482 }
483