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/casegrouper.h>
25 #include <data/case-ordering.h>
26 #include <data/casereader.h>
27 #include <data/casewriter.h>
28 #include <data/dictionary.h>
29 #include <libpspp/taint.h>
35 struct casereader *reader;
38 bool (*same_group) (const struct ccase *, const struct ccase *, void *aux);
39 void (*destroy) (void *aux);
44 casegrouper_create_func (struct casereader *reader,
45 bool (*same_group) (const struct ccase *,
48 void (*destroy) (void *aux),
51 struct casegrouper *grouper = xmalloc (sizeof *grouper);
52 grouper->reader = casereader_rename (reader);
53 grouper->taint = taint_clone (casereader_get_taint (grouper->reader));
54 grouper->same_group = same_group;
55 grouper->destroy = destroy;
60 /* FIXME: we really shouldn't need a temporary casewriter for the
61 common case where we read an entire group's data before going
64 casegrouper_get_next_group (struct casegrouper *grouper,
65 struct casereader **reader)
67 if (grouper->same_group != NULL)
69 struct casewriter *writer;
70 struct ccase group_case, tmp;
72 if (!casereader_read (grouper->reader, &group_case))
78 writer = autopaging_writer_create (casereader_get_value_cnt (grouper->reader));
79 case_clone (&tmp, &group_case);
80 casewriter_write (writer, &tmp);
82 while (casereader_peek (grouper->reader, 0, &tmp)
83 && grouper->same_group (&group_case, &tmp, grouper->aux))
86 casereader_read (grouper->reader, &discard);
87 case_destroy (&discard);
88 casewriter_write (writer, &tmp);
91 case_destroy (&group_case);
93 *reader = casewriter_make_reader (writer);
98 if (grouper->reader != NULL)
100 *reader = grouper->reader;
101 grouper->reader = NULL;
110 casegrouper_destroy (struct casegrouper *grouper)
114 struct taint *taint = grouper->taint;
117 casereader_destroy (grouper->reader);
118 if (grouper->destroy != NULL)
119 grouper->destroy (grouper->aux);
122 ok = !taint_has_tainted_successor (taint);
123 taint_destroy (taint);
130 struct casegrouper_vars
132 const struct variable **vars;
137 casegrouper_vars_same_group (const struct ccase *a, const struct ccase *b,
140 struct casegrouper_vars *cv = cv_;
141 return case_compare (a, b, cv->vars, cv->var_cnt) == 0;
145 casegrouper_vars_destroy (void *cv_)
147 struct casegrouper_vars *cv = cv_;
153 casegrouper_create_vars (struct casereader *reader,
154 const struct variable *const *vars,
159 struct casegrouper_vars *cv = xmalloc (sizeof *cv);
160 cv->vars = xmemdup (vars, sizeof *vars * var_cnt);
161 cv->var_cnt = var_cnt;
162 return casegrouper_create_func (reader,
163 casegrouper_vars_same_group,
164 casegrouper_vars_destroy,
168 return casegrouper_create_func (reader, NULL, NULL, NULL);
172 casegrouper_create_splits (struct casereader *reader,
173 const struct dictionary *dict)
175 return casegrouper_create_vars (reader,
176 dict_get_split_vars (dict),
177 dict_get_split_cnt (dict));
181 casegrouper_create_case_ordering (struct casereader *reader,
182 const struct case_ordering *co)
184 const struct variable **vars;
186 struct casegrouper *grouper;
188 case_ordering_get_vars (co, &vars, &var_cnt);
189 grouper = casegrouper_create_vars (reader, vars, var_cnt);