1 /* PSPP - computes sample statistics.
2 Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
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.
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.
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
27 #include "casefile-private.h"
28 #include "casefilter.h"
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.
38 Use casefile_append or casefile_append_xfer to append a case to a
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.
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.
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.
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. */
58 static struct ll_list all_casefiles = LL_INITIALIZER (all_casefiles);
60 static struct casefile *
61 ll_to_casefile (const struct ll *ll)
63 return ll_data (ll, struct casefile, ll);
66 static struct casereader *
67 ll_to_casereader (const struct ll *ll)
69 return ll_data (ll, struct casereader, ll);
73 /* atexit() handler that closes and deletes our temporary
78 while (!ll_is_empty (&all_casefiles))
79 casefile_destroy (ll_to_casefile (ll_head (&all_casefiles)));
82 /* Insert CF into the global list of casefiles */
84 casefile_register (struct casefile *cf, const struct class_casefile *class)
86 static bool initialised ;
89 atexit (exit_handler);
94 ll_push_head (&all_casefiles, &cf->ll);
95 ll_init (&cf->reader_list);
98 /* Remove CF from the global list */
100 casefile_unregister(struct casefile *cf)
105 /* Return the casefile corresponding to this reader */
107 casereader_get_casefile (const struct casereader *r)
112 /* Return the case number of the current case */
114 casereader_cnum(const struct casereader *r)
116 return r->class->cnum(r);
119 static struct ccase *
120 get_next_case(struct casereader *reader)
122 struct ccase *read_case = NULL;
123 struct casefile *cf = casereader_get_casefile (reader);
127 if ( casefile_error (cf) )
130 read_case = reader->class->get_next_case (reader);
132 while ( read_case && reader->filter
133 && casefilter_skip_case (reader->filter, read_case) ) ;
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. */
142 casereader_read (struct casereader *reader, struct ccase *c)
144 struct ccase * read_case = get_next_case (reader) ;
146 if ( NULL == read_case )
149 case_clone (c, read_case );
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
160 casereader_read_xfer (struct casereader *reader, struct ccase *c)
162 struct casefile *cf = casereader_get_casefile (reader);
163 struct ccase *read_case ;
166 read_case = get_next_case (reader) ;
168 if ( NULL == read_case )
171 if ( reader->destructive && casefile_in_core (cf) )
172 case_move (c, read_case);
174 case_clone (c, read_case);
181 casereader_destroy (struct casereader *r)
185 r->class->destroy(r);
188 /* Creates a copy of R and returns it */
190 casereader_clone(const struct casereader *r)
192 struct casereader *r2;
194 /* Would we ever want to clone a destructive reader ?? */
195 assert ( ! r->destructive ) ;
197 r2 = r->class->clone (r);
199 r2->filter = r->filter;
204 /* Destroys casefile CF. */
206 casefile_destroy(struct casefile *cf)
210 assert(cf->class->destroy);
212 while (!ll_is_empty (&cf->reader_list))
213 casereader_destroy (ll_to_casereader (ll_head (&cf->reader_list)));
215 casefile_unregister(cf);
217 cf->class->destroy(cf);
220 /* Returns true if an I/O error has occurred in casefile CF. */
222 casefile_error (const struct casefile *cf)
224 return cf->class->error(cf);
227 /* Returns the number of cases in casefile CF. */
229 casefile_get_case_cnt (const struct casefile *cf)
231 return cf->class->get_case_cnt(cf);
234 /* Returns the number of `union value's in a case for CF. */
236 casefile_get_value_cnt (const struct casefile *cf)
238 return cf->class->get_value_cnt(cf);
241 /* Creates and returns a casereader for CF. A casereader can be used to
242 sequentially read the cases in a casefile. */
244 casefile_get_reader (const struct casefile *cf, struct casefilter *filter)
246 struct casereader *r = cf->class->get_reader(cf);
247 r->cf = (struct casefile *) cf;
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.) */
262 casefile_get_destructive_reader (struct casefile *cf)
264 struct casereader *r = cf->class->get_reader (cf);
266 r->destructive = true;
267 cf->being_destroyed = true;
272 /* Appends a copy of case C to casefile CF.
273 Returns true if successful, false if an I/O error occurred. */
275 casefile_append (struct casefile *cf, const struct ccase *c)
277 assert (case_get_value_cnt (c) >= casefile_get_value_cnt (cf));
279 return cf->class->append(cf, c);
282 /* Appends case C to casefile CF, which takes over ownership of
284 Returns true if successful, false if an I/O error occurred. */
286 casefile_append_xfer (struct casefile *cf, struct ccase *c)
288 assert (case_get_value_cnt (c) >= casefile_get_value_cnt (cf));
290 cf->class->append (cf, c);
293 return cf->class->error (cf);
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
305 Implementations may choose to silently ignore this function.
307 Returns true if successful, false if an I/O error occurred. */
309 casefile_sleep (const struct casefile *cf)
311 return cf->class->sleep ? cf->class->sleep(cf) : true;
314 /* Returns true only if casefile CF is stored in memory (instead of on
315 disk), false otherwise.
318 casefile_in_core (const struct casefile *cf)
320 return cf->class->in_core(cf);
323 /* If CF is currently stored in memory, writes it to disk. Readers, if any,
324 retain their current positions.
326 Implementations may choose to silently ignore this function.
328 Returns true if successful, false if an I/O error occurred. */
330 casefile_to_disk (const struct casefile *cf)
332 return cf->class->to_disk ? cf->class->to_disk(cf) : true;
336 casereader_register(struct casefile *cf,
337 struct casereader *reader,
338 const struct class_casereader *class)
340 reader->class = class;
343 ll_push_head (&cf->reader_list, &reader->ll);