X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fsubcase.c;h=ca4992ae6030d91bd4f5b4f38a8c0d4583075b2b;hb=3f3b74c2dd0e8468e11b0bb22366f6081ba0d459;hp=be58609693900cc5d02fff87a5d225f8a4002688;hpb=5c3291dc396b795696e94f47780308fd7ace6fc4;p=pspp diff --git a/src/data/subcase.c b/src/data/subcase.c index be58609693..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 @@ -118,7 +220,7 @@ subcase_add_var (struct subcase *sc, const struct variable *var, const struct caseproto * subcase_get_proto (const struct subcase *sc_) { - struct subcase *sc = (struct subcase *) sc_; + struct subcase *sc = CONST_CAST (struct subcase *, sc_); if (sc->proto == NULL) {