QUICK CLUSTER: Adjust comment style.
[pspp] / src / data / case.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2004, 2007, 2009, 2010, 2011 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 "gl/minmax.h"
31 #include "gl/xalloc.h"
32
33 /* Set this flag to 1 to copy cases instead of ref counting them.
34    This is sometimes helpful in debugging situations. */
35 #define DEBUG_CASEREFS 0
36
37 #if DEBUG_CASEREFS
38 #warning "Caseref debug enabled.  CASES ARE NOT BEING SHARED!!"
39 #endif
40
41 static size_t case_size (const struct caseproto *);
42 static bool variable_matches_case (const struct ccase *,
43                                    const struct variable *);
44 static void copy_forward (struct ccase *dst, size_t dst_idx,
45                           const struct ccase *src, size_t src_idx,
46                           size_t n_values);
47 static void copy_backward (struct ccase *dst, size_t dst_idx,
48                            const struct ccase *src, size_t src_idx,
49                            size_t n_values);
50
51 /* Creates and returns a new case that stores data of the form
52    specified by PROTO.  The data in the case have indeterminate
53    contents until explicitly written.
54
55    The caller retains ownership of PROTO. */
56 struct ccase *
57 case_create (const struct caseproto *proto)
58 {
59   struct ccase *c = case_try_create (proto);
60   if (c == NULL)
61     xalloc_die ();
62   return c;
63 }
64
65 /* Like case_create, but returns a null pointer if not enough
66    memory is available. */
67 struct ccase *
68 case_try_create (const struct caseproto *proto)
69 {
70   struct ccase *c = malloc (case_size (proto));
71   if (c != NULL)
72     {
73       if (caseproto_try_init_values (proto, c->values))
74         {
75           c->proto = caseproto_ref (proto);
76           c->ref_cnt = 1;
77           return c;
78         }
79       free (c);
80     }
81   return NULL;
82 }
83
84 /* Creates and returns an unshared copy of case C. */
85 struct ccase *
86 case_clone (const struct ccase *c)
87 {
88   return case_unshare (case_ref (c));
89 }
90
91 /* Increments case C's reference count and returns C.  Afterward,
92    case C is shared among its reference count holders. */
93 struct ccase *
94 case_ref (const struct ccase *c_)
95 {
96   struct ccase *c = CONST_CAST (struct ccase *, c_);
97   c->ref_cnt++;
98 #if DEBUG_CASEREFS
99   c = case_unshare__ (c);
100 #endif
101   return c;
102 }
103
104 /* Returns an estimate of the number of bytes of memory that
105    would be consumed in creating a case based on PROTO.  The
106    estimate includes typical overhead from malloc() in addition
107    to the actual size of data. */
108 size_t
109 case_get_cost (const struct caseproto *proto)
110 {
111   /* FIXME: improve approximation? */
112   return (1 + caseproto_get_n_widths (proto)
113           + 3 * caseproto_get_n_long_strings (proto)) * sizeof (union value);
114 }
115
116 /* Changes the prototype for case C, which must not be shared.
117    The new PROTO must be conformable with C's current prototype
118    (as defined by caseproto_is_conformable).
119
120    Any new values created by this function have indeterminate
121    content that the caller is responsible for initializing.
122
123    The caller retains ownership of PROTO.
124
125    Returns a new case that replaces C, which is freed. */
126 struct ccase *
127 case_resize (struct ccase *c, const struct caseproto *new_proto)
128 {
129   struct caseproto *old_proto = c->proto;
130   size_t old_n_widths = caseproto_get_n_widths (old_proto);
131   size_t new_n_widths = caseproto_get_n_widths (new_proto);
132
133   assert (!case_is_shared (c));
134   expensive_assert (caseproto_is_conformable (old_proto, new_proto));
135
136   if (old_n_widths != new_n_widths)
137     {
138       if (new_n_widths < old_n_widths)
139         caseproto_reinit_values (old_proto, new_proto, c->values);
140       c = xrealloc (c, case_size (new_proto));
141       if (new_n_widths > old_n_widths)
142         caseproto_reinit_values (old_proto, new_proto, c->values);
143
144       caseproto_unref (old_proto);
145       c->proto = caseproto_ref (new_proto);
146     }
147
148   return c;
149 }
150
151 /* case_unshare_and_resize(C, PROTO) is equivalent to
152    case_resize(case_unshare(C), PROTO), but it is faster if case
153    C is shared.
154
155    Any new values created by this function have indeterminate
156    content that the caller is responsible for initializing.
157
158    The caller retains ownership of PROTO.
159
160    Returns the new case that replaces C, which is freed. */
161 struct ccase *
162 case_unshare_and_resize (struct ccase *c, const struct caseproto *proto)
163 {
164   if (!case_is_shared (c))
165     return case_resize (c, proto);
166   else
167     {
168       struct ccase *new = case_create (proto);
169       size_t old_n_values = caseproto_get_n_widths (c->proto);
170       size_t new_n_values = caseproto_get_n_widths (proto);
171       case_copy (new, 0, c, 0, MIN (old_n_values, new_n_values));
172       c->ref_cnt--;
173       return new;
174     }
175 }
176
177 /* Sets all of the numeric values in case C to the system-missing
178    value, and all of the string values to spaces. */
179 void
180 case_set_missing (struct ccase *c)
181 {
182   size_t i;
183
184   assert (!case_is_shared (c));
185   for (i = 0; i < caseproto_get_n_widths (c->proto); i++)
186     value_set_missing (&c->values[i], caseproto_get_width (c->proto, i));
187 }
188
189 /* Copies N_VALUES values from SRC (starting at SRC_IDX) to DST
190    (starting at DST_IDX).  Each value that is copied into must
191    have the same width as the value that it is copied from.
192
193    Properly handles overlapping ranges when DST == SRC.
194
195    DST must not be shared. */
196 void
197 case_copy (struct ccase *dst, size_t dst_idx,
198            const struct ccase *src, size_t src_idx,
199            size_t n_values)
200 {
201   assert (!case_is_shared (dst));
202   assert (caseproto_range_is_valid (dst->proto, dst_idx, n_values));
203   assert (caseproto_range_is_valid (src->proto, src_idx, n_values));
204   assert (caseproto_equal (dst->proto, dst_idx, src->proto, src_idx,
205                            n_values));
206
207   if (dst != src)
208     {
209       if (!dst->proto->n_long_strings || !src->proto->n_long_strings)
210         memcpy (&dst->values[dst_idx], &src->values[src_idx],
211                 sizeof dst->values[0] * n_values);
212       else
213         copy_forward (dst, dst_idx, src, src_idx, n_values);
214     }
215   else if (dst_idx != src_idx)
216     {
217       if (!dst->proto->n_long_strings)
218         memmove (&dst->values[dst_idx], &src->values[src_idx],
219                  sizeof dst->values[0] * n_values);
220       else if (dst_idx < src_idx)
221         copy_forward (dst, dst_idx, src, src_idx, n_values);
222       else /* dst_idx > src_idx */
223         copy_backward (dst, dst_idx, src, src_idx, n_values);
224     }
225 }
226
227 /* Copies N_VALUES values out of case C to VALUES, starting at
228    the given START_IDX. */
229 void
230 case_copy_out (const struct ccase *c,
231                size_t start_idx, union value *values, size_t n_values)
232 {
233   size_t i;
234
235   assert (caseproto_range_is_valid (c->proto, start_idx, n_values));
236
237   for (i = 0; i < n_values; i++)
238     value_copy (&values[i], &c->values[start_idx + i],
239                 caseproto_get_width (c->proto, start_idx + i));
240 }
241
242 /* Copies N_VALUES values from VALUES into case C, starting at
243    the given START_IDX.
244
245    C must not be shared. */
246 void
247 case_copy_in (struct ccase *c,
248               size_t start_idx, const union value *values, size_t n_values)
249 {
250   size_t i;
251
252   assert (!case_is_shared (c));
253   assert (caseproto_range_is_valid (c->proto, start_idx, n_values));
254
255   for (i = 0; i < n_values; i++)
256     value_copy (&c->values[start_idx + i], &values[i],
257                 caseproto_get_width (c->proto, start_idx + i));
258 }
259
260 /* Returns a pointer to the `union value' used for the
261    element of C for variable V.
262    Case C must be drawn from V's dictionary.
263    The caller must not modify the returned data. */
264 const union value *
265 case_data (const struct ccase *c, const struct variable *v)
266 {
267   assert (variable_matches_case (c, v));
268   return &c->values[var_get_case_index (v)];
269 }
270
271 /* Returns a pointer to the `union value' used for the element of
272    C numbered IDX.  The caller must not modify the returned
273    data. */
274 const union value *
275 case_data_idx (const struct ccase *c, size_t idx)
276 {
277   assert (idx < c->proto->n_widths);
278   return &c->values[idx];
279 }
280
281 /* Returns a pointer to the `union value' used for the element of
282    C for variable V.  Case C must be drawn from V's dictionary.
283    The caller is allowed to modify the returned data.
284
285    Case C must not be shared. */
286 union value *
287 case_data_rw (struct ccase *c, const struct variable *v)
288 {
289   assert (variable_matches_case (c, v));
290   assert (!case_is_shared (c));
291   return &c->values[var_get_case_index (v)];
292 }
293
294 /* Returns a pointer to the `union value' used for the
295    element of C numbered IDX.
296    The caller is allowed to modify the returned data.
297
298    Case C must not be shared. */
299 union value *
300 case_data_rw_idx (struct ccase *c, size_t idx)
301 {
302   assert (idx < c->proto->n_widths);
303   assert (!case_is_shared (c));
304   return &c->values[idx];
305 }
306
307 /* Returns the numeric value of the `union value' in C for
308    variable V.
309    Case C must be drawn from V's dictionary. */
310 double
311 case_num (const struct ccase *c, const struct variable *v)
312 {
313   assert (variable_matches_case (c, v));
314   return c->values[var_get_case_index (v)].f;
315 }
316
317 /* Returns the numeric value of the `union value' in C numbered
318    IDX. */
319 double
320 case_num_idx (const struct ccase *c, size_t idx)
321 {
322   assert (idx < c->proto->n_widths);
323   return c->values[idx].f;
324 }
325
326 /* Returns the string value of the `union value' in C for
327    variable V.  Case C must be drawn from V's dictionary.  The
328    caller must not modify the return value.
329
330    Like the strings embedded in all "union value"s, the return
331    value is not null-terminated. */
332 const uint8_t *
333 case_str (const struct ccase *c, const struct variable *v)
334 {
335   size_t idx = var_get_case_index (v);
336   assert (variable_matches_case (c, v));
337   return value_str (&c->values[idx], caseproto_get_width (c->proto, idx));
338 }
339
340 /* Returns the string value of the `union value' in C numbered
341    IDX.  The caller must not modify the return value.
342
343    Like the strings embedded in all "union value"s, the return
344    value is not null-terminated. */
345 const uint8_t *
346 case_str_idx (const struct ccase *c, size_t idx)
347 {
348   assert (idx < c->proto->n_widths);
349   return value_str (&c->values[idx], caseproto_get_width (c->proto, idx));
350 }
351
352 /* Returns the string value of the `union value' in C for
353    variable V.  Case C must be drawn from V's dictionary.  The
354    caller may modify the return value.
355
356    Case C must not be shared.
357
358    Like the strings embedded in all "union value"s, the return
359    value is not null-terminated. */
360 uint8_t *
361 case_str_rw (struct ccase *c, const struct variable *v)
362 {
363   size_t idx = var_get_case_index (v);
364   assert (variable_matches_case (c, v));
365   assert (!case_is_shared (c));
366   return value_str_rw (&c->values[idx], caseproto_get_width (c->proto, idx));
367 }
368
369 /* Returns the string value of the `union value' in C numbered
370    IDX.  The caller may modify the return value.
371
372    Case C must not be shared.
373
374    Like the strings embedded in all "union value"s, the return
375    value is not null-terminated. */
376 uint8_t *
377 case_str_rw_idx (struct ccase *c, size_t idx)
378 {
379   assert (idx < c->proto->n_widths);
380   assert (!case_is_shared (c));
381   return value_str_rw (&c->values[idx], caseproto_get_width (c->proto, idx));
382 }
383
384 /* Compares the values of the N_VARS variables in VP
385    in cases A and B and returns a strcmp()-type result. */
386 int
387 case_compare (const struct ccase *a, const struct ccase *b,
388               const struct variable *const *vp, size_t n_vars)
389 {
390   return case_compare_2dict (a, b, vp, vp, n_vars);
391 }
392
393 /* Compares the values of the N_VARS variables in VAP in case CA
394    to the values of the N_VARS variables in VBP in CB
395    and returns a strcmp()-type result. */
396 int
397 case_compare_2dict (const struct ccase *ca, const struct ccase *cb,
398                     const struct variable *const *vap,
399                     const struct variable *const *vbp,
400                     size_t n_vars)
401 {
402   int cmp = 0;
403   for (; !cmp && n_vars-- > 0; vap++, vbp++)
404     {
405       const union value *va = case_data (ca, *vap);
406       const union value *vb = case_data (cb, *vbp);
407       assert (var_get_width (*vap) == var_get_width (*vbp));
408       cmp = value_compare_3way (va, vb, var_get_width (*vap)); 
409     }
410   return cmp;
411 }
412
413 /* Returns a pointer to the array of `union value's used for C.
414    The caller must *not* modify the returned data.
415
416    This function breaks the case abstraction.  It should *not* be
417    commonly used.  Prefer the other case functions. */
418 const union value *
419 case_data_all (const struct ccase *c)
420 {
421   return c->values;
422 }
423
424 /* Returns a pointer to the array of `union value's used for C.
425    The caller is allowed to modify the returned data.
426
427    Case C must not be shared.
428
429    This function breaks the case abstraction.  It should *not* be
430    commonly used.  Prefer the other case functions. */
431 union value *
432 case_data_all_rw (struct ccase *c)
433 {
434   assert (!case_is_shared (c));
435   return c->values;
436 }
437
438 /* Internal helper function for case_unshare. */
439 struct ccase *
440 case_unshare__ (struct ccase *old)
441 {
442   struct ccase *new = case_create (old->proto);
443   case_copy (new, 0, old, 0, caseproto_get_n_widths (new->proto));
444   --old->ref_cnt;
445   return new;
446 }
447
448 /* Internal helper function for case_unref. */
449 void
450 case_unref__ (struct ccase *c)
451 {
452   caseproto_destroy_values (c->proto, c->values);
453   caseproto_unref (c->proto);
454   free (c);
455 }
456 \f
457 /* Returns the number of bytes needed by a case for case
458    prototype PROTO. */
459 static size_t
460 case_size (const struct caseproto *proto)
461 {
462   return (offsetof (struct ccase, values)
463           + caseproto_get_n_widths (proto) * sizeof (union value));
464 }
465
466 /* Returns true if C contains a value at V's case index with the
467    same width as V; that is, if V may plausibly be used to read
468    or write data in C.
469
470    Useful in assertions. */
471 static bool UNUSED
472 variable_matches_case (const struct ccase *c, const struct variable *v)
473 {
474   size_t case_idx = var_get_case_index (v);
475   return (case_idx < caseproto_get_n_widths (c->proto)
476           && caseproto_get_width (c->proto, case_idx) == var_get_width (v));
477 }
478
479 /* Internal helper function for case_copy(). */
480 static void
481 copy_forward (struct ccase *dst, size_t dst_idx,
482               const struct ccase *src, size_t src_idx,
483               size_t n_values)
484 {
485   size_t i;
486
487   for (i = 0; i < n_values; i++)
488     value_copy (&dst->values[dst_idx + i], &src->values[src_idx + i],
489                 caseproto_get_width (dst->proto, dst_idx + i));
490 }
491
492 /* Internal helper function for case_copy(). */
493 static void
494 copy_backward (struct ccase *dst, size_t dst_idx,
495                const struct ccase *src, size_t src_idx,
496                size_t n_values)
497 {
498   size_t i;
499
500   for (i = n_values; i-- != 0; )
501     value_copy (&dst->values[dst_idx + i], &src->values[src_idx + i],
502                 caseproto_get_width (dst->proto, dst_idx + i));
503 }
504