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