Add datasheet.
[pspp-builds.git] / src / data / casefile.c
index 95e0388c4e8733ed74b6a3e89ebd780a0dbbe771..d81ec29efa0a2c9d331ea08114e6b4be8986aaa4 100644 (file)
@@ -1,6 +1,5 @@
 /* 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
@@ -26,6 +25,7 @@
 #include "case.h"
 #include "casefile.h"
 #include "casefile-private.h"
+#include "casefilter.h"
 
 
 struct ccase;
@@ -116,6 +116,24 @@ casereader_cnum(const struct casereader *r)
   return r->class->cnum(r);
 }
 
+static struct ccase *
+get_next_case(struct casereader *reader)
+{
+  struct ccase *read_case = NULL;
+  struct casefile *cf = casereader_get_casefile (reader);
+
+  do 
+    { 
+      if ( casefile_error (cf) )
+       return NULL;
+  
+      read_case = reader->class->get_next_case (reader);
+    } 
+  while ( read_case && reader->filter 
+         && casefilter_skip_case (reader->filter, read_case) ) ;
+
+  return read_case;
+}
 
 /* Reads a copy of the next case from READER into C.
    Caller is responsible for destroying C.
@@ -123,16 +141,11 @@ casereader_cnum(const struct casereader *r)
 bool
 casereader_read (struct casereader *reader, struct ccase *c)
 {
-  struct casefile *cf = casereader_get_casefile (reader);
+  struct ccase * read_case = get_next_case (reader) ;
 
-  struct ccase *read_case = NULL;
-
-  if ( casefile_error (cf) )
+  if ( NULL == read_case ) 
     return false;
 
-  read_case = reader->class->get_next_case (reader);
-  if ( ! read_case ) return false;
-
   case_clone (c, read_case );
 
   return true;
@@ -144,19 +157,18 @@ casereader_read (struct casereader *reader, struct ccase *c)
    Returns true if successful, false at end of file or on I/O
    error. */
 bool
-casereader_read_xfer (struct casereader *ffr, struct ccase *c)
+casereader_read_xfer (struct casereader *reader, struct ccase *c)
 {
-  struct casefile *cf = casereader_get_casefile (ffr);
+  struct casefile *cf = casereader_get_casefile (reader);
+  struct ccase *read_case ;
+  case_nullify (c);
 
-  struct ccase *read_case = NULL ;
+  read_case = get_next_case (reader) ;
 
-  if ( casefile_error (cf) )
+  if ( NULL == read_case )
     return false;
 
-  read_case = ffr->class->get_next_case (ffr);
-  if ( ! read_case ) return false;
-
-  if ( ffr->destructive && casefile_in_core (cf) )
+  if ( reader->destructive && casefile_in_core (cf) )
     case_move (c, read_case);
   else
     case_clone (c, read_case);
@@ -173,6 +185,22 @@ casereader_destroy (struct casereader *r)
   r->class->destroy(r);
 }
 
+/* Creates a copy of R and returns it */
+struct casereader *
+casereader_clone(const struct casereader *r)
+{
+  struct casereader *r2;
+
+  /* Would we ever want to clone a destructive reader ?? */
+  assert ( ! r->destructive ) ;
+
+  r2 = r->class->clone (r);
+
+  r2->filter = r->filter;
+
+  return r2;
+}
+
 /* Destroys casefile CF. */
 void
 casefile_destroy(struct casefile *cf)
@@ -213,10 +241,11 @@ casefile_get_value_cnt (const struct casefile *cf)
 /* Creates and returns a casereader for CF.  A casereader can be used to
    sequentially read the cases in a casefile. */
 struct casereader *
-casefile_get_reader (const struct casefile *cf)
+casefile_get_reader  (const struct casefile *cf, struct casefilter *filter)
 {
   struct casereader *r = cf->class->get_reader(cf);
   r->cf = (struct casefile *) cf;
+  r->filter = filter;
 
   assert (r->class);
   
@@ -245,7 +274,7 @@ casefile_get_destructive_reader (struct casefile *cf)
 bool 
 casefile_append (struct casefile *cf, const struct ccase *c)
 {
-  assert (c->case_data->value_cnt >= casefile_get_value_cnt (cf));
+  assert (case_get_value_cnt (c) >= casefile_get_value_cnt (cf));
 
   return cf->class->append(cf, c);
 }
@@ -256,7 +285,7 @@ casefile_append (struct casefile *cf, const struct ccase *c)
 bool 
 casefile_append_xfer (struct casefile *cf, struct ccase *c)
 {
-  assert (c->case_data->value_cnt >= casefile_get_value_cnt (cf));
+  assert (case_get_value_cnt (c) >= casefile_get_value_cnt (cf));
 
   cf->class->append (cf, c);
   case_destroy (c);