21fb0bdbfdb725a58cd73f5640e5ed8c5f9ebee7
[pspp] / src / 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., 59 Temple Place - Suite 330, Boston, MA
18    02111-1307, USA. */
19
20 #include <config.h>
21 #include "case.h"
22 #include <limits.h>
23 #include <stdlib.h>
24 #include "val.h"
25 #include "alloc.h"
26 #include "str.h"
27
28 #ifdef GLOBAL_DEBUGGING
29 #undef NDEBUG
30 #else
31 #ifndef NDEBUG
32 #define NDEBUG
33 #endif
34 #endif
35 #include <assert.h>
36
37 /* Changes C not to share data with any other case.
38    C must be a case with a reference count greater than 1.
39    There should be no reason for external code to call this
40    function explicitly.  It will be called automatically when
41    needed. */
42 void
43 case_unshare (struct ccase *c) 
44 {
45   struct case_data *cd;
46   
47   assert (c != NULL);
48   assert (c->this == c);
49   assert (c->case_data != NULL);
50   assert (c->case_data->ref_cnt > 1);
51
52   cd = c->case_data;
53   cd->ref_cnt--;
54   case_create (c, c->case_data->value_cnt);
55   memcpy (c->case_data->values, cd->values,
56           sizeof *cd->values * cd->value_cnt); 
57 }
58
59 /* Returns the number of bytes needed by a case with VALUE_CNT
60    values. */
61 static inline size_t
62 case_size (size_t value_cnt) 
63 {
64   return (offsetof (struct case_data, values)
65           + value_cnt * sizeof (union value));
66 }
67
68 #ifdef GLOBAL_DEBUGGING
69 /* Initializes C as a null case. */
70 void
71 case_nullify (struct ccase *c) 
72 {
73   c->case_data = NULL;
74   c->this = c;
75 }
76 #endif /* GLOBAL_DEBUGGING */
77
78 #ifdef GLOBAL_DEBUGGING
79 /* Returns true iff C is a null case. */
80 int
81 case_is_null (const struct ccase *c) 
82 {
83   return c->case_data == NULL;
84 }
85 #endif /* GLOBAL_DEBUGGING */
86
87 /* Initializes C as a new case that can store VALUE_CNT values.
88    The values have indeterminate contents until explicitly
89    written. */
90 void
91 case_create (struct ccase *c, size_t value_cnt) 
92 {
93   if (!case_try_create (c, value_cnt))
94     out_of_memory ();
95 }
96
97 #ifdef GLOBAL_DEBUGGING
98 /* Initializes CLONE as a copy of ORIG. */
99 void
100 case_clone (struct ccase *clone, const struct ccase *orig)
101 {
102   assert (orig != NULL);
103   assert (orig->this == orig);
104   assert (orig->case_data != NULL);
105   assert (orig->case_data->ref_cnt > 0);
106   assert (clone != NULL);
107
108   if (clone != orig) 
109     {
110       *clone = *orig;
111       clone->this = clone;
112     }
113   orig->case_data->ref_cnt++;
114 }
115 #endif /* GLOBAL_DEBUGGING */
116
117 #ifdef GLOBAL_DEBUGGING
118 /* Replaces DST by SRC and nullifies SRC.
119    DST and SRC must be initialized cases at entry. */
120 void
121 case_move (struct ccase *dst, struct ccase *src) 
122 {
123   assert (src != NULL);
124   assert (src->this == src);
125   assert (src->case_data != NULL);
126   assert (src->case_data->ref_cnt > 0);
127   assert (dst != NULL);
128
129   *dst = *src;
130   dst->this = dst;
131   case_nullify (src);
132 }
133 #endif /* GLOBAL_DEBUGGING */
134
135 #ifdef GLOBAL_DEBUGGING
136 /* Destroys case C. */
137 void
138 case_destroy (struct ccase *c) 
139 {
140   struct case_data *cd;
141   
142   assert (c != NULL);
143   assert (c->this == c);
144
145   cd = c->case_data;
146   if (cd != NULL && --cd->ref_cnt == 0) 
147     {
148       memset (cd->values, 0xcc, sizeof *cd->values * cd->value_cnt);
149       cd->value_cnt = 0xdeadbeef;
150       free (cd); 
151     }
152 }
153 #endif /* GLOBAL_DEBUGGING */
154
155 /* Attempts to create C as a new case that holds VALUE_CNT
156    values.  Returns nonzero if successful, zero if memory
157    allocation failed. */
158 int
159 case_try_create (struct ccase *c, size_t value_cnt) 
160 {
161   c->case_data = malloc (case_size (value_cnt));
162   if (c->case_data != NULL) 
163     {
164 #ifdef GLOBAL_DEBUGGING
165       c->this = c;
166 #endif
167       c->case_data->value_cnt = value_cnt;
168       c->case_data->ref_cnt = 1;
169       return 1;
170     }
171   else 
172     {
173 #ifdef GLOBAL_DEBUGGING
174       c->this = c;
175 #endif
176       return 0;
177     }
178 }
179
180 /* Tries to initialize CLONE as a copy of ORIG.
181    Returns nonzero if successful, zero if memory allocation
182    failed. */
183 int
184 case_try_clone (struct ccase *clone, const struct ccase *orig) 
185 {
186   case_clone (clone, orig);
187   return 1;
188 }
189
190 #ifdef GLOBAL_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 != NULL);
199   assert (dst->this == dst);
200   assert (dst->case_data != NULL);
201   assert (dst->case_data->ref_cnt > 0);
202   assert (dst_idx + value_cnt <= dst->case_data->value_cnt);
203
204   assert (src != NULL);
205   assert (src->this == src);
206   assert (src->case_data != NULL);
207   assert (src->case_data->ref_cnt > 0);
208   assert (src_idx + value_cnt <= dst->case_data->value_cnt);
209
210   if (dst->case_data->ref_cnt > 1)
211     case_unshare (dst);
212   if (dst->case_data != src->case_data || dst_idx != src_idx) 
213     memmove (dst->case_data->values + dst_idx,
214              src->case_data->values + src_idx,
215              sizeof *dst->case_data->values * value_cnt); 
216 }
217 #endif /* GLOBAL_DEBUGGING */
218
219 #ifdef GLOBAL_DEBUGGING
220 /* Copies case C to OUTPUT.
221    OUTPUT_SIZE is the number of `union values' in OUTPUT,
222    which must match the number of `union values' in C. */
223 void
224 case_to_values (const struct ccase *c, union value *output,
225                 size_t output_size UNUSED) 
226 {
227   assert (c != NULL);
228   assert (c->this == c);
229   assert (c->case_data != NULL);
230   assert (c->case_data->ref_cnt > 0);
231   assert (output_size == c->case_data->value_cnt);
232   assert (output != NULL || output_size == 0);
233
234   memcpy (output, c->case_data->values,
235           c->case_data->value_cnt * sizeof *output);
236 }
237 #endif /* GLOBAL_DEBUGGING */
238
239 #ifdef GLOBAL_DEBUGGING
240 /* Copies INPUT into case C.
241    INPUT_SIZE is the number of `union values' in INPUT,
242    which must match the number of `union values' in C. */
243 void
244 case_from_values (struct ccase *c, const union value *input,
245                   size_t input_size UNUSED) 
246 {
247   assert (c != NULL);
248   assert (c->this == c);
249   assert (c->case_data != NULL);
250   assert (c->case_data->ref_cnt > 0);
251   assert (input_size == c->case_data->value_cnt);
252   assert (input != NULL || input_size == 0);
253
254   if (c->case_data->ref_cnt > 1)
255     case_unshare (c);
256   memcpy (c->case_data->values, input,
257           c->case_data->value_cnt * sizeof *input);
258 }
259 #endif /* GLOBAL_DEBUGGING */
260
261 #ifdef GLOBAL_DEBUGGING
262 /* Returns a pointer to the `union value' used for the
263    element of C numbered IDX.
264    The caller must not modify the returned data. */
265 const union value *
266 case_data (const struct ccase *c, size_t idx) 
267 {
268   assert (c != NULL);
269   assert (c->this == c);
270   assert (c->case_data != NULL);
271   assert (c->case_data->ref_cnt > 0);
272   assert (idx < c->case_data->value_cnt);
273
274   return &c->case_data->values[idx];
275 }
276 #endif /* GLOBAL_DEBUGGING */
277
278 #ifdef GLOBAL_DEBUGGING
279 /* Returns the numeric value of the `union value' in C numbered
280    IDX. */
281 double
282 case_num (const struct ccase *c, size_t idx) 
283 {
284   assert (c != NULL);
285   assert (c->this == c);
286   assert (c->case_data != NULL);
287   assert (c->case_data->ref_cnt > 0);
288   assert (idx < c->case_data->value_cnt);
289
290   return c->case_data->values[idx].f;
291 }
292 #endif /* GLOBAL_DEBUGGING */
293
294 #ifdef GLOBAL_DEBUGGING
295 /* Returns the string value of the `union value' in C numbered
296    IDX.
297    (Note that the value is not null-terminated.)
298    The caller must not modify the return value. */
299 const char *
300 case_str (const struct ccase *c, size_t idx) 
301 {
302   assert (c != NULL);
303   assert (c->this == c);
304   assert (c->case_data != NULL);
305   assert (c->case_data->ref_cnt > 0);
306   assert (idx < c->case_data->value_cnt);
307
308   return c->case_data->values[idx].s;
309 }
310 #endif /* GLOBAL_DEBUGGING */
311
312 #ifdef GLOBAL_DEBUGGING
313 /* Returns a pointer to the `union value' used for the
314    element of C numbered IDX.
315    The caller is allowed to modify the returned data. */
316 union value *
317 case_data_rw (struct ccase *c, size_t idx) 
318 {
319   assert (c != NULL);
320   assert (c->this == c);
321   assert (c->case_data != NULL);
322   assert (c->case_data->ref_cnt > 0);
323   assert (idx < c->case_data->value_cnt);
324
325   if (c->case_data->ref_cnt > 1)
326     case_unshare (c);
327   return &c->case_data->values[idx];
328 }
329 #endif /* GLOBAL_DEBUGGING */
330
331 /* Returns a pointer to the array of `union value's used for C.
332    The caller must *not* modify the returned data.
333
334    NOTE: This function breaks the case abstraction.  It should
335    *not* be used often.  Prefer the other case functions. */
336 const union value *
337 case_data_all (const struct ccase *c) 
338 {
339   assert (c != NULL);
340   assert (c->this == c);
341   assert (c->case_data != NULL);
342   assert (c->case_data->ref_cnt > 0);
343
344   return c->case_data->values;
345 }
346
347 /* Returns a pointer to the array of `union value's used for C.
348    The caller is allowed to modify the returned data.
349
350    NOTE: This function breaks the case abstraction.  It should
351    *not* be used often.  Prefer the other case functions. */
352 union value *
353 case_data_all_rw (struct ccase *c) 
354 {
355   assert (c != NULL);
356   assert (c->this == c);
357   assert (c->case_data != NULL);
358   assert (c->case_data->ref_cnt > 0);
359
360   if (c->case_data->ref_cnt > 1)
361     case_unshare (c);
362   return c->case_data->values;
363 }