4ff939cd02a1559ebdcaafeb8b51738ffc9a8973
[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
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    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, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17    02110-1301, USA. */
18
19 #include <config.h>
20
21 #include <data/storage-stream.h>
22
23 #include <assert.h>
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 #include <data/casefile-factory.h>
31
32 #include "xalloc.h"
33
34 /* Storage sink. */
35
36 /* Information about storage sink. */
37 struct storage_sink_info 
38   {
39     struct casefile *casefile;  /* Storage. */
40   };
41
42 static struct storage_sink_info *
43 get_storage_sink_info (struct case_sink *sink) 
44 {
45   assert (sink->class == &storage_sink_class);
46   return sink->aux;
47 }
48
49 /* Initializes a storage sink. */
50 static void
51 storage_sink_open (struct case_sink *sink)
52 {
53   struct storage_sink_info *info;
54
55   sink->aux = info = xmalloc (sizeof *info);
56   info->casefile = sink->factory->create_casefile (sink->factory,
57                                                    sink->value_cnt);
58 }
59
60 /* Writes case C to the storage sink SINK.
61    Returns true if successful, false if an I/O error occurred. */
62 static bool
63 storage_sink_write (struct case_sink *sink, const struct ccase *c)
64 {
65   struct storage_sink_info *info = get_storage_sink_info (sink);
66   return casefile_append (info->casefile, c);
67 }
68
69 /* Destroys internal data in SINK. */
70 static void
71 storage_sink_destroy (struct case_sink *sink)
72 {
73   struct storage_sink_info *info = get_storage_sink_info (sink);
74   casefile_destroy (info->casefile);
75   free (info); 
76 }
77
78 /* Closes the sink and returns a storage source to read back the
79    written data. */
80 static struct case_source *
81 storage_sink_make_source (struct case_sink *sink) 
82 {
83   struct storage_sink_info *info = get_storage_sink_info (sink);
84   struct case_source *source = storage_source_create (info->casefile);
85   info->casefile = NULL;
86   return source;
87 }
88
89 /* Storage sink. */
90 const struct case_sink_class storage_sink_class = 
91   {
92     "storage",
93     storage_sink_open,
94     storage_sink_write,
95     storage_sink_destroy,
96     storage_sink_make_source,
97   };
98 \f
99 /* Storage source. */
100
101 struct storage_source_info 
102   {
103     struct casefile *casefile;  /* Storage. */
104     struct casereader *reader;  /* Reader. */
105   };
106
107 static struct storage_source_info *
108 get_storage_source_info (const struct case_source *source) 
109 {
110   assert (source->class == &storage_source_class);
111   return source->aux;
112 }
113
114 /* Returns the number of cases that will be read by
115    storage_source_read(). */
116 static int
117 storage_source_count (const struct case_source *source) 
118 {
119   struct storage_source_info *info = get_storage_source_info (source);
120   return casefile_get_case_cnt (info->casefile);
121 }
122
123 /* Reads one case into OUTPUT_CASE.
124    Returns true if successful, false at end of file or if an
125    I/O error occurred. */
126 static bool
127 storage_source_read (struct case_source *source, struct ccase *output_case)
128 {
129   struct storage_source_info *info = get_storage_source_info (source);
130   struct ccase casefile_case;
131
132   if (info->reader == NULL)
133     info->reader = casefile_get_reader (info->casefile, NULL);
134
135   if (casereader_read (info->reader, &casefile_case))
136     {
137       case_copy (output_case, 0,
138                  &casefile_case, 0,
139                  casefile_get_value_cnt (info->casefile));
140       return true;
141     }
142   else
143     return false;
144 }
145
146 /* Destroys the source.
147    Returns true if successful read, false if an I/O occurred
148    during destruction or previously. */
149 static bool
150 storage_source_destroy (struct case_source *source)
151 {
152   struct storage_source_info *info = get_storage_source_info (source);
153   bool ok = true;
154   if (info->casefile)
155     {
156       ok = !casefile_error (info->casefile);
157       casefile_destroy (info->casefile); 
158     }
159   free (info);
160   return ok;
161 }
162
163 /* Returns the casefile encapsulated by SOURCE. */
164 struct casefile *
165 storage_source_get_casefile (struct case_source *source) 
166 {
167   struct storage_source_info *info = get_storage_source_info (source);
168   return info->casefile;
169 }
170
171 /* Destroys SOURCE and returns the casefile that it
172    encapsulated. */
173 struct casefile *
174 storage_source_decapsulate (struct case_source *source) 
175 {
176   struct storage_source_info *info = get_storage_source_info (source);
177   struct casefile *casefile = info->casefile;
178   assert (info->reader == NULL);
179   info->casefile = NULL;
180   free_case_source (source);
181   return casefile;
182 }
183
184 /* Creates and returns a new storage source that encapsulates
185    CASEFILE. */
186 struct case_source *
187 storage_source_create (struct casefile *casefile)
188 {
189   struct storage_source_info *info;
190
191   info = xmalloc (sizeof *info);
192   info->casefile = casefile;
193   info->reader = NULL;
194
195   return create_case_source (&storage_source_class, info);
196 }
197
198 /* Storage source. */
199 const struct case_source_class storage_source_class = 
200   {
201     "storage",
202     storage_source_count,
203     storage_source_read,
204     storage_source_destroy,
205   };