X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fcase-map.c;h=cff621f3456df7438562aa57d79dd78c4905fb3e;hb=b48a20de787a6374000174949dcd8f9666ecc51c;hp=a1a65cc181564e784ab4d8a7f2b230501cf0fcc1;hpb=9db3101d0bbbcfb687acd3e442e550557e4e56b1;p=pspp-builds.git diff --git a/src/data/case-map.c b/src/data/case-map.c index a1a65cc1..cff621f3 100644 --- a/src/data/case-map.c +++ b/src/data/case-map.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2007, 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 @@ -19,13 +19,17 @@ #include #include +#include +#include +#include #include #include #include -#include #include +#include "xalloc.h" + /* A case map. */ struct case_map { @@ -34,6 +38,9 @@ struct case_map corresponding source index. */ }; +static struct ccase *translate_case (struct ccase *, void *map_); +static bool destroy_case_map (void *map_); + /* Creates and returns an empty map. */ static struct case_map * create_case_map (size_t n) @@ -76,20 +83,30 @@ case_map_destroy (struct case_map *map) } } -/* Maps from SRC to DST, applying case map MAP. */ -void -case_map_execute (const struct case_map *map, - const struct ccase *src, struct ccase *dst) -{ - size_t dst_idx; +/* If MAP is nonnull, returns a new case that is the result of + applying case map MAP to SRC, and unrefs SRC. - case_create (dst, map->value_cnt); - for (dst_idx = 0; dst_idx < map->value_cnt; dst_idx++) + If MAP is null, returns SRC unchanged. */ +struct ccase * +case_map_execute (const struct case_map *map, struct ccase *src) +{ + if (map != NULL) { - int src_idx = map->map[dst_idx]; - if (src_idx != -1) - *case_data_rw_idx (dst, dst_idx) = *case_data_idx (src, src_idx); + struct ccase *dst; + size_t dst_idx; + + dst = case_create (map->value_cnt); + for (dst_idx = 0; dst_idx < map->value_cnt; dst_idx++) + { + int src_idx = map->map[dst_idx]; + if (src_idx != -1) + *case_data_rw_idx (dst, dst_idx) = *case_data_idx (src, src_idx); + } + case_unref (src); + return dst; } + else + return src; } /* Returns the number of `union value's in cases created by @@ -100,6 +117,62 @@ case_map_get_value_cnt (const struct case_map *map) return map->value_cnt; } +/* Creates and returns a new casereader whose cases are produced + by reading from SUBREADER and executing the actions of MAP. + The casereader will have as many `union value's as MAP. When + the new casereader is destroyed, MAP will be destroyed too. + + After this function is called, SUBREADER must not ever again + be referenced directly. It will be destroyed automatically + when the returned casereader is destroyed. */ +struct casereader * +case_map_create_input_translator (struct case_map *map, + struct casereader *subreader) +{ + return casereader_create_translator (subreader, + case_map_get_value_cnt (map), + translate_case, + destroy_case_map, + map); +} + +/* Creates and returns a new casewriter. Cases written to the + new casewriter will be passed through MAP and written to + SUBWRITER. The casewriter will have as many `union value's as + MAP. When the new casewriter is destroyed, MAP will be + destroyed too. + + After this function is called, SUBWRITER must not ever again + be referenced directly. It will be destroyed automatically + when the returned casewriter is destroyed. */ +struct casewriter * +case_map_create_output_translator (struct case_map *map, + struct casewriter *subwriter) +{ + return casewriter_create_translator (subwriter, + case_map_get_value_cnt (map), + translate_case, + destroy_case_map, + map); +} + +/* Casereader/casewriter translation callback. */ +static struct ccase * +translate_case (struct ccase *input, void *map_) +{ + struct case_map *map = map_; + return case_map_execute (map, input); +} + +/* Casereader/casewriter destruction callback. */ +static bool +destroy_case_map (void *map_) +{ + struct case_map *map = map_; + case_map_destroy (map); + return true; +} + /* Creates and returns a case_map that can be used to compact cases for dictionary D.