Actually implement the new procedure code and adapt all of its clients
[pspp-builds.git] / src / data / por-file-writer.c
index c7c7dd2f211672a68a0cbe5866599b481816f849..bab453d0c5c989cf9d77036cb8e9dca7635dd271 100644 (file)
@@ -1,6 +1,5 @@
 /* PSPP - computes sample statistics.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
-   Written by Ben Pfaff <blp@gnu.org>.
+   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
@@ -19,7 +18,7 @@
 
 #include <config.h>
 #include "por-file-writer.h"
-#include <libpspp/message.h>
+
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <time.h>
 #include <unistd.h>
+
+#include <data/case.h>
+#include <data/casewriter-provider.h>
+#include <data/casewriter.h>
+#include <data/dictionary.h>
+#include <data/file-handle-def.h>
+#include <data/format.h>
+#include <data/missing-values.h>
+#include <data/value-labels.h>
+#include <data/variable.h>
+
 #include <libpspp/alloc.h>
-#include "case.h"
-#include "dictionary.h"
-#include <libpspp/message.h>
-#include "file-handle-def.h"
 #include <libpspp/hash.h>
 #include <libpspp/magic.h>
+#include <libpspp/message.h>
 #include <libpspp/misc.h>
-#include "stat-macros.h"
 #include <libpspp/str.h>
-#include "value-labels.h"
-#include "variable.h"
 #include <libpspp/version.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
-#include <libpspp/debug-print.h>
-
 /* Portable file writer. */
 struct pfm_writer
   {
@@ -70,6 +72,9 @@ struct pfm_var
     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 *);
@@ -94,7 +99,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)
 {
@@ -107,7 +112,7 @@ pfm_open_writer (struct file_handle *fh, struct dictionary *dict,
   mode = S_IRUSR | S_IRGRP | S_IROTH;
   if (opts.create_writeable)
     mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-  fd = open (fh_get_filename (fh), O_WRONLY | O_CREAT | O_TRUNC, mode);
+  fd = open (fh_get_file_name (fh), O_WRONLY | O_CREAT | O_TRUNC, mode);
   if (fd < 0) 
     goto open_error;
 
@@ -135,8 +140,8 @@ pfm_open_writer (struct file_handle *fh, struct dictionary *dict,
     {
       const struct variable *dv = dict_get_var (dict, i);
       struct pfm_var *pv = &w->vars[i];
-      pv->width = dv->width;
-      pv->fv = dv->fv;
+      pv->width = var_get_width (dv);
+      pv->fv = var_get_case_index (dv);
     }
 
   w->digits = opts.digits;
@@ -153,18 +158,18 @@ 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:
   msg (ME, _("An error occurred while opening \"%s\" for writing "
              "as a portable file: %s."),
-       fh_get_filename (fh), strerror (errno));
+       fh_get_file_name (fh), strerror (errno));
   goto error;
 }
 \f  
@@ -282,9 +287,9 @@ write_version_data (struct pfm_writer *w)
 
 /* Write format F to file H. */
 static void
-write_format (struct pfm_writer *w, struct fmt_spec *f)
+write_format (struct pfm_writer *w, const struct fmt_spec *f)
 {
-  write_int (w, formats[f->type].spss);
+  write_int (w, fmt_to_io (f->type));
   write_int (w, f->w);
   write_int (w, f->d);
 }
@@ -293,12 +298,12 @@ write_format (struct pfm_writer *w, struct fmt_spec *f)
 static void
 write_value (struct pfm_writer *w, union value *v, struct variable *vv)
 {
-  if (vv->type == NUMERIC)
+  if (var_is_numeric (vv))
     write_float (w, v->f);
   else 
     {
-      write_int (w, vv->width);
-      buf_write (w, v->s, vv->width); 
+      write_int (w, var_get_width (vv));
+      buf_write (w, v->s, var_get_width (vv)); 
     }
 }
 
@@ -320,13 +325,13 @@ write_variables (struct pfm_writer *w, struct dictionary *dict)
       struct missing_values mv;
       
       buf_write (w, "7", 1);
-      write_int (w, v->width);
-      write_string (w, v->short_name);
-      write_format (w, &v->print);
-      write_format (w, &v->write);
+      write_int (w, var_get_width (v));
+      write_string (w, var_get_short_name (v));
+      write_format (w, var_get_print_format (v));
+      write_format (w, var_get_write_format (v));
 
       /* Write missing values. */
-      mv_copy (&mv, &v->miss);
+      mv_copy (&mv, var_get_missing_values (v));
       while (mv_has_range (&mv))
         {
           double x, y;
@@ -356,10 +361,11 @@ write_variables (struct pfm_writer *w, struct dictionary *dict)
           write_value (w, &value, v);
         }
 
-      if (v->label)
+      /* Write variable label. */
+      if (var_get_label (v) != NULL)
         { 
           buf_write (w, "C", 1);
-          write_string (w, v->label);
+          write_string (w, var_get_label (v));
         }
     }
 }
@@ -374,18 +380,19 @@ write_value_labels (struct pfm_writer *w, const struct dictionary *dict)
     {
       struct val_labs_iterator *j;
       struct variable *v = dict_get_var (dict, i);
+      const struct val_labs *val_labs = var_get_value_labels (v);
       struct val_lab *vl;
 
-      if (!val_labs_count (v->val_labs))
+      if (val_labs == NULL)
        continue;
 
       buf_write (w, "D", 1);
       write_int (w, 1);
-      write_string (w, v->short_name);
-      write_int (w, val_labs_count (v->val_labs));
+      write_string (w, var_get_short_name (v));
+      write_int (w, val_labs_count (val_labs));
 
-      for (vl = val_labs_first_sorted (v->val_labs, &j); vl != NULL;
-           vl = val_labs_next (v->val_labs, &j)) 
+      for (vl = val_labs_first_sorted (val_labs, &j); vl != NULL;
+           vl = val_labs_next (val_labs, &j)) 
         {
           write_value (w, &vl->value, v);
           write_string (w, vl->label);
@@ -393,41 +400,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];
+      for (i = 0; i < w->var_cnt; i++)
+        {
+          struct pfm_var *v = &w->vars[i];
       
-      if (v->width == 0)
-        write_float (w, case_num (c, v->fv));
-      else
-       {
-         write_int (w, v->width);
-          buf_write (w, case_str (c, v->fv), v->width);
-       }
+          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);
+            }
+        } 
     }
-
-  return !pfm_write_error (w);
+  else
+    casewriter_force_error (writer);
+  
+  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;
 
@@ -441,13 +454,13 @@ 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);
+      ok = !ferror (w->file);
       if (fclose (w->file) == EOF) 
         ok = false; 
 
       if (!ok) 
         msg (ME, _("An I/O error occurred writing portable file \"%s\"."),
-             fh_get_filename (w->fh));
+             fh_get_file_name (w->fh));
     }
 
   fh_close (w->fh, "portable file", "we");
@@ -843,3 +856,10 @@ format_trig_double (long double value, int base_10_precision, char output[])
   strcpy (output, "*.");
   return;
 }
+\f
+static struct casewriter_class por_file_casewriter_class = 
+  {
+    por_file_casewriter_write,
+    por_file_casewriter_destroy,
+    NULL,
+  };