1 /* PSPP - computes sample statistics.
2 Copyright (C) 2004, 2006 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
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.
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.
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
28 #include "casefile-private.h"
29 #include "casefilter.h"
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.
39 Use casefile_append or casefile_append_xfer to append a case to a
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.
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.
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.
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. */
59 static struct ll_list all_casefiles = LL_INITIALIZER (all_casefiles);
61 static struct casefile *
62 ll_to_casefile (const struct ll *ll)
64 return ll_data (ll, struct casefile, ll);
67 static struct casereader *
68 ll_to_casereader (const struct ll *ll)
70 return ll_data (ll, struct casereader, ll);
74 /* atexit() handler that closes and deletes our temporary
79 while (!ll_is_empty (&all_casefiles))
80 casefile_destroy (ll_to_casefile (ll_head (&all_casefiles)));
83 /* Insert CF into the global list of casefiles */
85 casefile_register (struct casefile *cf, const struct class_casefile *class)
87 static bool initialised ;
90 atexit (exit_handler);
95 ll_push_head (&all_casefiles, &cf->ll);
96 ll_init (&cf->reader_list);
99 /* Remove CF from the global list */
101 casefile_unregister(struct casefile *cf)
106 /* Return the casefile corresponding to this reader */
108 casereader_get_casefile (const struct casereader *r)
113 /* Return the case number of the current case */
115 casereader_cnum(const struct casereader *r)
117 return r->class->cnum(r);
120 static struct ccase *
121 get_next_case(struct casereader *reader)
123 struct ccase *read_case = NULL;
124 struct casefile *cf = casereader_get_casefile (reader);
128 if ( casefile_error (cf) )
131 read_case = reader->class->get_next_case (reader);
133 while ( read_case && reader->filter
134 && casefilter_skip_case (reader->filter, read_case) ) ;
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. */
143 casereader_read (struct casereader *reader, struct ccase *c)
145 struct ccase * read_case = get_next_case (reader) ;
147 if ( NULL == read_case )
150 case_clone (c, read_case );
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
161 casereader_read_xfer (struct casereader *reader, struct ccase *c)
163 struct casefile *cf = casereader_get_casefile (reader);
164 struct ccase *read_case ;
167 read_case = get_next_case (reader) ;
169 if ( NULL == read_case )
172 if ( reader->destructive && casefile_in_core (cf) )
173 case_move (c, read_case);
175 case_clone (c, read_case);
182 casereader_destroy (struct casereader *r)
186 r->class->destroy(r);
189 /* Creates a copy of R and returns it */
191 casereader_clone(const struct casereader *r)
193 struct casereader *r2;
195 /* Would we ever want to clone a destructive reader ?? */
196 assert ( ! r->destructive ) ;
198 r2 = r->class->clone (r);
200 r2->filter = r->filter;
205 /* Destroys casefile CF. */
207 casefile_destroy(struct casefile *cf)
211 assert(cf->class->destroy);
213 while (!ll_is_empty (&cf->reader_list))
214 casereader_destroy (ll_to_casereader (ll_head (&cf->reader_list)));
216 casefile_unregister(cf);
218 cf->class->destroy(cf);
221 /* Returns true if an I/O error has occurred in casefile CF. */
223 casefile_error (const struct casefile *cf)
225 return cf->class->error(cf);
228 /* Returns the number of cases in casefile CF. */
230 casefile_get_case_cnt (const struct casefile *cf)
232 return cf->class->get_case_cnt(cf);
235 /* Returns the number of `union value's in a case for CF. */
237 casefile_get_value_cnt (const struct casefile *cf)
239 return cf->class->get_value_cnt(cf);
242 /* Creates and returns a casereader for CF. A casereader can be used to
243 sequentially read the cases in a casefile. */
245 casefile_get_reader (const struct casefile *cf, struct casefilter *filter)
247 struct casereader *r = cf->class->get_reader(cf);
248 r->cf = (struct casefile *) cf;
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.) */
263 casefile_get_destructive_reader (struct casefile *cf)
265 struct casereader *r = cf->class->get_reader (cf);
267 r->destructive = true;
268 cf->being_destroyed = true;
273 /* Appends a copy of case C to casefile CF.
274 Returns true if successful, false if an I/O error occurred. */
276 casefile_append (struct casefile *cf, const struct ccase *c)
278 assert (c->case_data->value_cnt >= casefile_get_value_cnt (cf));
280 return cf->class->append(cf, c);
283 /* Appends case C to casefile CF, which takes over ownership of
285 Returns true if successful, false if an I/O error occurred. */
287 casefile_append_xfer (struct casefile *cf, struct ccase *c)
289 assert (c->case_data->value_cnt >= casefile_get_value_cnt (cf));
291 cf->class->append (cf, c);
294 return cf->class->error (cf);
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
306 Implementations may choose to silently ignore this function.
308 Returns true if successful, false if an I/O error occurred. */
310 casefile_sleep (const struct casefile *cf)
312 return cf->class->sleep ? cf->class->sleep(cf) : true;
315 /* Returns true only if casefile CF is stored in memory (instead of on
316 disk), false otherwise.
319 casefile_in_core (const struct casefile *cf)
321 return cf->class->in_core(cf);
324 /* If CF is currently stored in memory, writes it to disk. Readers, if any,
325 retain their current positions.
327 Implementations may choose to silently ignore this function.
329 Returns true if successful, false if an I/O error occurred. */
331 casefile_to_disk (const struct casefile *cf)
333 return cf->class->to_disk ? cf->class->to_disk(cf) : true;
337 casereader_register(struct casefile *cf,
338 struct casereader *reader,
339 const struct class_casereader *class)
341 reader->class = class;
344 ll_push_head (&cf->reader_list, &reader->ll);