1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2007, 2009, 2011 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU 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, see <http://www.gnu.org/licenses/>. */
19 #include "data/lazy-casereader.h"
23 #include "data/case.h"
24 #include "data/casereader.h"
25 #include "data/casereader-provider.h"
26 #include "libpspp/assertion.h"
28 #include "gl/xalloc.h"
30 /* A lazy casereader's auxiliary data. */
31 struct lazy_casereader
33 unsigned long int serial;
34 struct casereader *(*callback) (void *aux);
38 static const struct casereader_class lazy_casereader_class;
40 /* Creates and returns a new lazy casereader that will
41 instantiate its underlying casereader, if necessary, by
42 calling CALLBACK, passing AUX as its argument. *SERIAL is set
43 to a "serial number" that uniquely identifies the new lazy
44 casereader, for use with lazy_casereader_destroy.
46 PROTO must be the format of the cases to be read from the
49 CASE_CNT is an upper limit on the number of cases that
50 casereader_read will return from the casereader in successive
51 calls. Ordinarily, this is the actual number of cases in the
52 data source or CASENUMBER_MAX if the number of cases cannot be
53 predicted in advance. */
55 lazy_casereader_create (const struct caseproto *proto, casenumber case_cnt,
56 struct casereader *(*callback) (void *aux), void *aux,
57 unsigned long int *serial)
59 static unsigned long int next_serial = 0;
60 struct lazy_casereader *lc;
61 assert (callback != NULL);
62 lc = xmalloc (sizeof *lc);
63 *serial = lc->serial = next_serial++;
64 lc->callback = callback;
66 return casereader_create_sequential (NULL, proto, case_cnt,
67 &lazy_casereader_class, lc);
70 /* If READER is the lazy casereader that was returned by
71 lazy_casereader_create along with SERIAL, and READER was never
72 instantiated by any use of a casereader function, then this
73 function destroys READER without instantiating it, and returns
74 true. Returns false in any other case; that is, if READER is
75 not a lazy casereader, or if READER is a lazy casereader with
76 a serial number different from SERIAL, or if READER is a lazy
77 casereader that was instantiated.
79 When this function returns true, it necessarily indicates
80 that the lazy casereader was never cloned and never
83 lazy_casereader_destroy (struct casereader *reader, unsigned long int serial)
85 struct lazy_casereader *lc;
90 lc = casereader_dynamic_cast (reader, &lazy_casereader_class);
91 if (lc == NULL || lc->serial != serial)
95 casereader_destroy (reader);
99 /* Instantiates lazy casereader READER, which is associated with
102 instantiate_lazy_casereader (struct casereader *reader,
103 struct lazy_casereader *lc)
105 struct casereader *subreader;
107 /* Call the client-provided callback to obtain the real
108 casereader, then swap READER with that casereader. */
109 subreader = lc->callback (lc->aux);
110 casereader_swap (reader, subreader);
112 /* Now destroy the lazy casereader, which is no longer needed
113 since we already swapped it out. Set the callback to null
114 to prevent lazy_casereader_do_destroy from trying to
115 instantiate it again. */
117 casereader_destroy (subreader);
120 static struct ccase *
121 lazy_casereader_read (struct casereader *reader, void *lc_)
123 struct lazy_casereader *lc = lc_;
124 instantiate_lazy_casereader (reader, lc);
125 return casereader_read (reader);
129 lazy_casereader_do_destroy (struct casereader *reader UNUSED, void *lc_)
131 struct lazy_casereader *lc = lc_;
132 if (lc->callback != NULL)
133 casereader_destroy (lc->callback (lc->aux));
137 static struct casereader *
138 lazy_casereader_clone (struct casereader *reader, void *lc_)
140 struct lazy_casereader *lc = lc_;
141 instantiate_lazy_casereader (reader, lc);
142 return casereader_clone (reader);
145 static struct ccase *
146 lazy_casereader_peek (struct casereader *reader, void *lc_, casenumber idx)
148 struct lazy_casereader *lc = lc_;
149 instantiate_lazy_casereader (reader, lc);
150 return casereader_peek (reader, idx);
153 static const struct casereader_class lazy_casereader_class =
155 lazy_casereader_read,
156 lazy_casereader_do_destroy,
157 lazy_casereader_clone,
158 lazy_casereader_peek,