Change "union value" to dynamically allocate long strings.
[pspp-builds.git] / src / data / casewriter.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2007, 2009 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
16
17 #include <config.h>
18
19 #include <data/casewriter.h>
20 #include <data/casewriter-provider.h>
21
22 #include <assert.h>
23 #include <stdlib.h>
24
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>
32
33 #include "xalloc.h"
34
35 /* A casewriter. */
36 struct casewriter
37   {
38     struct taint *taint;
39     struct caseproto *proto;
40     casenumber case_cnt;
41     const struct casewriter_class *class;
42     void *aux;
43   };
44
45 static struct casewriter *create_casewriter_window (const struct caseproto *,
46                                                     casenumber max_in_core);
47
48 /* Writes case C to WRITER.  Ownership of C is transferred to
49    WRITER. */
50 void
51 casewriter_write (struct casewriter *writer, struct ccase *c)
52 {
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);
58 }
59
60 /* Destroys WRITER.
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
63    dependency. */
64 bool
65 casewriter_destroy (struct casewriter *writer)
66 {
67   bool ok = true;
68   if (writer != NULL)
69     {
70       writer->class->destroy (writer, writer->aux);
71       ok = taint_destroy (writer->taint);
72       caseproto_unref (writer->proto);
73       free (writer);
74     }
75   return ok;
76 }
77
78 /* Returns the prototype for that cases written to WRITER must
79    follow. */
80 const struct caseproto *
81 casewriter_get_proto (const struct casewriter *writer)
82 {
83   return writer->proto;
84 }
85
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.
90
91    Not all casewriters implement this function.  Behavior is
92    undefined if it is called on one that does not.
93
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. */
97 struct casereader *
98 casewriter_make_reader (struct casewriter *writer)
99 {
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);
103   free (writer);
104   return reader;
105 }
106
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
110    again. */
111 struct casewriter *
112 casewriter_rename (struct casewriter *writer)
113 {
114   struct casewriter *new = xmemdup (writer, sizeof *writer);
115   free (writer);
116   return new;
117 }
118
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. */
122 bool
123 casewriter_error (const struct casewriter *writer)
124 {
125   return taint_is_tainted (writer->taint);
126 }
127
128 /* Marks WRITER as having encountered an error.
129
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. */
136 void
137 casewriter_force_error (struct casewriter *writer)
138 {
139   taint_set_taint (writer->taint);
140 }
141
142 /* Returns WRITER's associate taint object, for use with
143    taint_propagate and other taint functions. */
144 const struct taint *
145 casewriter_get_taint (const struct casewriter *writer)
146 {
147   return writer->taint;
148 }
149
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
153    ownership. */
154 struct casewriter *
155 casewriter_create (const struct caseproto *proto,
156                    const struct casewriter_class *class, void *aux)
157 {
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;
163   writer->aux = aux;
164   return writer;
165 }
166
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.
171
172    A casewriter created with this function may be passed to
173    casewriter_make_reader.
174
175    This is usually the right kind of casewriter to use. */
176 struct casewriter *
177 autopaging_writer_create (const struct caseproto *proto)
178 {
179   return create_casewriter_window (proto,
180                                    settings_get_workspace_cases (proto));
181 }
182
183 /* Returns a casewriter for cases that match case prototype
184    PROTO.  The cases written to the casewriter will be kept in
185    memory.
186
187    A casewriter created with this function may be passed to
188    casewriter_make_reader. */
189 struct casewriter *
190 mem_writer_create (const struct caseproto *proto)
191 {
192   return create_casewriter_window (proto, CASENUMBER_MAX);
193 }
194
195 /* Returns a casewriter for cases that match case prototype
196    PROTO.  The cases written to the casewriter will be written
197    to disk.
198
199    A casewriter created with this function may be passed to
200    casewriter_make_reader. */
201 struct casewriter *
202 tmpfile_writer_create (const struct caseproto *proto)
203 {
204   return create_casewriter_window (proto, 0);
205 }
206 \f
207 static const struct casewriter_class casewriter_window_class;
208 static const struct casereader_random_class casereader_window_class;
209
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)
218 {
219   struct casewindow *window = casewindow_create (proto, max_in_core_cases);
220   struct casewriter *writer = casewriter_create (proto,
221                                                  &casewriter_window_class,
222                                                  window);
223   taint_propagate (casewindow_get_taint (window),
224                    casewriter_get_taint (writer));
225   return writer;
226 }
227
228 /* Writes case C to casewindow writer WINDOW. */
229 static void
230 casewriter_window_write (struct casewriter *writer UNUSED, void *window_,
231                          struct ccase *c)
232 {
233   struct casewindow *window = window_;
234   casewindow_push_head (window, c);
235 }
236
237 /* Destroys casewindow writer WINDOW. */
238 static void
239 casewriter_window_destroy (struct casewriter *writer UNUSED, void *window_)
240 {
241   struct casewindow *window = window_;
242   casewindow_destroy (window);
243 }
244
245 /* Converts casewindow writer WINDOW to a casereader and returns
246    the casereader. */
247 static struct casereader *
248 casewriter_window_convert_to_reader (struct casewriter *writer UNUSED,
249                                      void *window_)
250 {
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);
256
257   taint_propagate (casewindow_get_taint (window),
258                    casereader_get_taint (reader));
259   return reader;
260 }
261
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
266    needed.*/
267 static struct ccase *
268 casereader_window_read (struct casereader *reader UNUSED, void *window_,
269                         casenumber offset)
270 {
271   struct casewindow *window = window_;
272   if (offset >= casewindow_get_case_cnt (window))
273     return NULL;
274   return casewindow_get_case (window, offset);
275 }
276
277 /* Destroys casewindow reader WINDOW. */
278 static void
279 casereader_window_destroy (struct casereader *reader UNUSED, void *window_)
280 {
281   struct casewindow *window = window_;
282   casewindow_destroy (window);
283 }
284
285 /* Discards CASE_CNT cases from the front of WINDOW. */
286 static void
287 casereader_window_advance (struct casereader *reader UNUSED, void *window_,
288                            casenumber case_cnt)
289 {
290   struct casewindow *window = window_;
291   casewindow_pop_tail (window, case_cnt);
292 }
293
294 /* Class for casewindow writer. */
295 static const struct casewriter_class casewriter_window_class =
296   {
297     casewriter_window_write,
298     casewriter_window_destroy,
299     casewriter_window_convert_to_reader,
300   };
301
302 /* Class for casewindow reader. */
303 static const struct casereader_random_class casereader_window_class =
304   {
305     casereader_window_read,
306     casereader_window_destroy,
307     casereader_window_advance,
308   };
309 \f