casereader: New functions casereader_project() and casereader_project_1(). fc11-i386-build47 fc11-x64-build44 lenny-x64-build68
authorBen Pfaff <blp@gnu.org>
Sun, 6 Dec 2009 04:12:54 +0000 (20:12 -0800)
committerBen Pfaff <blp@gnu.org>
Sun, 6 Dec 2009 04:12:54 +0000 (20:12 -0800)
src/data/automake.mk
src/data/casereader-project.c [new file with mode: 0644]
src/data/casereader.h

index a249f5ad4e9557a8c0f5a6e28366dcc322182c1d..3edfce6265dd978e2a509f61654994ec92849c81 100644 (file)
@@ -25,6 +25,7 @@ src_data_libdata_la_SOURCES = \
        src/data/caseinit.c \
        src/data/caseinit.h \
        src/data/casereader-filter.c \
+       src/data/casereader-project.c \
        src/data/casereader-provider.h \
        src/data/casereader-translator.c \
        src/data/casereader.c \
diff --git a/src/data/casereader-project.c b/src/data/casereader-project.c
new file mode 100644 (file)
index 0000000..116a335
--- /dev/null
@@ -0,0 +1,106 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2009 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <data/casereader-provider.h>
+#include <data/subcase.h>
+
+#include "gl/xalloc.h"
+
+static bool
+projection_is_no_op (const struct casereader *reader, const struct subcase *sc)
+{
+  size_t n = subcase_get_n_fields (sc);
+  size_t i;
+
+  if (n != caseproto_get_n_widths (casereader_get_proto (reader)))
+    return false;
+
+  for (i = 0; i < n; i++)
+    if (subcase_get_case_index (sc, i) != i)
+      return false;
+
+  return true;
+}
+
+struct casereader_project
+  {
+    struct subcase old_sc;
+    struct subcase new_sc;
+  };
+
+static struct ccase *
+project_case (struct ccase *old, casenumber idx UNUSED, const void *project_)
+{
+  const struct casereader_project *project = project_;
+  struct ccase *new = case_create (subcase_get_proto (&project->new_sc));
+  subcase_copy (&project->old_sc, old, &project->new_sc, new);
+  case_unref (old);
+  return new;
+}
+
+static bool
+destroy_projection (void *project_)
+{
+  struct casereader_project *project = project_;
+  subcase_destroy (&project->old_sc);
+  subcase_destroy (&project->new_sc);
+  free (project);
+  return true;
+}
+
+/* Returns a casereader in which each row is obtained by extracting the subcase
+   SC from the corresponding row of SUBREADER. */
+struct casereader *
+casereader_project (struct casereader *subreader, const struct subcase *sc)
+{
+  if (projection_is_no_op (subreader, sc))
+    return casereader_rename (subreader);
+  else
+    {
+      struct casereader_project *project = xmalloc (sizeof *project);
+      const struct caseproto *proto;
+
+      subcase_clone (&project->old_sc, sc);
+      proto = subcase_get_proto (&project->old_sc);
+
+      subcase_init_empty (&project->new_sc);
+      subcase_add_proto_always (&project->new_sc, proto);
+
+      return casereader_translate_stateless (subreader, proto,
+                                             project_case, destroy_projection,
+                                             project);
+    }
+}
+
+/* Returns a casereader in which each row is obtained by extracting the value
+   with index COLUMN from the corresponding row of SUBREADER. */
+struct casereader *
+casereader_project_1 (struct casereader *subreader, int column)
+{
+  const struct caseproto *subproto = casereader_get_proto (subreader);
+  struct casereader *reader;
+  struct subcase sc;
+
+  subcase_init (&sc, column, caseproto_get_width (subproto, column),
+                SC_ASCEND);
+  reader = casereader_project (subreader, &sc);
+  subcase_destroy (&sc);
+
+  return reader;
+}
+
index c26657cf5d49a62d7870d0337117c2bfaf8a99d2..62dc4e9176a0798f03222802b6dfb2d82d81bd46 100644 (file)
@@ -58,6 +58,7 @@
 struct dictionary;
 struct casereader;
 struct casewriter;
+struct subcase;
 
 struct ccase *casereader_read (struct casereader *);
 bool casereader_destroy (struct casereader *);
@@ -125,6 +126,9 @@ casereader_translate_stateless (struct casereader *,
                                 bool (*destroy) (void *aux),
                                 void *aux);
 
+struct casereader *casereader_project (struct casereader *,
+                                       const struct subcase *);
+struct casereader *casereader_project_1 (struct casereader *, int column);
 /* A function which creates a numberic value from an existing case */
 typedef double new_value_func (const struct ccase *, casenumber, void *);