Fix segfault.
[pspp-builds.git] / src / data / storage-stream.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
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.
9
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.
14
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
18    02110-1301, USA. */
19
20 #include <config.h>
21
22 #include <data/storage-stream.h>
23
24 #include <stdlib.h>
25
26 #include <data/case-sink.h>
27 #include <data/case-source.h>
28 #include <data/case.h>
29 #include <data/casefile.h> 
30
31 #include "xalloc.h"
32
33 /* Information about storage sink or source. */
34 struct storage_stream_info 
35   {
36     struct casefile *casefile;  /* Storage. */
37   };
38 \f
39 /* Storage sink. */
40
41 /* Initializes a storage sink. */
42 static void
43 storage_sink_open (struct case_sink *sink)
44 {
45   struct storage_stream_info *info;
46
47   sink->aux = info = xmalloc (sizeof *info);
48   info->casefile = casefile_create (sink->value_cnt);
49 }
50
51 /* Destroys storage stream represented by INFO. */
52 static void
53 destroy_storage_stream_info (struct storage_stream_info *info) 
54 {
55   if (info != NULL) 
56     {
57       casefile_destroy (info->casefile);
58       free (info); 
59     }
60 }
61
62 /* Writes case C to the storage sink SINK.
63    Returns true if successful, false if an I/O error occurred. */
64 static bool
65 storage_sink_write (struct case_sink *sink, const struct ccase *c)
66 {
67   struct storage_stream_info *info = sink->aux;
68
69   return casefile_append (info->casefile, c);
70 }
71
72 /* Destroys internal data in SINK. */
73 static void
74 storage_sink_destroy (struct case_sink *sink)
75 {
76   destroy_storage_stream_info (sink->aux);
77 }
78
79 /* Closes the sink and returns a storage source to read back the
80    written data. */
81 static struct case_source *
82 storage_sink_make_source (struct case_sink *sink) 
83 {
84   struct case_source *source
85     = create_case_source (&storage_source_class, sink->aux);
86   sink->aux = NULL;
87   return source;
88 }
89
90 /* Storage sink. */
91 const struct case_sink_class storage_sink_class = 
92   {
93     "storage",
94     storage_sink_open,
95     storage_sink_write,
96     storage_sink_destroy,
97     storage_sink_make_source,
98   };
99 \f
100 /* Storage source. */
101
102 /* Returns the number of cases that will be read by
103    storage_source_read(). */
104 static int
105 storage_source_count (const struct case_source *source) 
106 {
107   struct storage_stream_info *info = source->aux;
108
109   return casefile_get_case_cnt (info->casefile);
110 }
111
112 /* Reads all cases from the storage source and passes them one by one to
113    write_case(). */
114 static bool
115 storage_source_read (struct case_source *source,
116                      struct ccase *output_case,
117                      write_case_func *write_case, write_case_data wc_data)
118 {
119   struct storage_stream_info *info = source->aux;
120   struct ccase casefile_case;
121   struct casereader *reader;
122   bool ok = true;
123
124   for (reader = casefile_get_reader (info->casefile);
125        ok && casereader_read (reader, &casefile_case);
126        case_destroy (&casefile_case))
127     {
128       case_copy (output_case, 0,
129                  &casefile_case, 0,
130                  casefile_get_value_cnt (info->casefile));
131       ok = write_case (wc_data);
132     }
133   casereader_destroy (reader);
134
135   return ok;
136 }
137
138 /* Destroys the source's internal data. */
139 static void
140 storage_source_destroy (struct case_source *source)
141 {
142   destroy_storage_stream_info (source->aux);
143 }
144
145 /* Storage source. */
146 const struct case_source_class storage_source_class = 
147   {
148     "storage",
149     storage_source_count,
150     storage_source_read,
151     storage_source_destroy,
152   };
153
154 /* Returns the casefile encapsulated by SOURCE. */
155 struct casefile *
156 storage_source_get_casefile (struct case_source *source) 
157 {
158   struct storage_stream_info *info = source->aux;
159
160   assert (source->class == &storage_source_class);
161   return info->casefile;
162 }
163
164 /* Destroys SOURCE and returns the casefile that it
165    encapsulated. */
166 struct casefile *
167 storage_source_decapsulate (struct case_source *source) 
168 {
169   struct storage_stream_info *info = source->aux;
170   struct casefile *casefile;
171
172   assert (source->class == &storage_source_class);
173   casefile = info->casefile;
174   info->casefile = NULL;
175   destroy_storage_stream_info (info);
176   return casefile;
177 }
178
179 /* Creates and returns a new storage stream that encapsulates
180    CASEFILE. */
181 struct case_source *
182 storage_source_create (struct casefile *casefile)
183 {
184   struct storage_stream_info *info;
185
186   info = xmalloc (sizeof *info);
187   info->casefile = casefile;
188
189   return create_case_source (&storage_source_class, info);
190 }