X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fcasereader-translator.c;h=0557b65e8d6336452b4b88c4881d901fc289c7f2;hb=b65cf0519aa1db140d30c878978f29b1e23c9cd0;hp=229dac2e54944c8df81088080c1032330c0cd84e;hpb=085d4563d8d5adfb3a2552d6ab1959c3fcacaee0;p=pspp-builds.git diff --git a/src/data/casereader-translator.c b/src/data/casereader-translator.c index 229dac2e..0557b65e 100644 --- a/src/data/casereader-translator.c +++ b/src/data/casereader-translator.c @@ -110,58 +110,104 @@ static const struct casereader_class casereader_translator_class = NULL, NULL, }; + -struct casereader_arithmetic_sequence - { - int value_ofs; - double first; - double increment; - casenumber n; - }; -static void cas_translate (struct ccase *input, struct ccase *output, - void *aux); -static bool cas_destroy (void *aux); +struct casereader_append_numeric +{ + int value_ofs; + casenumber n; + new_value_func *func; + void *aux; + void (*destroy) (void *aux); +}; + +static bool can_destroy (void *can_); + +static void can_translate (struct ccase *input, struct ccase *output, + void *can_); /* Creates and returns a new casereader whose cases are produced by reading from SUBREADER and appending an additional value, - which takes the value FIRST in the first case, FIRST + - INCREMENT in the second case, FIRST + INCREMENT * 2 in the - third case, and so on. + generated by FUNC. AUX is an optional parameter which + gets passed to FUNC. FUNC will also receive N as it, which is + the ordinal number of the case in the reader. DESTROY is an + optional parameter used to destroy AUX. After this function is called, SUBREADER must not ever again be referenced directly. It will be destroyed automatically when the translating casereader is destroyed. */ struct casereader * -casereader_create_arithmetic_sequence (struct casereader *subreader, - double first, double increment) +casereader_create_append_numeric (struct casereader *subreader, + new_value_func func, void *aux, + void (*destroy) (void *aux)) { - /* This could be implemented with a great deal more efficiency - and generality. However, this implementation is easy. */ - struct casereader_arithmetic_sequence *cas = xmalloc (sizeof *cas); - cas->value_ofs = casereader_get_value_cnt (subreader); - cas->first = first; - cas->increment = increment; - cas->n = 0; - return casereader_create_translator (subreader, cas->value_ofs + 1, - cas_translate, cas_destroy, cas); + struct casereader_append_numeric *can = xmalloc (sizeof *can); + can->value_ofs = casereader_get_value_cnt (subreader); + can->n = 0; + can->aux = aux; + can->func = func; + can->destroy = destroy; + return casereader_create_translator (subreader, can->value_ofs + 1, + can_translate, can_destroy, can); } + static void -cas_translate (struct ccase *input, struct ccase *output, void *cas_) +can_translate (struct ccase *input, struct ccase *output, void *can_) { - struct casereader_arithmetic_sequence *cas = cas_; + struct casereader_append_numeric *can = can_; + double new_value = can->func (input, can->n++, can->aux); case_nullify (output); case_move (output, input); - case_resize (output, cas->value_ofs + 1); - case_data_rw_idx (output, cas->value_ofs)->f - = cas->first + cas->increment * cas->n++; + case_resize (output, can->value_ofs + 1); + case_data_rw_idx (output, can->value_ofs)->f = new_value; } static bool -cas_destroy (void *cas_) +can_destroy (void *can_) { - struct casereader_arithmetic_sequence *cas = cas_; - free (cas); + struct casereader_append_numeric *can = can_; + if (can->destroy) + can->destroy (can->aux); + free (can); return true; } + + + +struct arithmetic_sequence +{ + double first; + double increment; +}; + +static double +next_arithmetic (const struct ccase *c UNUSED, + casenumber n, + void *aux) +{ + struct arithmetic_sequence *as = aux; + return n * as->increment + as->first; +} + +/* Creates and returns a new casereader whose cases are produced + by reading from SUBREADER and appending an additional value, + which takes the value FIRST in the first case, FIRST + + INCREMENT in the second case, FIRST + INCREMENT * 2 in the + third case, and so on. + + After this function is called, SUBREADER must not ever again + be referenced directly. It will be destroyed automatically + when the translating casereader is destroyed. */ +struct casereader * +casereader_create_arithmetic_sequence (struct casereader *subreader, + double first, double increment) +{ + struct arithmetic_sequence *as = xzalloc (sizeof *as); + as->first = first; + as->increment = increment; + return casereader_create_append_numeric (subreader, next_arithmetic, + as, free); +} +