Remove julcal.
[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 /* Resizes case C from OLD_CNT to NEW_CNT values. */
156 void
157 case_resize (struct ccase *c, size_t old_cnt, size_t new_cnt) 
158 {
159   struct ccase new;
160
161   case_create (&new, new_cnt);
162   case_copy (&new, 0, c, 0, old_cnt < new_cnt ? old_cnt : new_cnt);
163   case_swap (&new, c);
164   case_destroy (&new);
165 }
166
167 /* Swaps cases A and B. */
168 void
169 case_swap (struct ccase *a, struct ccase *b) 
170 {
171   struct case_data *t = a->case_data;
172   a->case_data = b->case_data;
173   b->case_data = t;
174 }
175
176 /* Attempts to create C as a new case that holds VALUE_CNT
177    values.  Returns nonzero if successful, zero if memory
178    allocation failed. */
179 int
180 case_try_create (struct ccase *c, size_t value_cnt) 
181 {
182   c->case_data = malloc (case_size (value_cnt));
183   if (c->case_data != NULL) 
184     {
185 #ifdef GLOBAL_DEBUGGING
186       c->this = c;
187 #endif
188       c->case_data->value_cnt = value_cnt;
189       c->case_data->ref_cnt = 1;
190       return 1;
191     }
192   else 
193     {
194 #ifdef GLOBAL_DEBUGGING
195       c->this = c;
196 #endif
197       return 0;
198     }
199 }
200
201 /* Tries to initialize CLONE as a copy of ORIG.
202    Returns nonzero if successful, zero if memory allocation
203    failed. */
204 int
205 case_try_clone (struct ccase *clone, const struct ccase *orig) 
206 {
207   case_clone (clone, orig);
208   return 1;
209 }
210
211 #ifdef GLOBAL_DEBUGGING
212 /* Copies VALUE_CNT values from SRC (starting at SRC_IDX) to DST
213    (starting at DST_IDX). */
214 void
215 case_copy (struct ccase *dst, size_t dst_idx,
216            const struct ccase *src, size_t src_idx,
217            size_t value_cnt)
218 {
219   assert (dst != NULL);
220   assert (dst->this == dst);
221   assert (dst->case_data != NULL);
222   assert (dst->case_data->ref_cnt > 0);
223   assert (dst_idx + value_cnt <= dst->case_data->value_cnt);
224
225   assert (src != NULL);
226   assert (src->this == src);
227   assert (src->case_data != NULL);
228   assert (src->case_data->ref_cnt > 0);
229   assert (src_idx + value_cnt <= dst->case_data->value_cnt);
230
231   if (dst->case_data->ref_cnt > 1)
232     case_unshare (dst);
233   if (dst->case_data != src->case_data || dst_idx != src_idx) 
234     memmove (dst->case_data->values + dst_idx,
235              src->case_data->values + src_idx,
236              sizeof *dst->case_data->values * value_cnt); 
237 }
238 #endif /* GLOBAL_DEBUGGING */
239
240 #ifdef GLOBAL_DEBUGGING
241 /* Copies case C to OUTPUT.
242    OUTPUT_SIZE is the number of `union values' in OUTPUT,
243    which must match the number of `union values' in C. */
244 void
245 case_to_values (const struct ccase *c, union value *output,
246                 size_t output_size UNUSED) 
247 {
248   assert (c != NULL);
249   assert (c->this == c);
250   assert (c->case_data != NULL);
251   assert (c->case_data->ref_cnt > 0);
252   assert (output_size == c->case_data->value_cnt);
253   assert (output != NULL || output_size == 0);
254
255   memcpy (output, c->case_data->values,
256           c->case_data->value_cnt * sizeof *output);
257 }
258 #endif /* GLOBAL_DEBUGGING */
259
260 #ifdef GLOBAL_DEBUGGING
261 /* Copies INPUT into case C.
262    INPUT_SIZE is the number of `union values' in INPUT,
263    which must match the number of `union values' in C. */
264 void
265 case_from_values (struct ccase *c, const union value *input,
266                   size_t input_size UNUSED) 
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 (input_size == c->case_data->value_cnt);
273   assert (input != NULL || input_size == 0);
274
275   if (c->case_data->ref_cnt > 1)
276     case_unshare (c);
277   memcpy (c->case_data->values, input,
278           c->case_data->value_cnt * sizeof *input);
279 }
280 #endif /* GLOBAL_DEBUGGING */
281
282 #ifdef GLOBAL_DEBUGGING
283 /* Returns a pointer to the `union value' used for the
284    element of C numbered IDX.
285    The caller must not modify the returned data. */
286 const union value *
287 case_data (const struct ccase *c, size_t idx) 
288 {
289   assert (c != NULL);
290   assert (c->this == c);
291   assert (c->case_data != NULL);
292   assert (c->case_data->ref_cnt > 0);
293   assert (idx < c->case_data->value_cnt);
294
295   return &c->case_data->values[idx];
296 }
297 #endif /* GLOBAL_DEBUGGING */
298
299 #ifdef GLOBAL_DEBUGGING
300 /* Returns the numeric value of the `union value' in C numbered
301    IDX. */
302 double
303 case_num (const struct ccase *c, size_t idx) 
304 {
305   assert (c != NULL);
306   assert (c->this == c);
307   assert (c->case_data != NULL);
308   assert (c->case_data->ref_cnt > 0);
309   assert (idx < c->case_data->value_cnt);
310
311   return c->case_data->values[idx].f;
312 }
313 #endif /* GLOBAL_DEBUGGING */
314
315 #ifdef GLOBAL_DEBUGGING
316 /* Returns the string value of the `union value' in C numbered
317    IDX.
318    (Note that the value is not null-terminated.)
319    The caller must not modify the return value. */
320 const char *
321 case_str (const struct ccase *c, size_t idx) 
322 {
323   assert (c != NULL);
324   assert (c->this == c);
325   assert (c->case_data != NULL);
326   assert (c->case_data->ref_cnt > 0);
327   assert (idx < c->case_data->value_cnt);
328
329   return c->case_data->values[idx].s;
330 }
331 #endif /* GLOBAL_DEBUGGING */
332
333 #ifdef GLOBAL_DEBUGGING
334 /* Returns a pointer to the `union value' used for the
335    element of C numbered IDX.
336    The caller is allowed to modify the returned data. */
337 union value *
338 case_data_rw (struct ccase *c, size_t idx) 
339 {
340   assert (c != NULL);
341   assert (c->this == c);
342   assert (c->case_data != NULL);
343   assert (c->case_data->ref_cnt > 0);
344   assert (idx < c->case_data->value_cnt);
345
346   if (c->case_data->ref_cnt > 1)
347     case_unshare (c);
348   return &c->case_data->values[idx];
349 }
350 #endif /* GLOBAL_DEBUGGING */
351
352 /* Returns a pointer to the array of `union value's used for C.
353    The caller must *not* modify the returned data.
354
355    NOTE: This function breaks the case abstraction.  It should
356    *not* be used often.  Prefer the other case functions. */
357 const union value *
358 case_data_all (const struct ccase *c) 
359 {
360   assert (c != NULL);
361   assert (c->this == c);
362   assert (c->case_data != NULL);
363   assert (c->case_data->ref_cnt > 0);
364
365   return c->case_data->values;
366 }
367
368 /* Returns a pointer to the array of `union value's used for C.
369    The caller is allowed to modify the returned data.
370
371    NOTE: This function breaks the case abstraction.  It should
372    *not* be used often.  Prefer the other case functions. */
373 union value *
374 case_data_all_rw (struct ccase *c) 
375 {
376   assert (c != NULL);
377   assert (c->this == c);
378   assert (c->case_data != NULL);
379   assert (c->case_data->ref_cnt > 0);
380
381   if (c->case_data->ref_cnt > 1)
382     case_unshare (c);
383   return c->case_data->values;
384 }