Update all #include directives to the currently preferred style.
[pspp-builds.git] / src / data / subcase.c
index 948319468c3c1d7a1c43d36663c10a49c6d168f7..f87093cd18413cbf97351ffdac019e807db33191 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2008, 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
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
-#include <data/subcase.h>
+
+#include "data/subcase.h"
+
 #include <stdlib.h>
-#include <data/case.h>
-#include <data/variable.h>
-#include <libpspp/assertion.h>
 
-#include "xalloc.h"
+#include "data/case.h"
+#include "data/variable.h"
+#include "libpspp/assertion.h"
+
+#include "gl/xalloc.h"
 
 static void invalidate_proto (struct subcase *sc);
 
@@ -64,6 +67,16 @@ subcase_init_var (struct subcase *sc, const struct variable *var,
   subcase_add_var (sc, var, direction);
 }
 
+
+void
+subcase_init (struct subcase *sc, int index, int width,
+                  enum subcase_direction direction)
+{
+  subcase_init_empty (sc);
+  subcase_add (sc, index, width, direction);
+}
+
+
 /* Removes all the fields from SC. */
 void
 subcase_clear (struct subcase *sc)
@@ -89,6 +102,28 @@ subcase_destroy (struct subcase *sc)
   caseproto_unref (sc->proto);
 }
 
+/* Returns true if VAR already has a field in SC,
+   false otherwise. */
+bool
+subcase_contains_var (const struct subcase *sc, const struct variable *var)
+{
+  return subcase_contains (sc, var_get_case_index (var));
+}
+
+/* Returns true if CASE_INDEX already has a field in SC,
+   false otherwise. */
+bool
+subcase_contains (const struct subcase *sc, int case_index)
+{
+  size_t i;
+
+  for (i = 0; i < sc->n_fields; i++)
+    if (sc->fields[i].case_index == case_index)
+      return true;
+
+  return false;
+}
+
 /* Add a field for VAR to SC, with DIRECTION as the sort order.
    Returns true if successful, false if VAR already has a field
    in SC. */
@@ -96,21 +131,77 @@ bool
 subcase_add_var (struct subcase *sc, const struct variable *var,
                  enum subcase_direction direction)
 {
-  size_t case_index = var_get_case_index (var);
-  struct subcase_field *field;
-  size_t i;
+  if (!subcase_contains_var (sc, var))
+    {
+      subcase_add_var_always (sc, var, direction);
+      return true;
+    }
+  else
+    return false;
+}
 
-  for (i = 0; i < sc->n_fields; i++)
-    if (sc->fields[i].case_index == case_index)
-      return false;
+/* Add a field for CASE_INDEX, WIDTH to SC, with DIRECTION as the sort order.
+   Returns true if successful, false if CASE_INDEX already has a field
+   in SC. */
+bool
+subcase_add (struct subcase *sc, int case_index, int width,
+             enum subcase_direction direction)
+{
+  if (!subcase_contains (sc, case_index))
+    {
+      subcase_add_always (sc, case_index, width, direction);
+      return true;
+    }
+  else
+    return false;
+}
+
+/* Add a field for VAR to SC, with DIRECTION as the sort order,
+   regardless of whether VAR already has a field in SC. */
+void
+subcase_add_var_always (struct subcase *sc, const struct variable *var,
+                        enum subcase_direction direction)
+{
+  return subcase_add_always (sc, var_get_case_index (var),
+                             var_get_width (var), direction);
+}
+
+/* Add a field for CASE_INDEX, WIDTH to SC, with DIRECTION as the
+   sort order, regardless of whether CASE_INDEX already has a
+   field in SC. */
+void
+subcase_add_always (struct subcase *sc, int case_index, int width,
+                    enum subcase_direction direction)
+{
+  struct subcase_field *field;
 
   sc->fields = xnrealloc (sc->fields, sc->n_fields + 1, sizeof *sc->fields);
   field = &sc->fields[sc->n_fields++];
   field->case_index = case_index;
-  field->width = var_get_width (var);
+  field->width = width;
   field->direction = direction;
   invalidate_proto (sc);
-  return true;
+}
+
+/* Adds a field to SC for each column in PROTO, so that SC
+   contains all of the columns in PROTO in the same order as a
+   case conforming to PROTO.  The fields are added with
+   ascending direction. */
+void
+subcase_add_proto_always (struct subcase *sc, const struct caseproto *proto)
+{
+  size_t n = caseproto_get_n_widths (proto);
+  size_t i;
+
+  sc->fields = xnrealloc (sc->fields, sc->n_fields + n, sizeof *sc->fields);
+  for (i = 0; i < n; i++)
+    {
+      struct subcase_field *field = &sc->fields[sc->n_fields++];
+      field->case_index = i;
+      field->width = caseproto_get_width (proto, i);
+      field->direction = SC_ASCEND;
+    }
+  invalidate_proto (sc);
 }
 
 /* Obtains a caseproto for a case described by SC.  The caller