1 /* PSPP - computes sample statistics.
2 Copyright (C) 2006 Free Software Foundation, Inc.
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.
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.
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
20 #include "any-reader.h"
26 #include <libpspp/assertion.h>
27 #include <libpspp/message.h>
28 #include "file-handle-def.h"
29 #include "file-name.h"
30 #include "por-file-reader.h"
31 #include "sys-file-reader.h"
32 #include <libpspp/str.h>
33 #include "scratch-reader.h"
37 #define _(msgid) gettext (msgid)
39 /* Type of file backing an any_reader. */
42 SYSTEM_FILE, /* System file. */
43 PORTABLE_FILE, /* Portable file. */
44 SCRATCH_FILE /* Scratch file. */
47 /* Reader for any type of case-structured file. */
50 enum any_reader_type type; /* Type of file. */
51 void *private; /* Private data. */
54 /* Result of type detection. */
57 YES, /* It is this type. */
58 NO, /* It is not this type. */
59 IO_ERROR /* File couldn't be opened. */
62 /* Tries to detect whether HANDLE represents a given type of
63 file, by opening the file and passing it to DETECT, and
64 returns a detect_result. */
65 static enum detect_result
66 try_detect (struct file_handle *handle, bool (*detect) (FILE *))
71 file = fn_open (fh_get_file_name (handle), "rb");
74 msg (ME, _("An error occurred while opening \"%s\": %s."),
75 fh_get_file_name (handle), strerror (errno));
79 is_type = detect (file);
81 fn_close (fh_get_file_name (handle), file);
83 return is_type ? YES : NO;
86 /* If PRIVATE is non-null, creates and returns a new any_reader,
87 initializing its fields to TYPE and PRIVATE. If PRIVATE is a
88 null pointer, just returns a null pointer. */
89 static struct any_reader *
90 make_any_reader (enum any_reader_type type, void *private)
94 struct any_reader *reader = xmalloc (sizeof *reader);
96 reader->private = private;
103 /* Creates an any_reader for HANDLE. On success, returns the new
104 any_reader and stores the file's dictionary into *DICT. On
105 failure, returns a null pointer. */
107 any_reader_open (struct file_handle *handle, struct dictionary **dict)
109 switch (fh_get_referent (handle))
113 enum detect_result result;
115 result = try_detect (handle, sfm_detect);
116 if (result == IO_ERROR)
118 else if (result == YES)
119 return make_any_reader (SYSTEM_FILE,
120 sfm_open_reader (handle, dict, NULL));
122 result = try_detect (handle, pfm_detect);
123 if (result == IO_ERROR)
125 else if (result == YES)
126 return make_any_reader (PORTABLE_FILE,
127 pfm_open_reader (handle, dict, NULL));
129 msg (SE, _("\"%s\" is not a system or portable file."),
130 fh_get_file_name (handle));
135 msg (SE, _("The inline file is not allowed here."));
139 return make_any_reader (SCRATCH_FILE,
140 scratch_reader_open (handle, dict));
145 /* Reads a single case from READER into C.
146 Returns true if successful, false at end of file or on error. */
148 any_reader_read (struct any_reader *reader, struct ccase *c)
150 switch (reader->type)
153 return sfm_read_case (reader->private, c);
156 return pfm_read_case (reader->private, c);
159 return scratch_reader_read_case (reader->private, c);
164 /* Returns true if an I/O error has occurred on READER, false
167 any_reader_error (struct any_reader *reader)
169 switch (reader->type)
172 return sfm_read_error (reader->private);
175 return pfm_read_error (reader->private);
178 return scratch_reader_error (reader->private);
185 any_reader_close (struct any_reader *reader)
190 switch (reader->type)
193 sfm_close_reader (reader->private);
197 pfm_close_reader (reader->private);
201 scratch_reader_close (reader->private);