treewide: Replace <name>_cnt by n_<name>s and <name>_cap by allocated_<name>.
[pspp] / src / data / casereader-filter.c
index 969bb4fae82f8088d35d88c790ec8d88448b1bea..08151fadd2a5475115f0a1523252399f425b3f68 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2009, 2011 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
 
 #include <config.h>
 
-#include <data/casereader.h>
+#include "data/casereader.h"
 
 #include <stdlib.h>
 
-#include <data/casereader-provider.h>
-#include <data/casewriter.h>
-#include <data/variable.h>
-#include <data/dictionary.h>
-#include <libpspp/taint.h>
-#include <libpspp/message.h>
+#include "data/casereader-provider.h"
+#include "data/casewriter.h"
+#include "data/variable.h"
+#include "data/dictionary.h"
+#include "libpspp/taint.h"
+#include "libpspp/message.h"
 
-#include "xalloc.h"
+#include "gl/xalloc.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -43,7 +43,7 @@ struct casereader_filter
     struct casewriter *exclude; /* Writer that gets filtered cases, or NULL. */
   };
 
-static struct casereader_class casereader_filter_class;
+static const struct casereader_class casereader_filter_class;
 
 /* Creates and returns a casereader whose content is a filtered
    version of the data in SUBREADER.  Only the cases for which
@@ -78,7 +78,7 @@ casereader_create_filter_func (struct casereader *subreader,
   filter->aux = aux;
   filter->exclude = exclude;
   reader = casereader_create_sequential (
-    NULL, casereader_get_value_cnt (filter->subreader), CASENUMBER_MAX,
+    NULL, casereader_get_proto (filter->subreader), CASENUMBER_MAX,
     &casereader_filter_class, filter);
   taint_propagate (casereader_get_taint (filter->subreader),
                    casereader_get_taint (reader));
@@ -86,22 +86,22 @@ casereader_create_filter_func (struct casereader *subreader,
 }
 
 /* Internal read function for filtering casereader. */
-static bool
-casereader_filter_read (struct casereader *reader UNUSED, void *filter_,
-                        struct ccase *c)
+static struct ccase *
+casereader_filter_read (struct casereader *reader UNUSED, void *filter_)
 
 {
   struct casereader_filter *filter = filter_;
   for (;;)
     {
-      if (!casereader_read (filter->subreader, c))
-        return false;
+      struct ccase *c = casereader_read (filter->subreader);
+      if (c == NULL)
+        return NULL;
       else if (filter->include (c, filter->aux))
-        return true;
+        return c;
       else if (filter->exclude != NULL)
         casewriter_write (filter->exclude, c);
       else
-        case_destroy (c);
+        case_unref (c);
     }
 }
 
@@ -115,12 +115,12 @@ casereader_filter_destroy (struct casereader *reader, void *filter_)
      casewriter, if there is one. */
   if (filter->exclude != NULL)
     {
-      struct ccase c;
-      while (casereader_read (filter->subreader, &c))
-        if (filter->include (&c, filter->aux))
-          case_destroy (&c);
+      struct ccase *c;
+      while ((c = casereader_read (filter->subreader)) != NULL)
+        if (filter->include (c, filter->aux))
+          case_unref (c);
         else
-          casewriter_write (filter->exclude, &c);
+          casewriter_write (filter->exclude, c);
     }
 
   casereader_destroy (filter->subreader);
@@ -130,7 +130,7 @@ casereader_filter_destroy (struct casereader *reader, void *filter_)
 }
 
 /* Filtering casereader class. */
-static struct casereader_class casereader_filter_class =
+static const struct casereader_class casereader_filter_class =
   {
     casereader_filter_read,
     casereader_filter_destroy,
@@ -243,8 +243,9 @@ casereader_filter_weight_destroy (void *cfw_)
 struct casereader_filter_missing
   {
     struct variable **vars;     /* Variables whose values to filter. */
-    size_t var_cnt;             /* Number of variables. */
+    size_t n_vars;              /* Number of variables. */
     enum mv_class class;        /* Types of missing values to filter. */
+    casenumber *n_missing;
   };
 
 static bool casereader_filter_missing_include (const struct ccase *, void *);
@@ -252,7 +253,7 @@ static bool casereader_filter_missing_destroy (void *);
 
 /* Creates and returns a casereader that filters out cases from
    READER that have a missing value in the given CLASS for any of
-   the VAR_CNT variables in VARS.  Only cases that have
+   the N_VARS variables in VARS.  Only cases that have
    non-missing values for all of these variables are passed
    through.
 
@@ -264,21 +265,27 @@ static bool casereader_filter_missing_destroy (void *);
    read or, if that never occurs, until the filtering casereader
    is destroyed.
 
+   If N_MISSING is non-null, then after reading, it will be filled
+   with the total number of dropped cases.
+
    After this function is called, READER must not ever again
    be referenced directly.  It will be destroyed automatically
    when the filtering casereader is destroyed. */
 struct casereader *
 casereader_create_filter_missing (struct casereader *reader,
-                                  const struct variable **vars, size_t var_cnt,
+                                  const struct variable *const *vars, size_t n_vars,
                                   enum mv_class class,
+                                 casenumber *n_missing,
                                   struct casewriter *exclude)
 {
-  if (var_cnt > 0 && class != MV_NEVER)
+  if (n_vars > 0 && class != MV_NEVER)
     {
       struct casereader_filter_missing *cfm = xmalloc (sizeof *cfm);
-      cfm->vars = xmemdup (vars, sizeof *vars * var_cnt);
-      cfm->var_cnt = var_cnt;
+      cfm->vars = xmemdup (vars, sizeof *vars * n_vars);
+      cfm->n_vars = n_vars;
       cfm->class = class;
+      cfm->n_missing = n_missing;
+      if (n_missing) *n_missing = 0;
       return casereader_create_filter_func (reader,
                                             casereader_filter_missing_include,
                                             casereader_filter_missing_destroy,
@@ -297,12 +304,16 @@ casereader_filter_missing_include (const struct ccase *c, void *cfm_)
   const struct casereader_filter_missing *cfm = cfm_;
   size_t i;
 
-  for (i = 0; i < cfm->var_cnt; i++)
+  for (i = 0; i < cfm->n_vars; i++)
     {
       struct variable *var = cfm->vars[i];
       const union value *value = case_data (c, var);
       if (var_is_value_missing (var, value, cfm->class))
-        return false;
+       {
+         if (cfm->n_missing)
+           (*cfm->n_missing)++;
+         return false;
+       }
     }
   return true;
 }