X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fpor-file-writer.c;h=b956ef459a507b78f6756c1a2a1aefb72ebe5dc7;hb=02c766f3f1ff964f0d4fa4849f1a55e193afa48d;hp=f6ebb73a2bad6df1bfc077ce465992ea674383ec;hpb=480a0746507ce73d26f528b56dc3ed80195096e0;p=pspp
diff --git a/src/data/por-file-writer.c b/src/data/por-file-writer.c
index f6ebb73a2b..b956ef459a 100644
--- a/src/data/por-file-writer.c
+++ b/src/data/por-file-writer.c
@@ -1,20 +1,18 @@
-/* PSPP - computes sample statistics.
+/* PSPP - a program for statistical analysis.
Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+ along with this program. If not, see . */
#include
#include "por-file-writer.h"
@@ -30,14 +28,15 @@
#include
#include
-#include "case.h"
-#include "dictionary.h"
-#include "file-handle-def.h"
-#include "format.h"
-#include "missing-values.h"
-#include "stat-macros.h"
-#include "value-labels.h"
-#include "variable.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
#include
@@ -65,12 +64,15 @@ struct pfm_writer
};
/* A variable to write to the portable file. */
-struct pfm_var
+struct pfm_var
{
int width; /* 0=numeric, otherwise string var width. */
int fv; /* Starting case index. */
};
+static struct casewriter_class por_file_casewriter_class;
+
+static bool close_writer (struct pfm_writer *);
static void buf_write (struct pfm_writer *, const void *, size_t);
static void write_header (struct pfm_writer *);
static void write_version_data (struct pfm_writer *);
@@ -83,7 +85,7 @@ static char *format_trig_int (int, bool force_sign, char[]);
/* Returns default options for writing a portable file. */
struct pfm_write_options
-pfm_writer_default_options (void)
+pfm_writer_default_options (void)
{
struct pfm_write_options opts;
opts.create_writeable = true;
@@ -95,7 +97,7 @@ pfm_writer_default_options (void)
/* Writes the dictionary DICT to portable file HANDLE according
to the given OPTS. Returns nonzero only if successful. DICT
will not be modified, except to assign short names. */
-struct pfm_writer *
+struct casewriter *
pfm_open_writer (struct file_handle *fh, struct dictionary *dict,
struct pfm_write_options opts)
{
@@ -109,7 +111,7 @@ pfm_open_writer (struct file_handle *fh, struct dictionary *dict,
if (opts.create_writeable)
mode |= S_IWUSR | S_IWGRP | S_IWOTH;
fd = open (fh_get_file_name (fh), O_WRONLY | O_CREAT | O_TRUNC, mode);
- if (fd < 0)
+ if (fd < 0)
goto open_error;
/* Open file handle. */
@@ -120,19 +122,19 @@ pfm_open_writer (struct file_handle *fh, struct dictionary *dict,
w = xmalloc (sizeof *w);
w->fh = fh;
w->file = fdopen (fd, "w");
- if (w->file == NULL)
+ if (w->file == NULL)
{
close (fd);
goto open_error;
}
-
+
w->lc = 0;
w->var_cnt = 0;
w->vars = NULL;
-
+
w->var_cnt = dict_get_var_cnt (dict);
w->vars = xnmalloc (w->var_cnt, sizeof *w->vars);
- for (i = 0; i < w->var_cnt; i++)
+ for (i = 0; i < w->var_cnt; i++)
{
const struct variable *dv = dict_get_var (dict, i);
struct pfm_var *pv = &w->vars[i];
@@ -141,7 +143,7 @@ pfm_open_writer (struct file_handle *fh, struct dictionary *dict,
}
w->digits = opts.digits;
- if (w->digits < 1)
+ if (w->digits < 1)
{
msg (ME, _("Invalid decimal digits count %d. Treating as %d."),
w->digits, DBL_DIG);
@@ -154,12 +156,12 @@ pfm_open_writer (struct file_handle *fh, struct dictionary *dict,
write_variables (w, dict);
write_value_labels (w, dict);
buf_write (w, "F", 1);
- if (pfm_write_error (w))
+ if (ferror (w->file))
goto error;
- return w;
+ return casewriter_create (&por_file_casewriter_class, w);
error:
- pfm_close_writer (w);
+ close_writer (w);
return NULL;
open_error:
@@ -168,7 +170,7 @@ pfm_open_writer (struct file_handle *fh, struct dictionary *dict,
fh_get_file_name (fh), strerror (errno));
goto error;
}
-
+
/* Write NBYTES starting at BUF to the portable file represented by
H. Break lines properly every 80 characters. */
static void
@@ -183,7 +185,7 @@ buf_write (struct pfm_writer *w, const void *buf_, size_t nbytes)
while (nbytes + w->lc >= 80)
{
size_t n = 80 - w->lc;
-
+
if (n)
fwrite (buf, n, 1, w->file);
fwrite ("\r\n", 2, 1, w->file);
@@ -241,7 +243,7 @@ write_header (struct pfm_writer *w)
for (i = 0; i < 5; i++)
buf_write (w, "ASCII SPSS PORT FILE ", 40);
-
+
buf_write (w, spss2ascii, 256);
buf_write (w, "SPSSPORT", 8);
}
@@ -262,9 +264,9 @@ write_version_data (struct pfm_writer *w)
tm.tm_mday = 1;
tmp = &tm;
}
- else
+ else
tmp = localtime (&t);
-
+
sprintf (date_str, "%04d%02d%02d",
tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday);
sprintf (time_str, "%02d%02d%02d", tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
@@ -296,10 +298,10 @@ write_value (struct pfm_writer *w, union value *v, struct variable *vv)
{
if (var_is_numeric (vv))
write_float (w, v->f);
- else
+ else
{
write_int (w, var_get_width (vv));
- buf_write (w, v->s, var_get_width (vv));
+ buf_write (w, v->s, var_get_width (vv));
}
}
@@ -310,7 +312,7 @@ write_variables (struct pfm_writer *w, struct dictionary *dict)
int i;
dict_assign_short_names (dict);
-
+
buf_write (w, "4", 1);
write_int (w, dict_get_var_cnt (dict));
write_int (w, 161);
@@ -319,7 +321,7 @@ write_variables (struct pfm_writer *w, struct dictionary *dict)
{
struct variable *v = dict_get_var (dict, i);
struct missing_values mv;
-
+
buf_write (w, "7", 1);
write_int (w, var_get_width (v));
write_string (w, var_get_short_name (v));
@@ -349,7 +351,7 @@ write_variables (struct pfm_writer *w, struct dictionary *dict)
write_float (w, y);
}
}
- while (mv_has_value (&mv))
+ while (mv_has_value (&mv))
{
union value value;
mv_pop_value (&mv, &value);
@@ -357,8 +359,9 @@ write_variables (struct pfm_writer *w, struct dictionary *dict)
write_value (w, &value, v);
}
+ /* Write variable label. */
if (var_get_label (v) != NULL)
- {
+ {
buf_write (w, "C", 1);
write_string (w, var_get_label (v));
}
@@ -387,7 +390,7 @@ write_value_labels (struct pfm_writer *w, const struct dictionary *dict)
write_int (w, val_labs_count (val_labs));
for (vl = val_labs_first_sorted (val_labs, &j); vl != NULL;
- vl = val_labs_next (val_labs, &j))
+ vl = val_labs_next (val_labs, &j))
{
write_value (w, &vl->value, v);
write_string (w, vl->label);
@@ -395,41 +398,47 @@ write_value_labels (struct pfm_writer *w, const struct dictionary *dict)
}
}
-/* Writes case ELEM to the portable file represented by H. */
-int
-pfm_write_case (struct pfm_writer *w, const struct ccase *c)
+/* Writes case C to the portable file represented by H. */
+static void
+por_file_casewriter_write (struct casewriter *writer, void *w_,
+ struct ccase *c)
{
+ struct pfm_writer *w = w_;
int i;
- if (ferror (w->file))
- return 0;
-
- for (i = 0; i < w->var_cnt; i++)
+ if (!ferror (w->file))
{
- struct pfm_var *v = &w->vars[i];
-
- if (v->width == 0)
- write_float (w, case_num_idx (c, v->fv));
- else
- {
- write_int (w, v->width);
- buf_write (w, case_str_idx (c, v->fv), v->width);
- }
+ for (i = 0; i < w->var_cnt; i++)
+ {
+ struct pfm_var *v = &w->vars[i];
+
+ if (v->width == 0)
+ write_float (w, case_num_idx (c, v->fv));
+ else
+ {
+ write_int (w, v->width);
+ buf_write (w, case_str_idx (c, v->fv), v->width);
+ }
+ }
}
+ else
+ casewriter_force_error (writer);
- return !pfm_write_error (w);
+ case_destroy (c);
}
-bool
-pfm_write_error (const struct pfm_writer *w)
+static void
+por_file_casewriter_destroy (struct casewriter *writer, void *w_)
{
- return ferror (w->file);
+ struct pfm_writer *w = w_;
+ if (!close_writer (w))
+ casewriter_force_error (writer);
}
/* Closes a portable file after we're done with it.
Returns true if successful, false if an I/O error occurred. */
-bool
-pfm_close_writer (struct pfm_writer *w)
+static bool
+close_writer (struct pfm_writer *w)
{
bool ok;
@@ -443,17 +452,17 @@ pfm_close_writer (struct pfm_writer *w)
memset (buf, 'Z', sizeof buf);
buf_write (w, buf, w->lc >= 80 ? 80 : 80 - w->lc);
- ok = !pfm_write_error (w);
- if (fclose (w->file) == EOF)
- ok = false;
+ ok = !ferror (w->file);
+ if (fclose (w->file) == EOF)
+ ok = false;
- if (!ok)
+ if (!ok)
msg (ME, _("An I/O error occurred writing portable file \"%s\"."),
fh_get_file_name (w->fh));
}
fh_close (w->fh, "portable file", "we");
-
+
free (w->vars);
free (w);
@@ -476,14 +485,14 @@ pfm_close_writer (struct pfm_writer *w)
/* This is floor(log30(2**31)), the minimum number of trigesimal
digits that a `long int' can hold. */
-#define CHUNK_SIZE 6
+#define CHUNK_SIZE 6
/* pow_tab[i] = pow (30, pow (2, i)) */
static long double pow_tab[16];
/* Initializes pow_tab[]. */
static void
-init_pow_tab (void)
+init_pow_tab (void)
{
static bool did_init = false;
long double power;
@@ -845,3 +854,10 @@ format_trig_double (long double value, int base_10_precision, char output[])
strcpy (output, "*.");
return;
}
+
+static struct casewriter_class por_file_casewriter_class =
+ {
+ por_file_casewriter_write,
+ por_file_casewriter_destroy,
+ NULL,
+ };