20ed8bae2810ac6bbf8b2a3766358a776598a8c4
[pspp-builds.git] / src / data / case.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 2004 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301, USA. */
19
20 #include <config.h>
21 #include "case.h"
22 #include <limits.h>
23 #include <stdlib.h>
24 #include "value.h"
25 #include <libpspp/alloc.h>
26 #include <libpspp/str.h>
27 #include "variable.h"
28
29 #ifdef DEBUGGING
30 #undef NDEBUG
31 #else
32 #ifndef NDEBUG
33 #define NDEBUG
34 #endif
35 #endif
36 #include <assert.h>
37
38 /* Changes C not to share data with any other case.
39    C must be a case with a reference count greater than 1.
40    There should be no reason for external code to call this
41    function explicitly.  It will be called automatically when
42    needed. */
43 void
44 case_unshare (struct ccase *c) 
45 {
46   struct case_data *cd;
47   
48   assert (c->case_data->ref_cnt > 1);
49
50   cd = c->case_data;
51   cd->ref_cnt--;
52   case_create (c, c->case_data->value_cnt);
53   memcpy (c->case_data->values, cd->values,
54           sizeof *cd->values * cd->value_cnt); 
55 }
56
57 /* Returns the number of bytes needed by a case with VALUE_CNT
58    values. */
59 static inline size_t
60 case_size (size_t value_cnt) 
61 {
62   return (offsetof (struct case_data, values)
63           + value_cnt * sizeof (union value));
64 }
65
66 #ifdef DEBUGGING
67 /* Initializes C as a null case. */
68 void
69 case_nullify (struct ccase *c) 
70 {
71   c->case_data = NULL;
72 }
73 #endif /* DEBUGGING */
74
75 #ifdef DEBUGGING
76 /* Returns true iff C is a null case. */
77 int
78 case_is_null (const struct ccase *c) 
79 {
80   return c->case_data == NULL;
81 }
82 #endif /* DEBUGGING */
83
84 /* Initializes C as a new case that can store VALUE_CNT values.
85    The values have indeterminate contents until explicitly
86    written. */
87 void
88 case_create (struct ccase *c, size_t value_cnt) 
89 {
90   if (!case_try_create (c, value_cnt))
91     xalloc_die ();
92 }
93
94 #ifdef DEBUGGING
95 /* Initializes CLONE as a copy of ORIG. */
96 void
97 case_clone (struct ccase *clone, const struct ccase *orig)
98 {
99   assert (orig->case_data->ref_cnt > 0);
100
101   if (clone != orig) 
102     *clone = *orig;
103   orig->case_data->ref_cnt++;
104 }
105 #endif /* DEBUGGING */
106
107 #ifdef DEBUGGING
108 /* Replaces DST by SRC and nullifies SRC.
109    DST and SRC must be initialized cases at entry. */
110 void
111 case_move (struct ccase *dst, struct ccase *src) 
112 {
113   assert (src->case_data->ref_cnt > 0);
114   
115   if (dst != src) 
116     {
117       *dst = *src;
118       case_nullify (src); 
119     }
120 }
121 #endif /* DEBUGGING */
122
123 #ifdef DEBUGGING
124 /* Destroys case C. */
125 void
126 case_destroy (struct ccase *c) 
127 {
128   struct case_data *cd;
129   
130   assert (c != NULL);
131
132   cd = c->case_data;
133   if (cd != NULL && --cd->ref_cnt == 0) 
134     {
135       memset (cd->values, 0xcc, sizeof *cd->values * cd->value_cnt);
136       cd->value_cnt = 0xdeadbeef;
137       free (cd); 
138     }
139 }
140 #endif /* DEBUGGING */
141
142 /* Resizes case C from OLD_CNT to NEW_CNT values. */
143 void
144 case_resize (struct ccase *c, size_t old_cnt, size_t new_cnt) 
145 {
146   struct ccase new;
147
148   case_create (&new, new_cnt);
149   case_copy (&new, 0, c, 0, old_cnt < new_cnt ? old_cnt : new_cnt);
150   case_swap (&new, c);
151   case_destroy (&new);
152 }
153
154 /* Swaps cases A and B. */
155 void
156 case_swap (struct ccase *a, struct ccase *b) 
157 {
158   struct case_data *t = a->case_data;
159   a->case_data = b->case_data;
160   b->case_data = t;
161 }
162
163 /* Attempts to create C as a new case that holds VALUE_CNT
164    values.  Returns true if successful, false if memory
165    allocation failed. */
166 bool
167 case_try_create (struct ccase *c, size_t value_cnt) 
168 {
169   c->case_data = malloc (case_size (value_cnt));
170   if (c->case_data != NULL) 
171     {
172       c->case_data->value_cnt = value_cnt;
173       c->case_data->ref_cnt = 1;
174       return true;
175     }
176   
177   return false;
178 }
179
180 /* Tries to initialize CLONE as a copy of ORIG.
181    Returns true if successful, false if memory allocation
182    failed. */
183 bool
184 case_try_clone (struct ccase *clone, const struct ccase *orig) 
185 {
186   case_clone (clone, orig);
187   return true;
188 }
189
190 #ifdef DEBUGGING
191 /* Copies VALUE_CNT values from SRC (starting at SRC_IDX) to DST
192    (starting at DST_IDX). */
193 void
194 case_copy (struct ccase *dst, size_t dst_idx,
195            const struct ccase *src, size_t src_idx,
196            size_t value_cnt)
197 {
198   assert (dst->case_data->ref_cnt > 0);
199   assert (dst_idx + value_cnt <= dst->case_data->value_cnt);
200
201   assert (src->case_data->ref_cnt > 0);
202   assert (src_idx + value_cnt <= src->case_data->value_cnt);
203
204   if (dst->case_data != src->case_data || dst_idx != src_idx) 
205     {
206       if (dst->case_data->ref_cnt > 1)
207         case_unshare (dst);
208       memmove (dst->case_data->values + dst_idx,
209                src->case_data->values + src_idx,
210                sizeof *dst->case_data->values * value_cnt); 
211     }
212 }
213 #endif /* DEBUGGING */
214
215 #ifdef DEBUGGING
216 /* Copies case C to OUTPUT.
217    OUTPUT_SIZE is the number of `union values' in OUTPUT,
218    which must match the number of `union values' in C. */
219 void
220 case_to_values (const struct ccase *c, union value *output,
221                 size_t output_size UNUSED) 
222 {
223   assert (c->case_data->ref_cnt > 0);
224   assert (output_size == c->case_data->value_cnt);
225   assert (output != NULL || output_size == 0);
226
227   memcpy (output, c->case_data->values,
228           c->case_data->value_cnt * sizeof *output);
229 }
230 #endif /* DEBUGGING */
231
232 #ifdef DEBUGGING
233 /* Copies INPUT into case C.
234    INPUT_SIZE is the number of `union values' in INPUT,
235    which must match the number of `union values' in C. */
236 void
237 case_from_values (struct ccase *c, const union value *input,
238                   size_t input_size UNUSED) 
239 {
240   assert (c != NULL);
241   assert (c->case_data != NULL);
242   assert (c->case_data->ref_cnt > 0);
243   assert (input_size == c->case_data->value_cnt);
244   assert (input != NULL || input_size == 0);
245
246   if (c->case_data->ref_cnt > 1)
247     case_unshare (c);
248   memcpy (c->case_data->values, input,
249           c->case_data->value_cnt * sizeof *input);
250 }
251 #endif /* DEBUGGING */
252
253 #ifdef DEBUGGING
254 /* Returns a pointer to the `union value' used for the
255    element of C numbered IDX.
256    The caller must not modify the returned data. */
257 const union value *
258 case_data_idx (const struct ccase *c, size_t idx) 
259 {
260   assert (c != NULL);
261   assert (c->case_data != NULL);
262   assert (c->case_data->ref_cnt > 0);
263   assert (idx < c->case_data->value_cnt);
264
265   return &c->case_data->values[idx];
266 }
267 #endif /* DEBUGGING */
268
269 #ifdef DEBUGGING
270 /* Returns the numeric value of the `union value' in C numbered
271    IDX. */
272 double
273 case_num_idx (const struct ccase *c, size_t idx) 
274 {
275   assert (c != NULL);
276   assert (c->case_data != NULL);
277   assert (c->case_data->ref_cnt > 0);
278   assert (idx < c->case_data->value_cnt);
279
280   return c->case_data->values[idx].f;
281 }
282 #endif /* DEBUGGING */
283
284 #ifdef DEBUGGING
285 /* Returns the string value of the `union value' in C numbered
286    IDX.
287    (Note that the value is not null-terminated.)
288    The caller must not modify the return value. */
289 const char *
290 case_str_idx (const struct ccase *c, size_t idx) 
291 {
292   assert (c != NULL);
293   assert (c->case_data != NULL);
294   assert (c->case_data->ref_cnt > 0);
295   assert (idx < c->case_data->value_cnt);
296
297   return c->case_data->values[idx].s;
298 }
299 #endif /* DEBUGGING */
300
301 #ifdef DEBUGGING
302 /* Returns a pointer to the `union value' used for the
303    element of C numbered IDX.
304    The caller is allowed to modify the returned data. */
305 union value *
306 case_data_rw_idx (struct ccase *c, size_t idx) 
307 {
308   assert (c != NULL);
309   assert (c->case_data != NULL);
310   assert (c->case_data->ref_cnt > 0);
311   assert (idx < c->case_data->value_cnt);
312
313   if (c->case_data->ref_cnt > 1)
314     case_unshare (c);
315   return &c->case_data->values[idx];
316 }
317 #endif /* DEBUGGING */
318
319 /* Compares the values of the VAR_CNT variables in VP
320    in cases A and B and returns a strcmp()-type result. */
321 int
322 case_compare (const struct ccase *a, const struct ccase *b,
323               struct variable *const *vp, size_t var_cnt)
324 {
325   return case_compare_2dict (a, b, vp, vp, var_cnt);
326 }
327
328 /* Compares the values of the VAR_CNT variables in VAP in case CA
329    to the values of the VAR_CNT variables in VBP in CB
330    and returns a strcmp()-type result. */
331 int
332 case_compare_2dict (const struct ccase *ca, const struct ccase *cb,
333                     struct variable *const *vap, struct variable *const *vbp,
334                     size_t var_cnt) 
335 {
336   for (; var_cnt-- > 0; vap++, vbp++) 
337     {
338       const struct variable *va = *vap;
339       const struct variable *vb = *vbp;
340
341       assert (var_get_width (va) == var_get_width (vb));
342       
343       if (var_get_width (va) == 0) 
344         {
345           double af = case_num (ca, va);
346           double bf = case_num (cb, vb);
347
348           if (af != bf) 
349             return af > bf ? 1 : -1;
350         }
351       else 
352         {
353           const char *as = case_str (ca, va);
354           const char *bs = case_str (cb, vb);
355           int cmp = memcmp (as, bs, var_get_width (va));
356
357           if (cmp != 0)
358             return cmp;
359         }
360     }
361   return 0;
362 }
363
364 /* Returns a pointer to the array of `union value's used for C.
365    The caller must *not* modify the returned data.
366
367    NOTE: This function breaks the case abstraction.  It should
368    *not* be used often.  Prefer the other case functions. */
369 const union value *
370 case_data_all (const struct ccase *c) 
371 {
372   assert (c != NULL);
373   assert (c->case_data != NULL);
374   assert (c->case_data->ref_cnt > 0);
375
376   return c->case_data->values;
377 }
378
379 /* Returns a pointer to the array of `union value's used for C.
380    The caller is allowed to modify the returned data.
381
382    NOTE: This function breaks the case abstraction.  It should
383    *not* be used often.  Prefer the other case functions. */
384 union value *
385 case_data_all_rw (struct ccase *c) 
386 {
387   assert (c != NULL);
388   assert (c->case_data != NULL);
389   assert (c->case_data->ref_cnt > 0);
390
391   if (c->case_data->ref_cnt > 1)
392     case_unshare (c);
393   return c->case_data->values;
394 }