Actually implement the new procedure code and adapt all of its clients
[pspp-builds.git] / src / data / fastfile.c
index 9cdba1567648b002c7848b057ba431be88464ff4..5856d07c80b359fc06ab7002614fa46efdb5945f 100644 (file)
@@ -1,6 +1,5 @@
 /* PSPP - computes sample statistics.
 /* PSPP - computes sample statistics.
-   Copyright (C) 2004, 2006 Free Software Foundation, Inc.
-   Written by Ben Pfaff <blp@gnu.org>.
+   Copyright (C) 2004, 2006, 2007 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
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    02110-1301, USA. */
 
 #include <config.h>
    02110-1301, USA. */
 
 #include <config.h>
+
 #include "casefile.h"
 #include "casefile-private.h"
 #include "fastfile.h"
 #include "casefile.h"
 #include "casefile-private.h"
 #include "fastfile.h"
+
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+
+#include <data/case.h>
+#include <data/make-file.h>
+#include <data/settings.h>
+#include <data/variable.h>
 #include <libpspp/alloc.h>
 #include <libpspp/alloc.h>
-#include "case.h"
 #include <libpspp/compiler.h>
 #include <libpspp/message.h>
 #include <libpspp/compiler.h>
 #include <libpspp/message.h>
+#include <libpspp/misc.h>
+#include <libpspp/str.h>
+
 #include "full-read.h"
 #include "full-write.h"
 #include "full-read.h"
 #include "full-write.h"
-#include <libpspp/misc.h>
-#include "make-file.h"
-#include "settings.h"
-#include "variable.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -86,8 +90,7 @@
           also read with casereaders in this phase, but the
           ability to create new casereaders is curtailed.
 
           also read with casereaders in this phase, but the
           ability to create new casereaders is curtailed.
 
-          In this phase, casereaders could still be cloned (once
-          we eventually implement cloning).
+          In this phase, casereaders could still be cloned.
 
           To transition from phase 1 or 2 to phase 3 and create a
           casereader, call casefile_get_destructive_reader().
 
           To transition from phase 1 or 2 to phase 3 and create a
           casereader, call casefile_get_destructive_reader().
@@ -243,8 +246,7 @@ fastfilereader_get_next_case (struct casereader *cr)
          ffr->buffer_pos = 0;
        }
 
          ffr->buffer_pos = 0;
        }
 
-      case_from_values (&ffr->c, ffr->buffer + ffr->buffer_pos,
-                       ff->value_cnt);
+      case_copy_in (&ffr->c, 0, ffr->buffer + ffr->buffer_pos, ff->value_cnt);
       ffr->buffer_pos += ff->value_cnt;
       
       read_case = &ffr->c;
       ffr->buffer_pos += ff->value_cnt;
       
       read_case = &ffr->c;
@@ -287,6 +289,44 @@ fastfile_get_reader (const struct casefile *cf_)
   return reader;
 }
 
   return reader;
 }
 
+
+/* Creates a copy of the casereader CR, and returns it */
+static struct casereader *
+fastfilereader_clone (const struct casereader *cr)
+{
+  const struct fastfilereader *ffr = (const struct fastfilereader *) cr ;
+  struct fastfilereader *new_ffr = xzalloc (sizeof *new_ffr);
+
+  struct casereader *new_reader = (struct casereader *) new_ffr;
+
+  struct casefile *cf =  casereader_get_casefile (cr);
+  struct fastfile *ff = (struct fastfile *) cf;
+
+  assert (!cf->being_destroyed);
+
+  /* Flush the buffer to disk if it's not empty. */
+  if (ff->mode == WRITE && ff->storage == DISK)
+    flush_buffer (ff);
+
+  ff->mode = READ;
+
+  casereader_register (cf, new_reader, &class_reader);
+
+  new_ffr->case_idx = ffr->case_idx ;
+  new_reader->destructive = cr->destructive;
+  new_ffr->fd = ffr->fd ;
+  new_ffr->buffer = ffr->buffer ;
+  new_ffr->buffer_pos = ffr->buffer_pos;
+
+  if (ff->storage == DISK)
+    reader_open_file (new_ffr);
+
+  return new_reader;
+}
+
+
+
+
 /* Returns the number of `union value's in a case for CF. */
 static size_t
 fastfile_get_value_cnt (const struct casefile *cf)
 /* Returns the number of `union value's in a case for CF. */
 static size_t
 fastfile_get_value_cnt (const struct casefile *cf)
@@ -604,7 +644,7 @@ write_case_to_disk (struct fastfile *ff, const struct ccase *c)
   if (!ff->ok)
     return;
 
   if (!ff->ok)
     return;
 
-  case_to_values (c, ff->buffer + ff->buffer_used, ff->value_cnt);
+  case_copy_out (c, 0, ff->buffer + ff->buffer_used, ff->value_cnt);
   ff->buffer_used += ff->value_cnt;
   if (ff->buffer_used + ff->value_cnt > ff->buffer_size)
     flush_buffer (ff);
   ff->buffer_used += ff->value_cnt;
   if (ff->buffer_used + ff->value_cnt > ff->buffer_size)
     flush_buffer (ff);
@@ -748,4 +788,5 @@ static const struct class_casereader class_reader =
     fastfilereader_get_next_case,
     fastfilereader_cnum,
     fastfilereader_destroy,
     fastfilereader_get_next_case,
     fastfilereader_cnum,
     fastfilereader_destroy,
+    fastfilereader_clone,
   };
   };