Patch #5209
[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
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
120 /* Reads a copy of the next case from READER into C.
121    Caller is responsible for destroying C.
122    Returns true if successful, false at end of file. */
123 bool
124 casereader_read (struct casereader *reader, struct ccase *c)
125 {
126   struct casefile *cf = casereader_get_casefile (reader);
127
128   struct ccase *read_case = NULL;
129
130   if ( casefile_error (cf) )
131     return false;
132
133   read_case = reader->class->get_next_case (reader);
134   if ( ! read_case ) return false;
135
136   case_clone (c, read_case );
137
138   return true;
139 }
140
141
142 /* Reads the next case from READER into C and transfers ownership
143    to the caller.  Caller is responsible for destroying C.
144    Returns true if successful, false at end of file or on I/O
145    error. */
146 bool
147 casereader_read_xfer (struct casereader *ffr, struct ccase *c)
148 {
149   struct casefile *cf = casereader_get_casefile (ffr);
150
151   struct ccase *read_case = NULL ;
152
153   if ( casefile_error (cf) )
154     return false;
155
156   read_case = ffr->class->get_next_case (ffr);
157   if ( ! read_case ) return false;
158
159   if ( ffr->destructive && casefile_in_core (cf) )
160     case_move (c, read_case);
161   else
162     case_clone (c, read_case);
163
164   return true;
165 }
166
167 /* Destroys R. */
168 void 
169 casereader_destroy (struct casereader *r)
170 {
171   ll_remove (&r->ll);
172
173   r->class->destroy(r);
174 }
175
176 /* Destroys casefile CF. */
177 void
178 casefile_destroy(struct casefile *cf)
179 {
180   if (!cf) return;
181   
182   assert(cf->class->destroy);
183
184   while (!ll_is_empty (&cf->reader_list))
185     casereader_destroy (ll_to_casereader (ll_head (&cf->reader_list)));
186       
187   casefile_unregister(cf);
188
189   cf->class->destroy(cf);
190 }
191
192 /* Returns true if an I/O error has occurred in casefile CF. */
193 bool 
194 casefile_error (const struct casefile *cf)
195 {
196   return cf->class->error(cf);
197 }
198
199 /* Returns the number of cases in casefile CF. */
200 unsigned long 
201 casefile_get_case_cnt (const struct casefile *cf)
202 {
203   return cf->class->get_case_cnt(cf);
204 }
205
206 /* Returns the number of `union value's in a case for CF. */
207 size_t 
208 casefile_get_value_cnt (const struct casefile *cf)
209 {
210   return cf->class->get_value_cnt(cf);
211 }
212
213 /* Creates and returns a casereader for CF.  A casereader can be used to
214    sequentially read the cases in a casefile. */
215 struct casereader *
216 casefile_get_reader (const struct casefile *cf)
217 {
218   struct casereader *r = cf->class->get_reader(cf);
219   r->cf = (struct casefile *) cf;
220
221   assert (r->class);
222   
223   return r;
224 }
225
226 /* Creates and returns a destructive casereader for CF.  Like a
227    normal casereader, a destructive casereader sequentially reads
228    the cases in a casefile.  Unlike a normal casereader, a
229    destructive reader cannot operate concurrently with any other
230    reader.  (This restriction could be relaxed in a few ways, but
231    it is so far unnecessary for other code.) */
232 struct casereader *
233 casefile_get_destructive_reader (struct casefile *cf) 
234 {
235   struct casereader *r = cf->class->get_reader (cf);
236   r->cf = cf;
237   r->destructive = true;
238   cf->being_destroyed = true;
239
240   return r;
241 }
242
243 /* Appends a copy of case C to casefile CF. 
244    Returns true if successful, false if an I/O error occurred. */
245 bool 
246 casefile_append (struct casefile *cf, const struct ccase *c)
247 {
248   assert (c->case_data->value_cnt >= casefile_get_value_cnt (cf));
249
250   return cf->class->append(cf, c);
251 }
252
253 /* Appends case C to casefile CF, which takes over ownership of
254    C.  
255    Returns true if successful, false if an I/O error occurred. */
256 bool 
257 casefile_append_xfer (struct casefile *cf, struct ccase *c)
258 {
259   assert (c->case_data->value_cnt >= casefile_get_value_cnt (cf));
260
261   cf->class->append (cf, c);
262   case_destroy (c);
263
264   return cf->class->error (cf);
265 }
266
267
268
269
270 /* Puts a casefile to "sleep", that is, minimizes the resources
271    needed for it by closing its file descriptor and freeing its
272    buffer.  This is useful if we need so many casefiles that we
273    might not have enough memory and file descriptors to go
274    around.
275   
276    Implementations may choose to silently ignore this function.
277
278    Returns true if successful, false if an I/O error occurred. */
279 bool
280 casefile_sleep (const struct casefile *cf)
281 {
282   return cf->class->sleep ? cf->class->sleep(cf) : true;
283 }
284
285 /* Returns true only if casefile CF is stored in memory (instead of on
286    disk), false otherwise. 
287 */
288 bool
289 casefile_in_core (const struct casefile *cf)
290 {
291   return cf->class->in_core(cf);
292 }
293
294 /* If CF is currently stored in memory, writes it to disk.  Readers, if any,
295    retain their current positions.
296
297    Implementations may choose to silently ignore this function.
298
299    Returns true if successful, false if an I/O error occurred. */
300 bool 
301 casefile_to_disk (const struct casefile *cf)
302 {
303   return cf->class->to_disk ? cf->class->to_disk(cf) : true;
304 }
305
306 void
307 casereader_register(struct casefile *cf, 
308                     struct casereader *reader, 
309                     const struct class_casereader *class)
310 {
311   reader->class = class;
312   reader->cf = cf;
313       
314   ll_push_head (&cf->reader_list, &reader->ll);
315 }