Implemented the find dialog.
[pspp] / src / data / casewriter.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2007 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/compiler.h>
30 #include <libpspp/taint.h>
31
32 #include "xalloc.h"
33
34 /* A casewriter. */
35 struct casewriter
36   {
37     struct taint *taint;
38     size_t value_cnt;
39     casenumber case_cnt;
40     const struct casewriter_class *class;
41     void *aux;
42   };
43
44 static struct casewriter *create_casewriter_window (size_t value_cnt,
45                                                     casenumber max_in_core);
46
47 /* Writes case C to WRITER. */
48 void
49 casewriter_write (struct casewriter *writer, struct ccase *c)
50 {
51   assert (case_get_value_cnt (c) >= writer->value_cnt);
52   writer->class->write (writer, writer->aux, c);
53 }
54
55 /* Destroys WRITER.
56    Returns true if successful, false if an I/O error was
57    encountered on WRITER or on some object on which WRITER has a
58    dependency. */
59 bool
60 casewriter_destroy (struct casewriter *writer)
61 {
62   bool ok = true;
63   if (writer != NULL)
64     {
65       writer->class->destroy (writer, writer->aux);
66       ok = taint_destroy (writer->taint);
67       free (writer);
68     }
69   return ok;
70 }
71
72 /* Returns the number of `union value's in each case written to
73    WRITER. */
74 size_t
75 casewriter_get_value_cnt (const struct casewriter *writer)
76 {
77   return writer->value_cnt;
78 }
79
80 /* Destroys WRITER and in its place returns a casereader that can
81    be used to read back the data written to WRITER.  WRITER must
82    not be used again after calling this function, even as an
83    argument to casewriter_destroy.
84
85    Not all casewriters implement this function.  Behavior is
86    undefined if it is called on one that does not.
87
88    If an I/O error was encountered on WRITER or on some object on
89    which WRITER has a dependency, then the error will be
90    propagated to the new casereader. */
91 struct casereader *
92 casewriter_make_reader (struct casewriter *writer)
93 {
94   struct casereader *reader;
95   reader = writer->class->convert_to_reader (writer, writer->aux);
96   taint_propagate (writer->taint, casereader_get_taint (reader));
97   taint_destroy (writer->taint);
98   free (writer);
99   return reader;
100 }
101
102 /* Returns a copy of WRITER, which is itself destroyed.
103    Useful for taking over ownership of a casewriter, to enforce
104    preventing the original owner from accessing the casewriter
105    again. */
106 struct casewriter *
107 casewriter_rename (struct casewriter *writer)
108 {
109   struct casewriter *new = xmemdup (writer, sizeof *writer);
110   free (writer);
111   return new;
112 }
113
114 /* Returns true if an I/O error or another hard error has
115    occurred on WRITER, a clone of WRITER, or on some object on
116    which WRITER's data has a dependency, false otherwise. */
117 bool
118 casewriter_error (const struct casewriter *writer)
119 {
120   return taint_is_tainted (writer->taint);
121 }
122
123 /* Marks WRITER as having encountered an error.
124
125    Ordinarily, this function should be called by the
126    implementation of a casewriter, not by the casewriter's
127    client.  Instead, casewriter clients should usually ensure
128    that a casewriter's error state is correct by using
129    taint_propagate to propagate to the casewriter's taint
130    structure, which may be obtained via casewriter_get_taint. */
131 void
132 casewriter_force_error (struct casewriter *writer)
133 {
134   taint_set_taint (writer->taint);
135 }
136
137 /* Returns WRITER's associate taint object, for use with
138    taint_propagate and other taint functions. */
139 const struct taint *
140 casewriter_get_taint (const struct casewriter *writer)
141 {
142   return writer->taint;
143 }
144
145 /* Creates and returns a new casewriter with the given CLASS and
146    auxiliary data AUX.  The casewriter accepts cases with
147    VALUE_CNT `union value's. */
148 struct casewriter *
149 casewriter_create (size_t value_cnt,
150                    const struct casewriter_class *class, void *aux)
151 {
152   struct casewriter *writer = xmalloc (sizeof *writer);
153   writer->taint = taint_create ();
154   writer->value_cnt = value_cnt;
155   writer->case_cnt = 0;
156   writer->class = class;
157   writer->aux = aux;
158   return writer;
159 }
160
161 /* Returns a casewriter for cases with VALUE_CNT struct values
162    per case.  The cases written to the casewriter will be kept in
163    memory, unless the amount of memory used grows too large, in
164    which case they will be written to disk.
165
166    A casewriter created with this function may be passed to
167    casewriter_make_reader.
168
169    This is usually the right kind of casewriter to use. */
170 struct casewriter *
171 autopaging_writer_create (size_t value_cnt)
172 {
173   return create_casewriter_window (value_cnt, get_workspace_cases (value_cnt));
174 }
175
176 /* Returns a casewriter for cases with VALUE_CNT struct values
177    per case.  The cases written to the casewriter will be kept in
178    memory.
179
180    A casewriter created with this function may be passed to
181    casewriter_make_reader. */
182 struct casewriter *
183 mem_writer_create (size_t value_cnt)
184 {
185   return create_casewriter_window (value_cnt, CASENUMBER_MAX);
186 }
187
188 /* Returns a casewriter for cases with VALUE_CNT struct values
189    per case.  The cases written to the casewriter will be written
190    to disk.
191
192    A casewriter created with this function may be passed to
193    casewriter_make_reader. */
194 struct casewriter *
195 tmpfile_writer_create (size_t value_cnt)
196 {
197   return create_casewriter_window (value_cnt, 0);
198 }
199 \f
200 static const struct casewriter_class casewriter_window_class;
201 static const struct casereader_random_class casereader_window_class;
202
203 /* Creates and returns a new casewriter based on a casewindow.
204    Each of the casewriter's cases are composed of VALUE_CNT
205    struct values.  The casewriter's cases will be maintained in
206    memory until MAX_IN_CORE_CASES have been written, at which
207    point they will be written to disk. */
208 static struct casewriter *
209 create_casewriter_window (size_t value_cnt, casenumber max_in_core_cases)
210 {
211   struct casewindow *window = casewindow_create (value_cnt, max_in_core_cases);
212   struct casewriter *writer = casewriter_create (value_cnt,
213                                                  &casewriter_window_class,
214                                                  window);
215   taint_propagate (casewindow_get_taint (window),
216                    casewriter_get_taint (writer));
217   return writer;
218 }
219
220 /* Writes case C to casewindow writer WINDOW. */
221 static void
222 casewriter_window_write (struct casewriter *writer UNUSED, void *window_,
223                          struct ccase *c)
224 {
225   struct casewindow *window = window_;
226   casewindow_push_head (window, c);
227 }
228
229 /* Destroys casewindow writer WINDOW. */
230 static void
231 casewriter_window_destroy (struct casewriter *writer UNUSED, void *window_)
232 {
233   struct casewindow *window = window_;
234   casewindow_destroy (window);
235 }
236
237 /* Converts casewindow writer WINDOW to a casereader and returns
238    the casereader. */
239 static struct casereader *
240 casewriter_window_convert_to_reader (struct casewriter *writer UNUSED,
241                                      void *window_)
242 {
243   struct casewindow *window = window_;
244   struct casereader *reader;
245   reader = casereader_create_random (casewindow_get_value_cnt (window),
246                                      casewindow_get_case_cnt (window),
247                                      &casereader_window_class, window);
248   taint_propagate (casewindow_get_taint (window),
249                    casereader_get_taint (reader));
250   return reader;
251 }
252
253 /* Reads the case at the given 0-based OFFSET from the front of
254    WINDOW into C.  Returns true if successful, false if
255    OFFSET is beyond the end of file or upon I/O error. */
256 static bool
257 casereader_window_read (struct casereader *reader UNUSED, void *window_,
258                         casenumber offset, struct ccase *c)
259 {
260   struct casewindow *window = window_;
261   if (offset >= casewindow_get_case_cnt (window))
262     return false;
263   else
264     return casewindow_get_case (window, offset, c);
265 }
266
267 /* Destroys casewindow reader WINDOW. */
268 static void
269 casereader_window_destroy (struct casereader *reader UNUSED, void *window_)
270 {
271   struct casewindow *window = window_;
272   casewindow_destroy (window);
273 }
274
275 /* Discards CASE_CNT cases from the front of WINDOW. */
276 static void
277 casereader_window_advance (struct casereader *reader UNUSED, void *window_,
278                            casenumber case_cnt)
279 {
280   struct casewindow *window = window_;
281   casewindow_pop_tail (window, case_cnt);
282 }
283
284 /* Class for casewindow writer. */
285 static const struct casewriter_class casewriter_window_class =
286   {
287     casewriter_window_write,
288     casewriter_window_destroy,
289     casewriter_window_convert_to_reader,
290   };
291
292 /* Class for casewindow reader. */
293 static const struct casereader_random_class casereader_window_class =
294   {
295     casereader_window_read,
296     casereader_window_destroy,
297     casereader_window_advance,
298   };
299 \f