Add casereaders and casewriters, the basis of the new data processing
[pspp-builds.git] / src / data / casereader-provider.h
diff --git a/src/data/casereader-provider.h b/src/data/casereader-provider.h
new file mode 100644 (file)
index 0000000..2726f68
--- /dev/null
@@ -0,0 +1,161 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 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
+   published by the Free Software Foundation; either version 2 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.
+
+   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. */
+
+/* Definitions needed to implement a new type of casereader.
+   Code that only uses casereaders does not need this header.
+
+   Two functions to create casereaders are supplied:
+
+        - casereader_create_sequential, to create a casereader
+          for a data source that is naturally sequential.  The
+          casereader layer will automatically, as needed,
+          simulate the ability to access cases randomly.
+
+        - casereader_create_random, to create a casereader for a
+          data source that supports random access to cases.  (This
+          function is in fact implemented as a set of wrappers
+          around casereader_create_sequential.)
+
+   Which function is used has no effect on the set of operations
+   that may be performed on the resulting casereader, only on how
+   the casereader is implemented internally. */
+
+#ifndef DATA_CASEREADER_PROVIDER_H
+#define DATA_CASEREADER_PROVIDER_H 1
+
+#include <data/casereader.h>
+
+/* Casereader class for sequential data sources. */
+struct casereader_class 
+  {
+    /* Mandatory.
+
+       Reads the next case from READER into case C, which the
+       casereader must create and which the client is responsible
+       for destroying.  If successful, returns true and advances
+       READER to the next case, so that the next call to this
+       function will read the next case.  The case just read will
+       never be read again by a call to this function for READER.
+
+       At end of file or upon an I/O error, returns false.  After
+       false is returned once, this function will not be called
+       again for the given READER.
+
+       If an I/O error occurs, this function should call
+       casereader_force_error on READER. */
+    bool (*read) (struct casereader *reader, void *aux, struct ccase *c);
+
+    /* Mandatory.
+
+       Destroys READER.
+
+       If an I/O error is detected during destruction, this
+       function should call casereader_force_error on READER. */
+    void (*destroy) (struct casereader *reader, void *aux);
+
+    /* Optional: if convenient and efficiently implementable,
+       supply this function as an optimization for use by
+       casereader_clone.  (But it might be easier to use the
+       random-access casereader wrapper instead.)
+
+       Creates and returns a clone of READER.  The clone must
+       read the same case data in the same sequence as READER,
+       starting from the same position.  The only allowable
+       exception to this rule is that I/O errors may force the
+       clone or the original casereader to stop reading after
+       differing numbers of cases.
+
+       The clone should have a clone of READER's taint object,
+       accomplished by passing casereader_get_taint (READER) to
+       casereader_create. */
+    struct casereader *(*clone) (struct casereader *reader, void *aux);
+
+    /* Optional: if convenient and efficiently implementable,
+       supply as an optimization for use by casereader_peek.
+       (But it might be easier to use the random-access
+       casereader wrapper instead.)
+
+       Reads the case at 0-based offset IDX from the beginning of
+       READER into case C, which the casereader must create and
+       which the client is responsible for destroying.
+
+       At end of file or upon an I/O error, returns false.  If
+       this function returns false, then it will never be called
+       again for an equal or greater value of IDX, and the "read"
+       member function will never be called to advance as far as
+       IDX cases further into the casereader.  That is, returning
+       false indicates that the casereader has fewer than IDX
+       cases left.
+
+       If an I/O error occurs, this function should call
+       casereader_force_error on READER. */
+    bool (*peek) (struct casereader *reader, void *aux, casenumber idx,
+                  struct ccase *c);
+  };
+
+struct casereader *
+casereader_create_sequential (const struct taint *,
+                              size_t value_cnt, casenumber case_cnt,
+                              const struct casereader_class *, void *);
+\f
+/* Casereader class for random-access data sources. */
+struct casereader_random_class
+  {
+    /* Mandatory.
+
+       Reads the case at 0-based offset IDX from the beginning of
+       READER into case C, which the casereader must create and
+       which the client is responsible for destroying.
+
+       At end of file or upon an I/O error, returns false.  If
+       this function returns false, then it will never be called
+       again for an equal or greater value of IDX, and the "read"
+       member function will never be called to advance as far as
+       IDX cases further into the casereader.  That is, returning
+       false indicates that the casereader has fewer than IDX
+       cases.
+
+       If an I/O error occurs, this function should call
+       casereader_force_error on READER. */
+    bool (*read) (struct casereader *reader, void *aux, casenumber idx,
+                  struct ccase *c);
+
+    /* Mandatory.
+
+       Destroys READER.
+
+       If an I/O error is detected during destruction, this
+       function should call casereader_force_error on READER. */
+    void (*destroy) (struct casereader *reader, void *aux);
+
+    /* Mandatory.
+       
+       A call to this function tells the callee that the CNT
+       cases at the beginning of READER will never be read again.
+       The casereader implementation should free any resources
+       associated with those cases.  After this function returns,
+       the IDX argument in future calls to the "read" function
+       will be relative to remaining cases. */
+    void (*advance) (struct casereader *reader, void *aux, casenumber cnt);
+  };
+
+struct casereader *
+casereader_create_random (size_t value_cnt, casenumber case_cnt,
+                          const struct casereader_random_class *, void *aux);
+
+#endif /* data/casereader-provider.h */