a003e7bebab38d0c583c706a35996a62c2cec8ff
[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/fastfile.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 = fastfile_create (sink->value_cnt);
57 }
58
59 /* Writes case C to the storage sink SINK.
60    Returns true if successful, false if an I/O error occurred. */
61 static bool
62 storage_sink_write (struct case_sink *sink, const struct ccase *c)
63 {
64   struct storage_sink_info *info = get_storage_sink_info (sink);
65   return casefile_append (info->casefile, c);
66 }
67
68 /* Destroys internal data in SINK. */
69 static void
70 storage_sink_destroy (struct case_sink *sink)
71 {
72   struct storage_sink_info *info = get_storage_sink_info (sink);
73   casefile_destroy (info->casefile);
74   free (info); 
75 }
76
77 /* Closes the sink and returns a storage source to read back the
78    written data. */
79 static struct case_source *
80 storage_sink_make_source (struct case_sink *sink) 
81 {
82   struct storage_sink_info *info = get_storage_sink_info (sink);
83   struct case_source *source = storage_source_create (info->casefile);
84   info->casefile = NULL;
85   return source;
86 }
87
88 /* Storage sink. */
89 const struct case_sink_class storage_sink_class = 
90   {
91     "storage",
92     storage_sink_open,
93     storage_sink_write,
94     storage_sink_destroy,
95     storage_sink_make_source,
96   };
97 \f
98 /* Storage source. */
99
100 struct storage_source_info 
101   {
102     struct casefile *casefile;  /* Storage. */
103     struct casereader *reader;  /* Reader. */
104   };
105
106 static struct storage_source_info *
107 get_storage_source_info (const struct case_source *source) 
108 {
109   assert (source->class == &storage_source_class);
110   return source->aux;
111 }
112
113 /* Returns the number of cases that will be read by
114    storage_source_read(). */
115 static int
116 storage_source_count (const struct case_source *source) 
117 {
118   struct storage_source_info *info = get_storage_source_info (source);
119   return casefile_get_case_cnt (info->casefile);
120 }
121
122 /* Reads one case into OUTPUT_CASE.
123    Returns true if successful, false at end of file or if an
124    I/O error occurred. */
125 static bool
126 storage_source_read (struct case_source *source, struct ccase *output_case)
127 {
128   struct storage_source_info *info = get_storage_source_info (source);
129   struct ccase casefile_case;
130
131   if (info->reader == NULL)
132     info->reader = casefile_get_reader (info->casefile, NULL);
133
134   if (casereader_read (info->reader, &casefile_case))
135     {
136       case_copy (output_case, 0,
137                  &casefile_case, 0,
138                  casefile_get_value_cnt (info->casefile));
139       return true;
140     }
141   else
142     return false;
143 }
144
145 /* Destroys the source.
146    Returns true if successful read, false if an I/O occurred
147    during destruction or previously. */
148 static bool
149 storage_source_destroy (struct case_source *source)
150 {
151   struct storage_source_info *info = get_storage_source_info (source);
152   bool ok = true;
153   if (info->casefile)
154     {
155       ok = !casefile_error (info->casefile);
156       casefile_destroy (info->casefile); 
157     }
158   free (info);
159   return ok;
160 }
161
162 /* Returns the casefile encapsulated by SOURCE. */
163 struct casefile *
164 storage_source_get_casefile (struct case_source *source) 
165 {
166   struct storage_source_info *info = get_storage_source_info (source);
167   return info->casefile;
168 }
169
170 /* Destroys SOURCE and returns the casefile that it
171    encapsulated. */
172 struct casefile *
173 storage_source_decapsulate (struct case_source *source) 
174 {
175   struct storage_source_info *info = get_storage_source_info (source);
176   struct casefile *casefile = info->casefile;
177   assert (info->reader == NULL);
178   info->casefile = NULL;
179   free_case_source (source);
180   return casefile;
181 }
182
183 /* Creates and returns a new storage source that encapsulates
184    CASEFILE. */
185 struct case_source *
186 storage_source_create (struct casefile *casefile)
187 {
188   struct storage_source_info *info;
189
190   info = xmalloc (sizeof *info);
191   info->casefile = casefile;
192   info->reader = NULL;
193
194   return create_case_source (&storage_source_class, info);
195 }
196
197 /* Storage source. */
198 const struct case_source_class storage_source_class = 
199   {
200     "storage",
201     storage_source_count,
202     storage_source_read,
203     storage_source_destroy,
204   };