Added casereader_clone function.
[pspp-builds.git] / src / language / data-io / get.c
index 0cc628be098797ad6070facc032e84d66f865688..2bb463113c4fcff8d4b49d0dd7aba8818512c3bd 100644 (file)
@@ -26,6 +26,8 @@
 #include <data/case-sink.h>
 #include <data/case-source.h>
 #include <data/case.h>
+#include <data/casefile.h>
+#include <data/fastfile.h>
 #include <data/dictionary.h>
 #include <data/por-file-writer.h>
 #include <data/procedure.h>
@@ -38,7 +40,9 @@
 #include <language/command.h>
 #include <language/data-io/file-handle.h>
 #include <language/lexer/lexer.h>
+#include <language/lexer/variable-parser.h>
 #include <libpspp/alloc.h>
+#include <libpspp/assertion.h>
 #include <libpspp/compiler.h>
 #include <libpspp/hash.h>
 #include <libpspp/message.h>
@@ -438,6 +442,8 @@ parse_write_command (enum writer_type writer_type,
     }
   else
     aw->writer = any_writer_open (handle, dict);
+  if (aw->writer == NULL)
+    goto error;
   dict_destroy (dict);
   
   return aw;
@@ -450,7 +456,7 @@ parse_write_command (enum writer_type writer_type,
 
 /* Writes case C to writer AW. */
 static bool
-case_writer_write_case (struct case_writer *aw, struct ccase *c) 
+case_writer_write_case (struct case_writer *aw, const struct ccase *c) 
 {
   if (aw->map != NULL) 
     {
@@ -462,7 +468,7 @@ case_writer_write_case (struct case_writer *aw, struct ccase *c)
 \f
 /* SAVE and EXPORT. */
 
-static bool output_proc (struct ccase *, void *);
+static bool output_proc (const struct ccase *, void *);
 
 /* Parses and performs the SAVE or EXPORT procedure. */
 static int
@@ -489,7 +495,7 @@ parse_output_proc (enum writer_type writer_type)
 
 /* Writes case C to file. */
 static bool
-output_proc (struct ccase *c, void *aw_) 
+output_proc (const struct ccase *c, void *aw_) 
 {
   struct case_writer *aw = aw_;
   return case_writer_write_case (aw, c);
@@ -536,7 +542,7 @@ parse_output_trns (enum writer_type writer_type)
 
 /* Writes case C to the system file specified on XSAVE or XEXPORT. */
 static int
-output_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED)
+output_trns_proc (void *trns_, struct ccase *c, casenum_t case_num UNUSED)
 {
   struct output_trns *t = trns_;
   case_writer_write_case (t->aw, c);
@@ -779,7 +785,7 @@ struct mtf_proc
     char first[LONG_NAME_LEN + 1], last[LONG_NAME_LEN + 1];
     
     struct dictionary *dict;    /* Dictionary of output file. */
-    struct case_sink *sink;     /* Sink to receive output. */
+    struct casefile *output;    /* MATCH FILES output. */
     struct ccase mtf_case;      /* Case used for output. */
 
     unsigned seq_num;           /* Have we initialized this variable? */
@@ -793,7 +799,7 @@ static bool mtf_delete_file_in_place (struct mtf_proc *, struct mtf_file **);
 
 static bool mtf_read_nonactive_records (void *);
 static bool mtf_processing_finish (void *);
-static bool mtf_processing (struct ccase *, void *);
+static bool mtf_processing (const struct ccase *, void *);
 
 static char *var_type_description (struct variable *);
 
@@ -819,7 +825,7 @@ cmd_match_files (void)
   mtf.first[0] = '\0';
   mtf.last[0] = '\0';
   mtf.dict = dict_create ();
-  mtf.sink = NULL;
+  mtf.output = NULL;
   case_nullify (&mtf.mtf_case);
   mtf.seq_num = 0;
   mtf.seq_nums = NULL;
@@ -839,7 +845,7 @@ cmd_match_files (void)
           saw_table = true;
         }
       else
-        assert (0);
+        NOT_REACHED ();
       lex_match ('=');
 
       file->by = NULL;
@@ -1121,10 +1127,7 @@ cmd_match_files (void)
     discard_variables ();
 
   dict_compact_values (mtf.dict);
-  mtf.sink = create_case_sink (&storage_sink_class, mtf.dict, NULL);
-  if (mtf.sink->class->open != NULL)
-    mtf.sink->class->open (mtf.sink);
-
+  mtf.output = fastfile_create (dict_get_next_value_idx (mtf.dict));
   mtf.seq_nums = xcalloc (dict_get_var_cnt (mtf.dict), sizeof *mtf.seq_nums);
   case_create (&mtf.mtf_case, dict_get_next_value_idx (mtf.dict));
 
@@ -1141,10 +1144,11 @@ cmd_match_files (void)
 
   discard_variables ();
 
+  dict_destroy (default_dict);
   default_dict = mtf.dict;
   mtf.dict = NULL;
-  proc_set_source (mtf.sink->class->make_source (mtf.sink));
-  free_case_sink (mtf.sink);
+  proc_set_source (storage_source_create (mtf.output));
+  mtf.output = NULL;
   
   if (!mtf_free (&mtf))
     ok = false;
@@ -1167,7 +1171,7 @@ mtf_processing_finish (void *mtf_)
     if (iter->handle == NULL)
       {
         if (!mtf_delete_file_in_place (mtf, &iter))
-          abort ();
+          NOT_REACHED ();
         break;
       }
   
@@ -1305,10 +1309,10 @@ mtf_read_nonactive_records (void *mtf_)
 static inline int
 mtf_compare_BY_values (struct mtf_proc *mtf,
                        struct mtf_file *a, struct mtf_file *b,
-                       struct ccase *c)
+                       const struct ccase *c)
 {
-  struct ccase *ca = case_is_null (&a->input) ? c : &a->input;
-  struct ccase *cb = case_is_null (&b->input) ? c : &b->input;
+  const struct ccase *ca = case_is_null (&a->input) ? c : &a->input;
+  const struct ccase *cb = case_is_null (&b->input) ? c : &b->input;
   assert ((a == NULL) + (b == NULL) + (c == NULL) <= 1);
   return case_compare_2dict (ca, cb, a->by, b->by, mtf->by_cnt);
 }
@@ -1316,7 +1320,7 @@ mtf_compare_BY_values (struct mtf_proc *mtf,
 /* Perform one iteration of steps 3...7 above.
    Returns true if successful, false if an I/O error occurred. */
 static bool
-mtf_processing (struct ccase *c, void *mtf_)
+mtf_processing (const struct ccase *c, void *mtf_)
 {
   struct mtf_proc *mtf = mtf_;
 
@@ -1420,7 +1424,7 @@ mtf_processing (struct ccase *c, void *mtf_)
          
              if (mv != NULL && mtf->seq_nums[mv->index] != mtf->seq_num) 
                 {
-                  struct ccase *record
+                  const struct ccase *record
                     = case_is_null (&iter->input) ? c : &iter->input;
                   union value *out = case_data_rw (&mtf->mtf_case, mv->fv);
 
@@ -1467,7 +1471,7 @@ mtf_processing (struct ccase *c, void *mtf_)
        }
 
       /* 5. Write the output record. */
-      mtf->sink->class->write (mtf->sink, &mtf->mtf_case);
+      casefile_append (mtf->output, &mtf->mtf_case);
 
       /* 6. Read another record from each input file FILE and TABLE
         that we stored values from above.  If we come to the end of
@@ -1542,8 +1546,11 @@ mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f)
           if (dv->width == mv->width)
             {
               if (val_labs_count (dv->val_labs)
-                  && !val_labs_count (mv->val_labs))
-                mv->val_labs = val_labs_copy (dv->val_labs);
+                  && !val_labs_count (mv->val_labs)) 
+                {
+                  val_labs_destroy (mv->val_labs);
+                  mv->val_labs = val_labs_copy (dv->val_labs); 
+                }
               if (!mv_is_empty (&dv->miss) && mv_is_empty (&mv->miss))
                 mv_copy (&mv->miss, &dv->miss);
             }