1 /* PSPP - computes sample statistics.
2 Copyright (C) 2007 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 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, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #include <data/casereader.h>
25 #include <data/casereader-provider.h>
26 #include <data/casewriter.h>
27 #include <data/variable.h>
28 #include <data/dictionary.h>
29 #include <libpspp/taint.h>
30 #include <libpspp/message.h>
35 #define _(msgid) gettext (msgid)
37 struct casereader_filter
39 struct casereader *subreader;
40 bool (*include) (const struct ccase *, void *aux);
41 bool (*destroy) (void *aux);
43 struct casewriter *exclude;
46 static struct casereader_class casereader_filter_class;
49 casereader_create_filter_func (struct casereader *subreader,
50 bool (*include) (const struct ccase *,
52 bool (*destroy) (void *aux),
54 struct casewriter *exclude)
56 struct casereader_filter *filter = xmalloc (sizeof *filter);
57 struct casereader *reader;
58 filter->subreader = casereader_rename (subreader);
59 filter->include = include;
60 filter->destroy = destroy;
62 filter->exclude = exclude;
63 reader = casereader_create_sequential (
64 NULL, casereader_get_value_cnt (filter->subreader), CASENUMBER_MAX,
65 &casereader_filter_class, filter);
66 taint_propagate (casereader_get_taint (filter->subreader),
67 casereader_get_taint (reader));
72 casereader_filter_read (struct casereader *reader UNUSED, void *filter_,
76 struct casereader_filter *filter = filter_;
79 if (!casereader_read (filter->subreader, c))
81 else if (filter->include (c, filter->aux))
83 else if (filter->exclude != NULL)
84 casewriter_write (filter->exclude, c);
91 casereader_filter_destroy (struct casereader *reader, void *filter_)
93 struct casereader_filter *filter = filter_;
94 casereader_destroy (filter->subreader);
95 if (filter->destroy != NULL && !filter->destroy (filter->aux))
96 casereader_force_error (reader);
100 static struct casereader_class casereader_filter_class =
102 casereader_filter_read,
103 casereader_filter_destroy,
105 /* We could in fact delegate clone to the subreader, if the
106 filter function is required to have no memory and if we
107 added reference counting. But it might be useful to have
108 filter functions with memory and in any case this would
109 require a little extra work. */
114 struct casereader_filter_weight
116 const struct variable *weight_var;
117 bool *warn_on_invalid;
118 bool local_warn_on_invalid;
122 casereader_filter_weight_include (const struct ccase *c, void *cfw_)
124 struct casereader_filter_weight *cfw = cfw_;
125 double value = case_num (c, cfw->weight_var);
126 if (value >= 0.0 && !var_is_num_missing (cfw->weight_var, value, MV_ANY))
130 if (*cfw->warn_on_invalid)
132 msg (SW, _("At least one case in the data read had a weight value "
133 "that was user-missing, system-missing, zero, or "
134 "negative. These case(s) were ignored."));
135 *cfw->warn_on_invalid = false;
142 casereader_filter_weight_destroy (void *cfw_)
144 struct casereader_filter_weight *cfw = cfw_;
150 casereader_create_filter_weight (struct casereader *reader,
151 const struct dictionary *dict,
152 bool *warn_on_invalid,
153 struct casewriter *exclude)
155 struct variable *weight_var = dict_get_weight (dict);
156 if (weight_var != NULL)
158 struct casereader_filter_weight *cfw = xmalloc (sizeof *cfw);
159 cfw->weight_var = weight_var;
160 cfw->warn_on_invalid = (warn_on_invalid
162 : &cfw->local_warn_on_invalid);
163 cfw->local_warn_on_invalid = true;
164 reader = casereader_create_filter_func (reader,
165 casereader_filter_weight_include,
166 casereader_filter_weight_destroy,
170 reader = casereader_rename (reader);
174 struct casereader_filter_missing
176 struct variable **vars;
182 casereader_filter_missing_include (const struct ccase *c, void *cfm_)
184 const struct casereader_filter_missing *cfm = cfm_;
187 for (i = 0; i < cfm->var_cnt; i++)
189 struct variable *var = cfm->vars[i];
190 const union value *value = case_data (c, var);
191 if (var_is_value_missing (var, value, cfm->class))
198 casereader_filter_missing_destroy (void *cfm_)
200 struct casereader_filter_missing *cfm = cfm_;
207 casereader_create_filter_missing (struct casereader *reader,
208 const struct variable **vars, size_t var_cnt,
210 struct casewriter *exclude)
212 if (var_cnt > 0 && class != MV_NEVER)
214 struct casereader_filter_missing *cfm = xmalloc (sizeof *cfm);
215 cfm->vars = xmemdup (vars, sizeof *vars * var_cnt);
216 cfm->var_cnt = var_cnt;
218 return casereader_create_filter_func (reader,
219 casereader_filter_missing_include,
220 casereader_filter_missing_destroy,
225 return casereader_rename (reader);
230 casereader_counter_include (const struct ccase *c UNUSED, void *counter_)
232 casenumber *counter = counter_;
238 casereader_create_counter (struct casereader *reader, casenumber *counter,
239 casenumber initial_value)
241 *counter = initial_value;
242 return casereader_create_filter_func (reader, casereader_counter_include,
243 NULL, counter, NULL);