X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fsubcase.c;h=6ffaa4c2bed24a603e3ce0aa267c16661e82f471;hb=2fe0749f0892964767cefadb5fac1c9784e9df84;hp=3e019c7c8497bf3340bf1dc2cce256fe6d85aad4;hpb=2165f59ab9eee5272b4037e45477811627cae078;p=pspp-builds.git diff --git a/src/data/subcase.c b/src/data/subcase.c index 3e019c7c..6ffaa4c2 100644 --- a/src/data/subcase.c +++ b/src/data/subcase.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 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 @@ -23,13 +23,15 @@ #include "xalloc.h" +static void invalidate_proto (struct subcase *sc); + /* Initializes SC as a subcase that contains no fields. */ void subcase_init_empty (struct subcase *sc) { sc->fields = NULL; sc->n_fields = 0; - sc->n_values = 0; + sc->proto = NULL; } /* Initializes SC as a subcase with fields extracted from the @@ -42,14 +44,13 @@ subcase_init_vars (struct subcase *sc, sc->fields = xnmalloc (n_vars, sizeof *sc->fields); sc->n_fields = n_vars; - sc->n_values = 0; + 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; - sc->n_values += value_cnt_from_width (field->width); } } @@ -63,12 +64,22 @@ 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) { sc->n_fields = 0; - sc->n_values = 0; + invalidate_proto (sc); } /* Initializes SC with the same fields as ORIG. */ @@ -77,7 +88,7 @@ subcase_clone (struct subcase *sc, const struct subcase *orig) { sc->fields = xmemdup (orig->fields, orig->n_fields * sizeof *orig->fields); sc->n_fields = orig->n_fields; - sc->n_values = orig->n_values; + sc->proto = orig->proto ? caseproto_ref (orig->proto) : NULL; } /* Frees the memory owned by SC (but not SC itself). */ @@ -85,8 +96,10 @@ void subcase_destroy (struct subcase *sc) { free (sc->fields); + caseproto_unref (sc->proto); } + /* 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. */ @@ -94,7 +107,17 @@ bool subcase_add_var (struct subcase *sc, const struct variable *var, enum subcase_direction direction) { - size_t case_index = var_get_case_index (var); + return subcase_add (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. + 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) +{ struct subcase_field *field; size_t i; @@ -105,12 +128,30 @@ subcase_add_var (struct subcase *sc, const struct variable *var, 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; - sc->n_values += value_cnt_from_width (field->width); + invalidate_proto (sc); return true; } +/* Obtains a caseproto for a case described by SC. The caller + must not modify or unref the returned case prototype. */ +const struct caseproto * +subcase_get_proto (const struct subcase *sc_) +{ + struct subcase *sc = (struct subcase *) sc_; + + if (sc->proto == NULL) + { + size_t i; + + sc->proto = caseproto_create (); + for (i = 0; i < sc->n_fields; i++) + sc->proto = caseproto_add_width (sc->proto, sc->fields[i].width); + } + return sc->proto; +} + /* Returns true if and only if A and B are conformable, which means that they have the same number of fields and that each corresponding field in A and B have the same width. */ @@ -121,7 +162,7 @@ subcase_conformable (const struct subcase *a, const struct subcase *b) if (a == b) return true; - if (a->n_values != b->n_values || a->n_fields != b->n_fields) + if (a->n_fields != b->n_fields) return false; for (i = 0; i < a->n_fields; i++) if (a->fields[i].width != b->fields[i].width) @@ -130,7 +171,7 @@ subcase_conformable (const struct subcase *a, const struct subcase *b) } /* Copies the fields represented by SC from C into VALUES. - VALUES must have space for at least subcase_get_n_values(SC) + VALUES must have space for at least subcase_get_n_fields(SC) array elements. */ void subcase_extract (const struct subcase *sc, const struct ccase *c, @@ -141,13 +182,13 @@ subcase_extract (const struct subcase *sc, const struct ccase *c, for (i = 0; i < sc->n_fields; i++) { const struct subcase_field *field = &sc->fields[i]; - value_copy (values, case_data_idx (c, field->case_index), field->width); - values += value_cnt_from_width (field->width); + union value *value = &values[i]; + value_copy (value, case_data_idx (c, field->case_index), field->width); } } /* Copies the data in VALUES into the fields in C represented by - SC. VALUES must have at least subcase_get_n_values(SC) array + SC. VALUES must have at least subcase_get_n_fields(SC) array elements, and C must be large enough to contain all the fields in SC. */ void @@ -159,16 +200,18 @@ subcase_inject (const struct subcase *sc, for (i = 0; i < sc->n_fields; i++) { const struct subcase_field *field = &sc->fields[i]; - value_copy (case_data_rw_idx (c, field->case_index), values, + const union value *value = &values[i]; + value_copy (case_data_rw_idx (c, field->case_index), value, field->width); - values += value_cnt_from_width (field->width); } } /* Copies the fields in SRC represented by SRC_SC into the corresponding fields in DST respresented by DST_SC. SRC_SC and DST_SC must be conformable (as tested by - subcase_conformable()). */ + subcase_conformable()). + + DST must not be shared. */ void subcase_copy (const struct subcase *src_sc, const struct ccase *src, const struct subcase *dst_sc, struct ccase *dst) @@ -226,11 +269,11 @@ subcase_compare_3way_xc (const struct subcase *sc, for (i = 0; i < sc->n_fields; i++) { const struct subcase_field *field = &sc->fields[i]; - int cmp = value_compare_3way (a, case_data_idx (b, field->case_index), + int cmp = value_compare_3way (&a[i], + case_data_idx (b, field->case_index), field->width); if (cmp != 0) return field->direction == SC_ASCEND ? cmp : -cmp; - a += value_cnt_from_width (field->width); } return 0; } @@ -259,16 +302,9 @@ subcase_compare_3way_xx (const struct subcase *sc, for (i = 0; i < sc->n_fields; i++) { const struct subcase_field *field = &sc->fields[i]; - size_t n_values; - int cmp; - - cmp = value_compare_3way (a, b, field->width); + int cmp = value_compare_3way (a++, b++, field->width); if (cmp != 0) return field->direction == SC_ASCEND ? cmp : -cmp; - - n_values = value_cnt_from_width (field->width); - a += n_values; - b += n_values; } return 0; } @@ -316,3 +352,11 @@ subcase_equal_xx (const struct subcase *sc, return subcase_compare_3way_xx (sc, a, b) == 0; } +/* Discards SC's case prototype. (It will be recreated if needed + again later.) */ +static void +invalidate_proto (struct subcase *sc) +{ + caseproto_unref (sc->proto); + sc->proto = NULL; +}