X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fcaseinit.c;h=021db396d15fe10b45cd74a0c9de3bf09f3143d1;hb=c81025c3b79323fcec83fa848b682c551158c3f0;hp=4f7ece7e03bac3dc6950a2d977a0203ddad62c23;hpb=9a331fe64eb814ae5c1322e21717a04fb254bf65;p=pspp diff --git a/src/data/caseinit.c b/src/data/caseinit.c index 4f7ece7e03..021db396d1 100644 --- a/src/data/caseinit.c +++ b/src/data/caseinit.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2009 Free Software Foundation, Inc. + Copyright (C) 2007, 2009, 2010, 2011 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 @@ -16,21 +16,21 @@ #include -#include +#include "data/caseinit.h" #include #include #include -#include -#include -#include -#include -#include -#include -#include +#include "data/case.h" +#include "data/dictionary.h" +#include "data/value.h" +#include "data/variable.h" +#include "libpspp/array.h" +#include "libpspp/assertion.h" +#include "libpspp/compiler.h" -#include "xalloc.h" +#include "gl/xalloc.h" /* Initializer list: a set of values to write to locations within a case. */ @@ -38,8 +38,9 @@ /* Binds a value with a place to put it. */ struct init_value { - union value value; size_t case_index; + int width; + union value value; }; /* A set of values to initialize in a case. */ @@ -52,7 +53,7 @@ struct init_list /* A bitmap of the "left" status of variables. */ enum leave_class { - LEAVE_REINIT = 0x001, /* Reinitalize for every case. */ + LEAVE_REINIT = 0x001, /* Reinitialize for every case. */ LEAVE_LEFT = 0x002 /* Keep the value from one case to the next. */ }; @@ -64,10 +65,30 @@ init_list_create (struct init_list *list) list->cnt = 0; } +/* Initializes NEW as a copy of OLD. */ +static void +init_list_clone (struct init_list *new, 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 *iv = &new->values[i]; + value_clone (&iv->value, &iv->value, iv->width); + } +} + /* Frees the storage associated with LIST. */ static void init_list_destroy (struct init_list *list) { + struct init_value *iv; + + for (iv = &list->values[0]; iv < &list->values[list->cnt]; iv++) + value_destroy (&iv->value, iv->width); free (list->values); } @@ -111,14 +132,13 @@ init_list_mark (struct init_list *list, const struct init_list *exclude, size_t i; assert (list != exclude); - list->values = xnrealloc (list->values, - list->cnt + dict_get_next_value_idx (d), + list->values = xnrealloc (list->values, list->cnt + dict_get_var_cnt (d), sizeof *list->values); for (i = 0; i < var_cnt; i++) { struct variable *v = dict_get_var (d, i); size_t case_index = var_get_case_index (v); - int offset; + struct init_value *iv; /* Only include the correct class. */ if (!(include & (var_get_leave (v) ? LEAVE_LEFT : LEAVE_REINIT))) @@ -128,19 +148,14 @@ init_list_mark (struct init_list *list, const struct init_list *exclude, if (exclude != NULL && init_list_includes (exclude, case_index)) continue; - offset = 0; - do - { - struct init_value *iv = &list->values[list->cnt++]; - iv->case_index = case_index++; - if (var_is_numeric (v)) - iv->value.f = var_get_leave (v) ? 0 : SYSMIS; - else - memset (iv->value.s, ' ', sizeof iv->value.s); - - offset += sizeof iv->value.s; - } - while (offset < var_get_width (v)); + iv = &list->values[list->cnt++]; + iv->case_index = case_index; + iv->width = var_get_width (v); + value_init (&iv->value, iv->width); + if (var_is_numeric (v) && var_get_leave (v)) + iv->value.f = 0; + else + value_set_missing (&iv->value, iv->width); } /* Drop duplicates. */ @@ -153,13 +168,10 @@ init_list_mark (struct init_list *list, const struct init_list *exclude, static void init_list_init (const struct init_list *list, struct ccase *c) { - size_t i; + const struct init_value *iv; - for (i = 0; i < list->cnt; i++) - { - const struct init_value *value = &list->values[i]; - *case_data_rw_idx (c, value->case_index) = value->value; - } + for (iv = &list->values[0]; iv < &list->values[list->cnt]; iv++) + value_copy (case_data_rw_idx (c, iv->case_index), &iv->value, iv->width); } /* Updates the values in the initializer LIST from the data in @@ -167,13 +179,10 @@ init_list_init (const struct init_list *list, struct ccase *c) static void init_list_update (const struct init_list *list, const struct ccase *c) { - size_t i; + struct init_value *iv; - for (i = 0; i < list->cnt; i++) - { - struct init_value *value = &list->values[i]; - value->value = *case_data_idx (c, value->case_index); - } + for (iv = &list->values[0]; iv < &list->values[list->cnt]; iv++) + value_copy (&iv->value, case_data_idx (c, iv->case_index), iv->width); } /* A case initializer. */ @@ -205,6 +214,17 @@ caseinit_create (void) return ci; } +/* Creates and returns a copy of OLD. */ +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); + return new; +} + /* Clears the contents of case initializer CI. */ void caseinit_clear (struct caseinit *ci)