better tests
[pspp] / src / data / casereader-select.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
16
17 #include <config.h>
18
19 #include "data/casereader-provider.h"
20
21 #include "gl/xalloc.h"
22
23 struct casereader_select
24   {
25     casenumber by;
26     casenumber i;
27   };
28
29 static bool
30 casereader_select_include (const struct ccase *c UNUSED, void *cs_)
31 {
32   struct casereader_select *cs = cs_;
33   if (++cs->i >= cs->by)
34     {
35       cs->i = 0;
36       return true;
37     }
38   else
39     return false;
40 }
41
42 static bool
43 casereader_select_destroy (void *cs_)
44 {
45   struct casereader_select *cs = cs_;
46   free (cs);
47   return true;
48 }
49
50 /* Returns a casereader that contains cases FIRST though LAST, exclusive, of
51    those within SUBREADER.  (The first case in SUBREADER is number 0.)  If BY
52    is greater than 1, then it specifies a step between cases, e.g.  a BY value
53    of 2 causes the cases numbered FIRST + 1, FIRST + 3, FIRST + 5, and so on
54    to be omitted.
55
56    The caller gives up ownership of SUBREADER, transferring it into this
57    function. */
58 struct casereader *
59 casereader_select (struct casereader *subreader,
60                    casenumber first, casenumber last, casenumber by)
61 {
62   if (by == 0)
63     by = 1;
64
65   casereader_advance (subreader, first);
66   if (last >= first)
67     casereader_truncate (subreader, (last - first) / by * by);
68
69   if (by == 1)
70     return casereader_rename (subreader);
71   else
72     {
73       struct casereader_select *cs = xmalloc (sizeof *cs);
74       cs->by = by;
75       cs->i = by - 1;
76       return casereader_create_filter_func (subreader,
77                                             casereader_select_include,
78                                             casereader_select_destroy,
79                                             cs, NULL);
80     }
81 }