1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2006, 2010, 2011, 2012, 2014 Free Software Foundation, Inc.
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.
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.
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/>. */
19 #include "data/any-reader.h"
27 #include "data/casereader.h"
28 #include "data/dataset.h"
29 #include "data/dictionary.h"
30 #include "data/file-handle-def.h"
31 #include "data/file-name.h"
32 #include "libpspp/assertion.h"
33 #include "libpspp/cast.h"
34 #include "libpspp/message.h"
35 #include "libpspp/str.h"
37 #include "gl/xalloc.h"
40 #define _(msgid) gettext (msgid)
41 #define N_(msgid) (msgid)
43 static const struct any_reader_class dataset_reader_class
;
45 static const struct any_reader_class
*classes
[] =
47 &sys_file_reader_class
,
48 &por_file_reader_class
,
49 &pcp_file_reader_class
,
51 enum { N_CLASSES
= sizeof classes
/ sizeof *classes
};
54 any_reader_detect (const struct file_handle
*file_handle
,
55 const struct any_reader_class
**classp
)
60 int (*detect
) (FILE *);
69 file
= fn_open (file_handle
, "rb");
72 msg (ME
, _("An error occurred while opening `%s': %s."),
73 fh_get_file_name (file_handle
), strerror (errno
));
78 for (int i
= 0; i
< N_CLASSES
; i
++)
80 int rc
= classes
[i
]->detect (file
);
93 msg (ME
, _("Error reading `%s': %s."), fh_get_file_name (file_handle
), strerror (-retval
));
95 fn_close (file_handle
, file
);
101 any_reader_open (struct file_handle
*handle
)
103 switch (fh_get_referent (handle
))
107 const struct any_reader_class
*class;
110 retval
= any_reader_detect (handle
, &class);
114 msg (SE
, _("`%s' is not a system or portable file."),
115 fh_get_file_name (handle
));
119 return class->open (handle
);
123 msg (SE
, _("The inline file is not allowed here."));
127 return dataset_reader_class
.open (handle
);
132 /* gnulib on some systems defines "close" as something else,
133 which causes problems for this code. So undefine it here. */
137 any_reader_close (struct any_reader
*any_reader
)
139 return any_reader
? any_reader
->klass
->close (any_reader
) : true;
143 any_reader_decode (struct any_reader
*any_reader
,
144 const char *encoding
,
145 struct dictionary
**dictp
,
146 struct any_read_info
*info
)
148 const struct any_reader_class
*class = any_reader
->klass
;
149 struct casereader
*reader
;
151 reader
= any_reader
->klass
->decode (any_reader
, encoding
, dictp
, info
);
158 any_reader_get_strings (const struct any_reader
*any_reader
, struct pool
*pool
,
159 char ***labels
, bool **ids
, char ***values
)
161 return (any_reader
->klass
->get_strings
162 ? any_reader
->klass
->get_strings (any_reader
, pool
, labels
, ids
,
168 any_reader_open_and_decode (struct file_handle
*handle
,
169 const char *encoding
,
170 struct dictionary
**dictp
,
171 struct any_read_info
*info
)
173 struct any_reader
*any_reader
= any_reader_open (handle
);
175 ? any_reader_decode (any_reader
, encoding
, dictp
, info
)
179 struct dataset_reader
181 struct any_reader any_reader
;
182 struct dictionary
*dict
;
183 struct casereader
*reader
;
186 /* Opens FH, which must have referent type FH_REF_DATASET, and returns a
187 dataset_reader for it, or a null pointer on failure. Stores a copy of the
188 dictionary for the dataset file into *DICT. The caller takes ownership of
189 the casereader and the dictionary. */
190 static struct any_reader
*
191 dataset_reader_open (struct file_handle
*fh
)
193 struct dataset_reader
*reader
;
196 /* We don't bother doing fh_lock or fh_ref on the file handle,
197 as there's no advantage in this case, and doing these would
198 require us to keep track of the "struct file_handle" and
199 "struct fh_lock" and undo our work later. */
200 assert (fh_get_referent (fh
) == FH_REF_DATASET
);
202 ds
= fh_get_dataset (fh
);
203 if (ds
== NULL
|| !dataset_has_source (ds
))
205 msg (SE
, _("Cannot read from dataset %s because no dictionary or data "
206 "has been written to it yet."),
211 reader
= xmalloc (sizeof *reader
);
212 reader
->any_reader
.klass
= &dataset_reader_class
;
213 reader
->dict
= dict_clone (dataset_dict (ds
));
214 reader
->reader
= casereader_clone (dataset_source (ds
));
215 return &reader
->any_reader
;
218 static struct dataset_reader
*
219 dataset_reader_cast (const struct any_reader
*r_
)
221 assert (r_
->klass
== &dataset_reader_class
);
222 return UP_CAST (r_
, struct dataset_reader
, any_reader
);
226 dataset_reader_close (struct any_reader
*r_
)
228 struct dataset_reader
*r
= dataset_reader_cast (r_
);
229 dict_unref (r
->dict
);
230 casereader_destroy (r
->reader
);
236 static struct casereader
*
237 dataset_reader_decode (struct any_reader
*r_
, const char *encoding UNUSED
,
238 struct dictionary
**dictp
, struct any_read_info
*info
)
240 struct dataset_reader
*r
= dataset_reader_cast (r_
);
241 struct casereader
*reader
;
247 memset (info
, 0, sizeof *info
);
248 info
->integer_format
= INTEGER_NATIVE
;
249 info
->float_format
= FLOAT_NATIVE_DOUBLE
;
250 info
->compression
= ANY_COMP_NONE
;
251 info
->case_cnt
= casereader_get_case_cnt (reader
);
258 static const struct any_reader_class dataset_reader_class
=
263 dataset_reader_close
,
264 dataset_reader_decode
,