Clean up how transformations work.
[pspp] / src / data / transformations.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2009, 2011, 2013 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/transformations.h"
20
21 #include <assert.h>
22 #include <stdlib.h>
23
24 #include "libpspp/str.h"
25
26 #include "gl/xalloc.h"
27
28 void
29 trns_chain_init (struct trns_chain *chain)
30 {
31   *chain = (struct trns_chain) TRNS_CHAIN_INIT;
32 }
33
34 bool
35 trns_chain_uninit (struct trns_chain *chain)
36 {
37   bool ok = true;
38   for (size_t i = 0; i < chain->n; i++)
39     {
40       struct transformation *xform = &chain->xforms[i];
41       if (xform->class->destroy)
42         ok = xform->class->destroy (xform->aux) && ok;
43     }
44   free (chain->xforms);
45   return ok;
46 }
47
48 bool
49 trns_chain_clear (struct trns_chain *chain)
50 {
51   bool ok = trns_chain_uninit (chain);
52   trns_chain_init (chain);
53   return ok;
54 }
55
56 void
57 trns_chain_append (struct trns_chain *chain, const struct transformation *t)
58 {
59   if (chain->n >= chain->allocated)
60     chain->xforms = x2nrealloc (chain->xforms, &chain->allocated,
61                                 sizeof *chain->xforms);
62
63   chain->xforms[chain->n++] = *t;
64 }
65
66 void
67 trns_chain_splice (struct trns_chain *dst, struct trns_chain *src)
68 {
69   if (dst->n + src->n >= dst->allocated)
70     {
71       dst->allocated = dst->n + src->n;
72       dst->xforms = xrealloc (dst->xforms,
73                               dst->allocated * sizeof *dst->xforms);
74     }
75
76   memcpy (&dst->xforms[dst->n], src->xforms, src->n * sizeof *src->xforms);
77   dst->n += src->n;
78   src->n = 0;
79 }
80
81 /* Executes the N transformations in XFORMS against case *C passing CASE_NR as
82    the case number.  The transformations may replace *C by a new case.  Returns
83    the result code that caused the transformations to terminate, or
84    TRNS_CONTINUE if the transformations finished due to "falling off the end"
85    of the set of transformations. */
86 enum trns_result
87 trns_chain_execute (const struct trns_chain *chain,
88                     casenumber case_nr, struct ccase **c)
89 {
90   for (size_t i = 0; i < chain->n; i++)
91     {
92       const struct transformation *trns = &chain->xforms[i];
93       int retval = trns->class->execute (trns->aux, c, case_nr);
94       if (retval != TRNS_CONTINUE)
95         return retval;
96     }
97
98   return TRNS_CONTINUE;
99 }