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