X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fsubcase.c;h=ca4992ae6030d91bd4f5b4f38a8c0d4583075b2b;hb=refs%2Fheads%2Fctables7;hp=948319468c3c1d7a1c43d36663c10a49c6d168f7;hpb=07db00919d6f067fd5dd6c6c1c2c2fba4f42cf21;p=pspp
diff --git a/src/data/subcase.c b/src/data/subcase.c
index 948319468c..ca4992ae60 100644
--- a/src/data/subcase.c
+++ b/src/data/subcase.c
@@ -1,5 +1,5 @@
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009, 2011, 2013 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
@@ -15,13 +15,16 @@
along with this program. If not, see . */
#include
-#include
+
+#include "data/subcase.h"
+
#include
-#include
-#include
-#include
-#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);
@@ -40,18 +43,8 @@ void
subcase_init_vars (struct subcase *sc,
const struct variable *const *vars, size_t n_vars)
{
- size_t i;
-
- sc->fields = xnmalloc (n_vars, sizeof *sc->fields);
- sc->n_fields = n_vars;
- sc->proto = NULL;
- for (i = 0; i < n_vars; i++)
- {
- struct subcase_field *field = &sc->fields[i];
- field->case_index = var_get_case_index (vars[i]);
- field->width = var_get_width (vars[i]);
- field->direction = SC_ASCEND;
- }
+ subcase_init_empty (sc);
+ subcase_add_vars_always (sc, vars, n_vars);
}
/* Initializes SC as a subcase with a single field extracted
@@ -64,6 +57,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)
@@ -83,12 +86,34 @@ subcase_clone (struct subcase *sc, const struct subcase *orig)
/* Frees the memory owned by SC (but not SC itself). */
void
-subcase_destroy (struct subcase *sc)
+subcase_uninit (struct subcase *sc)
{
free (sc->fields);
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 +121,98 @@ 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;
+ if (!subcase_contains_var (sc, var))
+ {
+ subcase_add_var_always (sc, var, direction);
+ return true;
+ }
+ else
+ 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 each of the N_VARS variables in VAR to SC, regardless of
+ whether each variable already has a field in SC. The fields are added with
+ ascending direction. */
+void
+subcase_add_vars_always (struct subcase *sc,
+ const struct variable *const *vars, size_t n_vars)
+{
size_t i;
- for (i = 0; i < sc->n_fields; i++)
- if (sc->fields[i].case_index == case_index)
- return false;
+ sc->fields = xnrealloc (sc->fields,
+ sc->n_fields + n_vars, sizeof *sc->fields);
+ for (i = 0; i < n_vars; i++)
+ {
+ struct subcase_field *field = &sc->fields[sc->n_fields++];
+ field->case_index = var_get_case_index (vars[i]);
+ field->width = var_get_width (vars[i]);
+ field->direction = SC_ASCEND;
+ }
+ invalidate_proto (sc);
+}
+
+/* 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