Remove "Written by Ben Pfaff <blp@gnu.org>" lines everywhere.
[pspp-builds.git] / src / data / casefile.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 2004, 2006 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    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, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17    02110-1301, USA. */
18
19 #include <config.h>
20 #include <stddef.h>
21 #include <stdbool.h>
22 #include <stdlib.h>
23 #include <assert.h>
24
25 #include "case.h"
26 #include "casefile.h"
27 #include "casefile-private.h"
28 #include "casefilter.h"
29
30
31 struct ccase;
32
33 /* A casefile is an abstract class representing an array of cases.  In
34    general, cases are accessible sequentially,  and are immutable once
35    appended to the casefile.  However some implementations may provide
36    special methods for  case mutation or random access.
37
38    Use casefile_append or casefile_append_xfer to append a case to a
39    casefile. 
40
41    The casefile may be read sequentially,
42    starting from the beginning, by "casereaders".  Any
43    number of casereaders may be created, at any time.
44    Each casereader has an independent position in the casefile.
45
46    Casereaders may only move forward.  They cannot move backward to
47    arbitrary records or seek randomly.  Cloning casereaders is
48    possible, but it is not yet implemented.
49
50    Use casereader_read() or casereader_read_xfer() to read
51    a case from a casereader.  Use casereader_destroy() to
52    discard a casereader when it is no longer needed.
53
54    When a casefile is no longer needed, it may be destroyed with
55    casefile_destroy().  This function will also destroy any
56    remaining casereaders. */
57
58 static struct ll_list all_casefiles = LL_INITIALIZER (all_casefiles);
59
60 static struct casefile *
61 ll_to_casefile (const struct ll *ll)
62 {
63   return ll_data (ll, struct casefile, ll);
64 }
65
66 static struct casereader *
67 ll_to_casereader (const struct ll *ll)
68 {
69   return ll_data (ll, struct casereader, ll);
70 }
71
72
73 /* atexit() handler that closes and deletes our temporary
74    files. */
75 static void
76 exit_handler (void) 
77 {
78   while (!ll_is_empty (&all_casefiles))
79     casefile_destroy (ll_to_casefile (ll_head (&all_casefiles)));
80 }
81
82 /* Insert CF into the global list of casefiles */
83 void
84 casefile_register (struct casefile *cf, const struct class_casefile *class)
85 {
86   static bool initialised ;
87   if ( !initialised ) 
88     {
89       atexit (exit_handler);
90       initialised = true;
91     }
92
93   cf->class = class;
94   ll_push_head (&all_casefiles, &cf->ll);
95   ll_init (&cf->reader_list);
96 }
97
98 /* Remove CF from the global list */
99 static void
100 casefile_unregister(struct casefile *cf)
101 {
102   ll_remove (&cf->ll);
103 }
104
105 /* Return the casefile corresponding to this reader */
106 struct casefile *
107 casereader_get_casefile (const struct casereader *r)
108 {
109   return r->cf;
110 }
111
112 /* Return the case number of the current case */
113 unsigned long
114 casereader_cnum(const struct casereader *r)
115 {
116   return r->class->cnum(r);
117 }
118
119 static struct ccase *
120 get_next_case(struct casereader *reader)
121 {
122   struct ccase *read_case = NULL;
123   struct casefile *cf = casereader_get_casefile (reader);
124
125   do 
126     { 
127       if ( casefile_error (cf) )
128         return NULL;
129   
130       read_case = reader->class->get_next_case (reader);
131     } 
132   while ( read_case && reader->filter 
133           && casefilter_skip_case (reader->filter, read_case) ) ;
134
135   return read_case;
136 }
137
138 /* Reads a copy of the next case from READER into C.
139    Caller is responsible for destroying C.
140    Returns true if successful, false at end of file. */
141 bool
142 casereader_read (struct casereader *reader, struct ccase *c)
143 {
144   struct ccase * read_case = get_next_case (reader) ;
145
146   if ( NULL == read_case ) 
147     return false;
148
149   case_clone (c, read_case );
150
151   return true;
152 }
153
154
155 /* Reads the next case from READER into C and transfers ownership
156    to the caller.  Caller is responsible for destroying C.
157    Returns true if successful, false at end of file or on I/O
158    error. */
159 bool
160 casereader_read_xfer (struct casereader *reader, struct ccase *c)
161 {
162   struct casefile *cf = casereader_get_casefile (reader);
163   struct ccase *read_case ;
164   case_nullify (c);
165
166   read_case = get_next_case (reader) ;
167
168   if ( NULL == read_case )
169     return false;
170
171   if ( reader->destructive && casefile_in_core (cf) )
172     case_move (c, read_case);
173   else
174     case_clone (c, read_case);
175
176   return true;
177 }
178
179 /* Destroys R. */
180 void 
181 casereader_destroy (struct casereader *r)
182 {
183   ll_remove (&r->ll);
184
185   r->class->destroy(r);
186 }
187
188 /* Creates a copy of R and returns it */
189 struct casereader *
190 casereader_clone(const struct casereader *r)
191 {
192   struct casereader *r2;
193
194   /* Would we ever want to clone a destructive reader ?? */
195   assert ( ! r->destructive ) ;
196
197   r2 = r->class->clone (r);
198
199   r2->filter = r->filter;
200
201   return r2;
202 }
203
204 /* Destroys casefile CF. */
205 void
206 casefile_destroy(struct casefile *cf)
207 {
208   if (!cf) return;
209   
210   assert(cf->class->destroy);
211
212   while (!ll_is_empty (&cf->reader_list))
213     casereader_destroy (ll_to_casereader (ll_head (&cf->reader_list)));
214       
215   casefile_unregister(cf);
216
217   cf->class->destroy(cf);
218 }
219
220 /* Returns true if an I/O error has occurred in casefile CF. */
221 bool 
222 casefile_error (const struct casefile *cf)
223 {
224   return cf->class->error(cf);
225 }
226
227 /* Returns the number of cases in casefile CF. */
228 unsigned long 
229 casefile_get_case_cnt (const struct casefile *cf)
230 {
231   return cf->class->get_case_cnt(cf);
232 }
233
234 /* Returns the number of `union value's in a case for CF. */
235 size_t 
236 casefile_get_value_cnt (const struct casefile *cf)
237 {
238   return cf->class->get_value_cnt(cf);
239 }
240
241 /* Creates and returns a casereader for CF.  A casereader can be used to
242    sequentially read the cases in a casefile. */
243 struct casereader *
244 casefile_get_reader  (const struct casefile *cf, struct casefilter *filter)
245 {
246   struct casereader *r = cf->class->get_reader(cf);
247   r->cf = (struct casefile *) cf;
248   r->filter = filter;
249
250   assert (r->class);
251   
252   return r;
253 }
254
255 /* Creates and returns a destructive casereader for CF.  Like a
256    normal casereader, a destructive casereader sequentially reads
257    the cases in a casefile.  Unlike a normal casereader, a
258    destructive reader cannot operate concurrently with any other
259    reader.  (This restriction could be relaxed in a few ways, but
260    it is so far unnecessary for other code.) */
261 struct casereader *
262 casefile_get_destructive_reader (struct casefile *cf) 
263 {
264   struct casereader *r = cf->class->get_reader (cf);
265   r->cf = cf;
266   r->destructive = true;
267   cf->being_destroyed = true;
268
269   return r;
270 }
271
272 /* Appends a copy of case C to casefile CF. 
273    Returns true if successful, false if an I/O error occurred. */
274 bool 
275 casefile_append (struct casefile *cf, const struct ccase *c)
276 {
277   assert (c->case_data->value_cnt >= casefile_get_value_cnt (cf));
278
279   return cf->class->append(cf, c);
280 }
281
282 /* Appends case C to casefile CF, which takes over ownership of
283    C.  
284    Returns true if successful, false if an I/O error occurred. */
285 bool 
286 casefile_append_xfer (struct casefile *cf, struct ccase *c)
287 {
288   assert (c->case_data->value_cnt >= casefile_get_value_cnt (cf));
289
290   cf->class->append (cf, c);
291   case_destroy (c);
292
293   return cf->class->error (cf);
294 }
295
296
297
298
299 /* Puts a casefile to "sleep", that is, minimizes the resources
300    needed for it by closing its file descriptor and freeing its
301    buffer.  This is useful if we need so many casefiles that we
302    might not have enough memory and file descriptors to go
303    around.
304   
305    Implementations may choose to silently ignore this function.
306
307    Returns true if successful, false if an I/O error occurred. */
308 bool
309 casefile_sleep (const struct casefile *cf)
310 {
311   return cf->class->sleep ? cf->class->sleep(cf) : true;
312 }
313
314 /* Returns true only if casefile CF is stored in memory (instead of on
315    disk), false otherwise. 
316 */
317 bool
318 casefile_in_core (const struct casefile *cf)
319 {
320   return cf->class->in_core(cf);
321 }
322
323 /* If CF is currently stored in memory, writes it to disk.  Readers, if any,
324    retain their current positions.
325
326    Implementations may choose to silently ignore this function.
327
328    Returns true if successful, false if an I/O error occurred. */
329 bool 
330 casefile_to_disk (const struct casefile *cf)
331 {
332   return cf->class->to_disk ? cf->class->to_disk(cf) : true;
333 }
334
335 void
336 casereader_register(struct casefile *cf, 
337                     struct casereader *reader, 
338                     const struct class_casereader *class)
339 {
340   reader->class = class;
341   reader->cf = cf;
342       
343   ll_push_head (&cf->reader_list, &reader->ll);
344 }