1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2007, 2009 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/casewriter.h>
20 #include <data/casewriter-provider.h>
25 #include <data/casereader.h>
26 #include <data/casereader-provider.h>
27 #include <data/casewindow.h>
28 #include <data/settings.h>
29 #include <libpspp/assertion.h>
30 #include <libpspp/compiler.h>
31 #include <libpspp/taint.h>
39 struct caseproto *proto;
41 const struct casewriter_class *class;
45 static struct casewriter *create_casewriter_window (const struct caseproto *,
46 casenumber max_in_core);
48 /* Writes case C to WRITER. Ownership of C is transferred to
51 casewriter_write (struct casewriter *writer, struct ccase *c)
53 size_t n_widths UNUSED = caseproto_get_n_widths (writer->proto);
54 assert (case_get_value_cnt (c) >= n_widths);
55 expensive_assert (caseproto_equal (case_get_proto (c), 0,
56 writer->proto, 0, n_widths));
57 writer->class->write (writer, writer->aux, c);
61 Returns true if successful, false if an I/O error was
62 encountered on WRITER or on some object on which WRITER has a
65 casewriter_destroy (struct casewriter *writer)
70 writer->class->destroy (writer, writer->aux);
71 ok = taint_destroy (writer->taint);
72 caseproto_unref (writer->proto);
78 /* Returns the prototype for that cases written to WRITER must
80 const struct caseproto *
81 casewriter_get_proto (const struct casewriter *writer)
86 /* Destroys WRITER and in its place returns a casereader that can
87 be used to read back the data written to WRITER. WRITER must
88 not be used again after calling this function, even as an
89 argument to casewriter_destroy.
91 Not all casewriters implement this function. Behavior is
92 undefined if it is called on one that does not.
94 If an I/O error was encountered on WRITER or on some object on
95 which WRITER has a dependency, then the error will be
96 propagated to the new casereader. */
98 casewriter_make_reader (struct casewriter *writer)
100 struct casereader *reader = writer->class->convert_to_reader (writer, writer->aux);
101 taint_propagate (writer->taint, casereader_get_taint (reader));
102 taint_destroy (writer->taint);
107 /* Returns a copy of WRITER, which is itself destroyed.
108 Useful for taking over ownership of a casewriter, to enforce
109 preventing the original owner from accessing the casewriter
112 casewriter_rename (struct casewriter *writer)
114 struct casewriter *new = xmemdup (writer, sizeof *writer);
119 /* Returns true if an I/O error or another hard error has
120 occurred on WRITER, a clone of WRITER, or on some object on
121 which WRITER's data has a dependency, false otherwise. */
123 casewriter_error (const struct casewriter *writer)
125 return taint_is_tainted (writer->taint);
128 /* Marks WRITER as having encountered an error.
130 Ordinarily, this function should be called by the
131 implementation of a casewriter, not by the casewriter's
132 client. Instead, casewriter clients should usually ensure
133 that a casewriter's error state is correct by using
134 taint_propagate to propagate to the casewriter's taint
135 structure, which may be obtained via casewriter_get_taint. */
137 casewriter_force_error (struct casewriter *writer)
139 taint_set_taint (writer->taint);
142 /* Returns WRITER's associate taint object, for use with
143 taint_propagate and other taint functions. */
145 casewriter_get_taint (const struct casewriter *writer)
147 return writer->taint;
150 /* Creates and returns a new casewriter with the given CLASS and
151 auxiliary data AUX. The casewriter accepts cases that match
152 case prototype PROTO, of which the caller retains
155 casewriter_create (const struct caseproto *proto,
156 const struct casewriter_class *class, void *aux)
158 struct casewriter *writer = xmalloc (sizeof *writer);
159 writer->taint = taint_create ();
160 writer->proto = caseproto_ref (proto);
161 writer->case_cnt = 0;
162 writer->class = class;
167 /* Returns a casewriter for cases that match case prototype
168 PROTO. The cases written to the casewriter will be kept in
169 memory, unless the amount of memory used grows too large, in
170 which case they will be written to disk.
172 A casewriter created with this function may be passed to
173 casewriter_make_reader.
175 This is usually the right kind of casewriter to use. */
177 autopaging_writer_create (const struct caseproto *proto)
179 return create_casewriter_window (proto,
180 settings_get_workspace_cases (proto));
183 /* Returns a casewriter for cases that match case prototype
184 PROTO. The cases written to the casewriter will be kept in
187 A casewriter created with this function may be passed to
188 casewriter_make_reader. */
190 mem_writer_create (const struct caseproto *proto)
192 return create_casewriter_window (proto, CASENUMBER_MAX);
195 /* Returns a casewriter for cases that match case prototype
196 PROTO. The cases written to the casewriter will be written
199 A casewriter created with this function may be passed to
200 casewriter_make_reader. */
202 tmpfile_writer_create (const struct caseproto *proto)
204 return create_casewriter_window (proto, 0);
207 static const struct casewriter_class casewriter_window_class;
208 static const struct casereader_random_class casereader_window_class;
210 /* Creates and returns a new casewriter based on a casewindow.
211 Each of the casewriter's cases are composed of VALUE_CNT
212 struct values. The casewriter's cases will be maintained in
213 memory until MAX_IN_CORE_CASES have been written, at which
214 point they will be written to disk. */
215 static struct casewriter *
216 create_casewriter_window (const struct caseproto *proto,
217 casenumber max_in_core_cases)
219 struct casewindow *window = casewindow_create (proto, max_in_core_cases);
220 struct casewriter *writer = casewriter_create (proto,
221 &casewriter_window_class,
223 taint_propagate (casewindow_get_taint (window),
224 casewriter_get_taint (writer));
228 /* Writes case C to casewindow writer WINDOW. */
230 casewriter_window_write (struct casewriter *writer UNUSED, void *window_,
233 struct casewindow *window = window_;
234 casewindow_push_head (window, c);
237 /* Destroys casewindow writer WINDOW. */
239 casewriter_window_destroy (struct casewriter *writer UNUSED, void *window_)
241 struct casewindow *window = window_;
242 casewindow_destroy (window);
245 /* Converts casewindow writer WINDOW to a casereader and returns
247 static struct casereader *
248 casewriter_window_convert_to_reader (struct casewriter *writer UNUSED,
251 struct casewindow *window = window_;
252 struct casereader *reader =
253 casereader_create_random (casewindow_get_proto (window),
254 casewindow_get_case_cnt (window),
255 &casereader_window_class, window);
257 taint_propagate (casewindow_get_taint (window),
258 casereader_get_taint (reader));
262 /* Reads and returns the case at the given 0-based OFFSET from
263 the front of WINDOW into C. Returns a null pointer if OFFSET
264 is beyond the end of file or upon I/O error. The caller must
265 call case_unref() on the returned case when it is no longer
267 static struct ccase *
268 casereader_window_read (struct casereader *reader UNUSED, void *window_,
271 struct casewindow *window = window_;
272 if (offset >= casewindow_get_case_cnt (window))
274 return casewindow_get_case (window, offset);
277 /* Destroys casewindow reader WINDOW. */
279 casereader_window_destroy (struct casereader *reader UNUSED, void *window_)
281 struct casewindow *window = window_;
282 casewindow_destroy (window);
285 /* Discards CASE_CNT cases from the front of WINDOW. */
287 casereader_window_advance (struct casereader *reader UNUSED, void *window_,
290 struct casewindow *window = window_;
291 casewindow_pop_tail (window, case_cnt);
294 /* Class for casewindow writer. */
295 static const struct casewriter_class casewriter_window_class =
297 casewriter_window_write,
298 casewriter_window_destroy,
299 casewriter_window_convert_to_reader,
302 /* Class for casewindow reader. */
303 static const struct casereader_random_class casereader_window_class =
305 casereader_window_read,
306 casereader_window_destroy,
307 casereader_window_advance,