Made case_{reader,writer}_class structures const.
[pspp-builds.git] / src / data / casereader-translator.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2007 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.h>
20
21 #include <stdlib.h>
22
23 #include <data/casereader-provider.h>
24 #include <libpspp/taint.h>
25
26 #include "xalloc.h"
27
28 /* Casereader that applies a user-supplied function to translate
29    each case into another in an arbitrary fashion. */
30
31 /* A translating casereader. */
32 struct casereader_translator
33   {
34     struct casereader *subreader; /* Source of input cases. */
35
36     void (*translate) (struct ccase *input, struct ccase *output, void *aux);
37     bool (*destroy) (void *aux);
38     void *aux;
39   };
40
41 static const struct casereader_class casereader_translator_class;
42
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.
48
49    When the translating casereader is destroyed, DESTROY will be
50    called to allow any state maintained by TRANSLATE to be freed.
51
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. */
55 struct casereader *
56 casereader_create_translator (struct casereader *subreader,
57                               size_t output_value_cnt,
58                               void (*translate) (struct ccase *input,
59                                                  struct ccase *output,
60                                                  void *aux),
61                               bool (*destroy) (void *aux),
62                               void *aux)
63 {
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;
69   ct->aux = aux;
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));
75   return reader;
76 }
77
78 /* Internal read function for translating casereader. */
79 static bool
80 casereader_translator_read (struct casereader *reader UNUSED,
81                             void *ct_, struct ccase *c)
82 {
83   struct casereader_translator *ct = ct_;
84   struct ccase tmp;
85
86   if (casereader_read (ct->subreader, &tmp))
87     {
88       ct->translate (&tmp, c, ct->aux);
89       return true;
90     }
91   else
92     return false;
93 }
94
95 /* Internal destroy function for translating casereader. */
96 static void
97 casereader_translator_destroy (struct casereader *reader UNUSED, void *ct_)
98 {
99   struct casereader_translator *ct = ct_;
100   casereader_destroy (ct->subreader);
101   ct->destroy (ct->aux);
102   free (ct);
103 }
104
105 /* Casereader class for translating casereader. */
106 static const struct casereader_class casereader_translator_class =
107   {
108     casereader_translator_read,
109     casereader_translator_destroy,
110     NULL,
111     NULL,
112   };