X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fcaseinit.c;h=3efe128efd205c7f618e712a3d6386d5e127c912;hb=54b3aa8432383287c75b9baf954b7bf887126a0c;hp=c93de348728c08ab096ae8f41fae0b543769114a;hpb=339f1956cc727eda788638644ef93ab7852b31cd;p=pspp diff --git a/src/data/caseinit.c b/src/data/caseinit.c index c93de34872..3efe128efd 100644 --- a/src/data/caseinit.c +++ b/src/data/caseinit.c @@ -23,6 +23,7 @@ #include #include "data/case.h" +#include "data/casereader.h" #include "data/dictionary.h" #include "data/value.h" #include "data/variable.h" @@ -47,7 +48,7 @@ struct init_value struct init_list { struct init_value *values; - size_t cnt; + size_t n; }; /* A bitmap of the "left" status of variables. */ @@ -62,23 +63,21 @@ static void init_list_create (struct init_list *list) { list->values = NULL; - list->cnt = 0; + list->n = 0; } /* Initializes NEW as a copy of OLD. */ -static void -init_list_clone (struct init_list *new, const struct init_list *old) +static struct init_list +init_list_clone (const struct init_list *old) { - size_t i; - - new->values = xmemdup (old->values, old->cnt * sizeof *old->values); - new->cnt = old->cnt; - - for (i = 0; i < new->cnt; i++) + struct init_value *values = xmemdup (old->values, + old->n * sizeof *old->values); + for (size_t i = 0; i < old->n; i++) { - struct init_value *iv = &new->values[i]; + struct init_value *iv = &values[i]; value_clone (&iv->value, &iv->value, iv->width); } + return (struct init_list) { .values = values, .n = old->n }; } /* Frees the storage associated with LIST. */ @@ -87,7 +86,7 @@ init_list_destroy (struct init_list *list) { struct init_value *iv; - for (iv = &list->values[0]; iv < &list->values[list->cnt]; iv++) + for (iv = &list->values[0]; iv < &list->values[list->n]; iv++) value_destroy (&iv->value, iv->width); free (list->values); } @@ -117,7 +116,7 @@ init_list_includes (const struct init_list *list, size_t case_index) { struct init_value value; value.case_index = case_index; - return binary_search (list->values, list->cnt, sizeof *list->values, + return binary_search (list->values, list->n, sizeof *list->values, &value, compare_init_values, NULL) != NULL; } @@ -131,7 +130,7 @@ init_list_mark (struct init_list *list, const struct init_list *exclude, size_t n_vars = dict_get_n_vars (d); assert (list != exclude); - list->values = xnrealloc (list->values, list->cnt + dict_get_n_vars (d), + list->values = xnrealloc (list->values, list->n + dict_get_n_vars (d), sizeof *list->values); for (size_t i = 0; i < n_vars; i++) { @@ -147,7 +146,7 @@ init_list_mark (struct init_list *list, const struct init_list *exclude, if (exclude != NULL && init_list_includes (exclude, case_index)) continue; - iv = &list->values[list->cnt++]; + iv = &list->values[list->n++]; iv->case_index = case_index; iv->width = var_get_width (v); value_init (&iv->value, iv->width); @@ -158,8 +157,8 @@ init_list_mark (struct init_list *list, const struct init_list *exclude, } /* Drop duplicates. */ - list->cnt = sort_unique (list->values, list->cnt, sizeof *list->values, - compare_init_values, NULL); + list->n = sort_unique (list->values, list->n, sizeof *list->values, + compare_init_values, NULL); } /* Initializes data in case C to the values in the initializer @@ -169,7 +168,7 @@ init_list_init (const struct init_list *list, struct ccase *c) { const struct init_value *iv; - for (iv = &list->values[0]; iv < &list->values[list->cnt]; iv++) + for (iv = &list->values[0]; iv < &list->values[list->n]; iv++) value_copy (case_data_rw_idx (c, iv->case_index), &iv->value, iv->width); } @@ -180,7 +179,7 @@ init_list_update (const struct init_list *list, const struct ccase *c) { struct init_value *iv; - for (iv = &list->values[0]; iv < &list->values[list->cnt]; iv++) + for (iv = &list->values[0]; iv < &list->values[list->n]; iv++) value_copy (&iv->value, case_data_idx (c, iv->case_index), iv->width); } @@ -218,9 +217,11 @@ struct caseinit * caseinit_clone (struct caseinit *old) { struct caseinit *new = xmalloc (sizeof *new); - init_list_clone (&new->preinited_values, &old->preinited_values); - init_list_clone (&new->reinit_values, &old->reinit_values); - init_list_clone (&new->left_values, &old->left_values); + *new = (struct caseinit) { + .preinited_values = init_list_clone (&old->preinited_values), + .reinit_values = init_list_clone (&old->reinit_values), + .left_values = init_list_clone (&old->left_values), + }; return new; } @@ -272,15 +273,75 @@ void caseinit_init_vars (const struct caseinit *ci, struct ccase *c) { init_list_init (&ci->reinit_values, c); +} + +/* Copies the left vars from CI into C. */ +void +caseinit_restore_left_vars (struct caseinit *ci, struct ccase *c) +{ init_list_init (&ci->left_values, c); } -/* Updates the left vars in CI from the data in C, so that the - next call to caseinit_init_vars will store those values in the - next case. */ +/* Copies the left vars from C into CI. */ void -caseinit_update_left_vars (struct caseinit *ci, const struct ccase *c) +caseinit_save_left_vars (struct caseinit *ci, const struct ccase *c) { init_list_update (&ci->left_values, c); } + +struct caseinit_translator + { + struct init_list reinit_values; + struct caseproto *proto; + }; + +static struct ccase * +translate_caseinit (struct ccase *c, void *cit_) +{ + const struct caseinit_translator *cit = cit_; + + c = case_unshare_and_resize (c, cit->proto); + init_list_init (&cit->reinit_values, c); + return c; +} + +static bool +translate_destroy (void *cit_) +{ + struct caseinit_translator *cit = cit_; + + init_list_destroy (&cit->reinit_values); + caseproto_unref (cit->proto); + free (cit); + + return true; +} + +/* Returns a new casereader that yields each case from R, resized to match + OUTPUT_PROTO and initialized from CI as if with caseinit_init_vars(). Takes + ownership of R. + + OUTPUT_PROTO must be conformable with R's prototype. */ +struct casereader * +caseinit_translate_casereader_to_init_vars (struct caseinit *ci, + const struct caseproto *output_proto, + struct casereader *r) +{ + assert (caseproto_is_conformable (casereader_get_proto (r), output_proto)); + if (caseproto_equal (output_proto, casereader_get_proto (r)) + && ci->reinit_values.n == 0) + return casereader_rename (r); + + struct caseinit_translator *cit = xmalloc (sizeof *cit); + *cit = (struct caseinit_translator) { + .reinit_values = init_list_clone (&ci->reinit_values), + .proto = caseproto_ref (output_proto), + }; + + static const struct casereader_translator_class class = { + .translate = translate_caseinit, + .destroy = translate_destroy, + }; + return casereader_translate_stateless (r, output_proto, &class, cit); +}