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,
114 struct casereader_arithmetic_sequence
122 static void cas_translate (struct ccase *input, struct ccase *output,
124 static bool cas_destroy (void *aux);
126 /* Creates and returns a new casereader whose cases are produced
127 by reading from SUBREADER and appending an additional value,
128 which takes the value FIRST in the first case, FIRST +
129 INCREMENT in the second case, FIRST + INCREMENT * 2 in the
130 third case, and so on.
132 After this function is called, SUBREADER must not ever again
133 be referenced directly. It will be destroyed automatically
134 when the translating casereader is destroyed. */
136 casereader_create_arithmetic_sequence (struct casereader *subreader,
137 double first, double increment)
139 /* This could be implemented with a great deal more efficiency
140 and generality. However, this implementation is easy. */
141 struct casereader_arithmetic_sequence *cas = xmalloc (sizeof *cas);
142 cas->value_ofs = casereader_get_value_cnt (subreader);
144 cas->increment = increment;
146 return casereader_create_translator (subreader, cas->value_ofs + 1,
147 cas_translate, cas_destroy, cas);
151 cas_translate (struct ccase *input, struct ccase *output, void *cas_)
153 struct casereader_arithmetic_sequence *cas = cas_;
154 case_nullify (output);
155 case_move (output, input);
156 case_resize (output, cas->value_ofs + 1);
157 case_data_rw_idx (output, cas->value_ofs)->f
158 = cas->first + cas->increment * cas->n++;
162 cas_destroy (void *cas_)
164 struct casereader_arithmetic_sequence *cas = cas_;