1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2007 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include <data/casereader.h>
23 #include <data/casereader-provider.h>
24 #include <libpspp/taint.h>
28 /* Casereader that applies a user-supplied function to translate
29 each case into another in an arbitrary fashion. */
31 /* A translating casereader. */
32 struct casereader_translator
34 struct casereader *subreader; /* Source of input cases. */
36 void (*translate) (struct ccase *input, struct ccase *output, void *aux);
37 bool (*destroy) (void *aux);
41 static const struct casereader_class casereader_translator_class;
43 /* Creates and returns a new casereader whose cases are produced
44 by reading from SUBREADER and passing through TRANSLATE, which
45 must create case OUTPUT, with OUTPUT_VALUE_CNT values, and
46 populate it based on INPUT and auxiliary data AUX. TRANSLATE
47 must also destroy INPUT.
49 When the translating casereader is destroyed, DESTROY will be
50 called to allow any state maintained by TRANSLATE to be freed.
52 After this function is called, SUBREADER must not ever again
53 be referenced directly. It will be destroyed automatically
54 when the translating casereader is destroyed. */
56 casereader_create_translator (struct casereader *subreader,
57 size_t output_value_cnt,
58 void (*translate) (struct ccase *input,
61 bool (*destroy) (void *aux),
64 struct casereader_translator *ct = xmalloc (sizeof *ct);
65 struct casereader *reader;
66 ct->subreader = casereader_rename (subreader);
67 ct->translate = translate;
68 ct->destroy = destroy;
70 reader = casereader_create_sequential (
71 NULL, output_value_cnt, casereader_get_case_cnt (ct->subreader),
72 &casereader_translator_class, ct);
73 taint_propagate (casereader_get_taint (ct->subreader),
74 casereader_get_taint (reader));
78 /* Internal read function for translating casereader. */
80 casereader_translator_read (struct casereader *reader UNUSED,
81 void *ct_, struct ccase *c)
83 struct casereader_translator *ct = ct_;
86 if (casereader_read (ct->subreader, &tmp))
88 ct->translate (&tmp, c, ct->aux);
95 /* Internal destroy function for translating casereader. */
97 casereader_translator_destroy (struct casereader *reader UNUSED, void *ct_)
99 struct casereader_translator *ct = ct_;
100 casereader_destroy (ct->subreader);
101 ct->destroy (ct->aux);
105 /* Casereader class for translating casereader. */
106 static const struct casereader_class casereader_translator_class =
108 casereader_translator_read,
109 casereader_translator_destroy,
116 struct casereader_append_numeric
120 new_value_func *func;
122 void (*destroy) (void *aux);
125 static bool can_destroy (void *can_);
127 static void can_translate (struct ccase *input, struct ccase *output,
130 /* Creates and returns a new casereader whose cases are produced
131 by reading from SUBREADER and appending an additional value,
132 generated by FUNC. AUX is an optional parameter which
133 gets passed to FUNC. FUNC will also receive N as it, which is
134 the ordinal number of the case in the reader. DESTROY is an
135 optional parameter used to destroy AUX.
137 After this function is called, SUBREADER must not ever again
138 be referenced directly. It will be destroyed automatically
139 when the translating casereader is destroyed. */
141 casereader_create_append_numeric (struct casereader *subreader,
142 new_value_func func, void *aux,
143 void (*destroy) (void *aux))
145 struct casereader_append_numeric *can = xmalloc (sizeof *can);
146 can->value_ofs = casereader_get_value_cnt (subreader);
150 can->destroy = destroy;
151 return casereader_create_translator (subreader, can->value_ofs + 1,
152 can_translate, can_destroy, can);
157 can_translate (struct ccase *input, struct ccase *output, void *can_)
159 struct casereader_append_numeric *can = can_;
160 double new_value = can->func (input, can->n++, can->aux);
161 case_nullify (output);
162 case_move (output, input);
163 case_resize (output, can->value_ofs + 1);
164 case_data_rw_idx (output, can->value_ofs)->f = new_value;
168 can_destroy (void *can_)
170 struct casereader_append_numeric *can = can_;
172 can->destroy (can->aux);
179 struct arithmetic_sequence
186 next_arithmetic (const struct ccase *c UNUSED,
190 struct arithmetic_sequence *as = aux;
191 return n * as->increment + as->first;
194 /* Creates and returns a new casereader whose cases are produced
195 by reading from SUBREADER and appending an additional value,
196 which takes the value FIRST in the first case, FIRST +
197 INCREMENT in the second case, FIRST + INCREMENT * 2 in the
198 third case, and so on.
200 After this function is called, SUBREADER must not ever again
201 be referenced directly. It will be destroyed automatically
202 when the translating casereader is destroyed. */
204 casereader_create_arithmetic_sequence (struct casereader *subreader,
205 double first, double increment)
207 struct arithmetic_sequence *as = xzalloc (sizeof *as);
209 as->increment = increment;
210 return casereader_create_append_numeric (subreader, next_arithmetic,