1 /* PSPP - computes sample statistics.
2 Copyright (C) 2006 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
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.
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.
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
21 #include "any-reader.h"
27 #include <libpspp/assertion.h>
28 #include <libpspp/message.h>
29 #include "file-handle-def.h"
30 #include "file-name.h"
31 #include "por-file-reader.h"
32 #include "sys-file-reader.h"
33 #include <libpspp/str.h>
34 #include "scratch-reader.h"
38 #define _(msgid) gettext (msgid)
40 /* Type of file backing an any_reader. */
43 SYSTEM_FILE, /* System file. */
44 PORTABLE_FILE, /* Portable file. */
45 SCRATCH_FILE /* Scratch file. */
48 /* Reader for any type of case-structured file. */
51 enum any_reader_type type; /* Type of file. */
52 void *private; /* Private data. */
55 /* Result of type detection. */
58 YES, /* It is this type. */
59 NO, /* It is not this type. */
60 IO_ERROR /* File couldn't be opened. */
63 /* Tries to detect whether HANDLE represents a given type of
64 file, by opening the file and passing it to DETECT, and
65 returns a detect_result. */
66 static enum detect_result
67 try_detect (struct file_handle *handle, bool (*detect) (FILE *))
72 file = fn_open (fh_get_file_name (handle), "rb");
75 msg (ME, _("An error occurred while opening \"%s\": %s."),
76 fh_get_file_name (handle), strerror (errno));
80 is_type = detect (file);
82 fn_close (fh_get_file_name (handle), file);
84 return is_type ? YES : NO;
87 /* If PRIVATE is non-null, creates and returns a new any_reader,
88 initializing its fields to TYPE and PRIVATE. If PRIVATE is a
89 null pointer, just returns a null pointer. */
90 static struct any_reader *
91 make_any_reader (enum any_reader_type type, void *private)
95 struct any_reader *reader = xmalloc (sizeof *reader);
97 reader->private = private;
104 /* Creates an any_reader for HANDLE. On success, returns the new
105 any_reader and stores the file's dictionary into *DICT. On
106 failure, returns a null pointer. */
108 any_reader_open (struct file_handle *handle, struct dictionary **dict)
110 switch (fh_get_referent (handle))
114 enum detect_result result;
116 result = try_detect (handle, sfm_detect);
117 if (result == IO_ERROR)
119 else if (result == YES)
120 return make_any_reader (SYSTEM_FILE,
121 sfm_open_reader (handle, dict, NULL));
123 result = try_detect (handle, pfm_detect);
124 if (result == IO_ERROR)
126 else if (result == YES)
127 return make_any_reader (PORTABLE_FILE,
128 pfm_open_reader (handle, dict, NULL));
130 msg (SE, _("\"%s\" is not a system or portable file."),
131 fh_get_file_name (handle));
136 msg (SE, _("The inline file is not allowed here."));
140 return make_any_reader (SCRATCH_FILE,
141 scratch_reader_open (handle, dict));
146 /* Reads a single case from READER into C.
147 Returns true if successful, false at end of file or on error. */
149 any_reader_read (struct any_reader *reader, struct ccase *c)
151 switch (reader->type)
154 return sfm_read_case (reader->private, c);
157 return pfm_read_case (reader->private, c);
160 return scratch_reader_read_case (reader->private, c);
165 /* Returns true if an I/O error has occurred on READER, false
168 any_reader_error (struct any_reader *reader)
170 switch (reader->type)
173 return sfm_read_error (reader->private);
176 return pfm_read_error (reader->private);
179 return scratch_reader_error (reader->private);
186 any_reader_close (struct any_reader *reader)
191 switch (reader->type)
194 sfm_close_reader (reader->private);
198 pfm_close_reader (reader->private);
202 scratch_reader_close (reader->private);