From cba0d9a3d5873beddd0d241cc672fbf0cdaf0e07 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 25 Nov 2009 21:27:17 -0800 Subject: [PATCH] subcase: Add more useful functions. --- src/data/subcase.c | 85 +++++++++++++++++++++++++++++++++++++++++----- src/data/subcase.h | 20 +++++++++-- 2 files changed, 94 insertions(+), 11 deletions(-) diff --git a/src/data/subcase.c b/src/data/subcase.c index 03098685..32056215 100644 --- a/src/data/subcase.c +++ b/src/data/subcase.c @@ -99,6 +99,27 @@ 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 @@ -107,8 +128,13 @@ bool subcase_add_var (struct subcase *sc, const struct variable *var, enum subcase_direction direction) { - return subcase_add (sc, var_get_case_index (var), - var_get_width (var), direction); + 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. @@ -116,14 +142,35 @@ subcase_add_var (struct subcase *sc, const struct variable *var, in SC. */ bool subcase_add (struct subcase *sc, int case_index, int width, - enum subcase_direction direction) + enum subcase_direction direction) { - struct subcase_field *field; - size_t i; + if (!subcase_contains (sc, case_index)) + { + subcase_add_always (sc, case_index, width, 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 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++]; @@ -131,7 +178,27 @@ subcase_add (struct subcase *sc, int case_index, int width, 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 diff --git a/src/data/subcase.h b/src/data/subcase.h index 6e59da1d..71bf6fd7 100644 --- a/src/data/subcase.h +++ b/src/data/subcase.h @@ -60,17 +60,27 @@ void subcase_clone (struct subcase *, const struct subcase *); void subcase_clear (struct subcase *); void subcase_destroy (struct subcase *); -bool subcase_add (struct subcase *sc, int index, int width, - enum subcase_direction direction); +bool subcase_contains (const struct subcase *, int case_index); +bool subcase_contains_var (const struct subcase *, const struct variable *); +bool subcase_add (struct subcase *, int case_index, int width, + enum subcase_direction direction); bool subcase_add_var (struct subcase *, const struct variable *, enum subcase_direction); +void subcase_add_always (struct subcase *sc, int case_index, int width, + enum subcase_direction direction); +void subcase_add_var_always (struct subcase *, const struct variable *, + enum subcase_direction); +void subcase_add_proto_always (struct subcase *, const struct caseproto *); + const struct caseproto *subcase_get_proto (const struct subcase *); static inline bool subcase_is_empty (const struct subcase *); static inline size_t subcase_get_n_fields (const struct subcase *); +static inline size_t subcase_get_case_index (const struct subcase *, + size_t idx); static inline enum subcase_direction subcase_get_direction ( const struct subcase *, size_t idx); @@ -100,6 +110,12 @@ bool subcase_equal_cx (const struct subcase *, bool subcase_equal_xx (const struct subcase *, const union value *a, const union value *b); +static inline size_t +subcase_get_case_index (const struct subcase *sc, size_t idx) +{ + return sc->fields[idx].case_index; +} + static inline enum subcase_direction subcase_get_direction (const struct subcase *sc, size_t idx) { -- 2.30.2