X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=inline;f=src%2Fdata%2Ftransformations.c;h=f1cfaf47c9688c5d51cd273d7d623b34292d3449;hb=df1d194af32e35739355981252785e768f21ebb0;hp=f77c24f8b95095a832b416a756ac26fd53a4a13e;hpb=5862de297bb487c81660beb3796d5c612eeb12b7;p=pspp
diff --git a/src/data/transformations.c b/src/data/transformations.c
index f77c24f8b9..f1cfaf47c9 100644
--- a/src/data/transformations.c
+++ b/src/data/transformations.c
@@ -1,209 +1,98 @@
-/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 1997-9, 2000, 2006, 2009, 2011, 2013 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+ along with this program. If not, see . */
#include
-#include
+#include "data/transformations.h"
#include
#include
-#include
-
-#include "xalloc.h"
-
-/* A single transformation. */
-struct transformation
- {
- /* Offset to add to EXECUTE's return value, if it returns a
- transformation index. Normally 0 but set to the starting
- index of a spliced chain after splicing. */
- int idx_ofs;
- trns_finalize_func *finalize; /* Finalize proc. */
- trns_proc_func *execute; /* Executes the transformation. */
- trns_free_func *free; /* Garbage collector proc. */
- void *aux; /* Auxiliary data. */
- };
-
-/* A chain of transformations. */
-struct trns_chain
- {
- struct transformation *trns; /* Array of transformations. */
- size_t trns_cnt; /* Number of transformations. */
- size_t trns_cap; /* Allocated capacity. */
- bool finalized; /* Finalize functions called? */
- };
-
-/* Allocates and returns a new transformation chain. */
-struct trns_chain *
-trns_chain_create (void)
-{
- struct trns_chain *chain = xmalloc (sizeof *chain);
- chain->trns = NULL;
- chain->trns_cnt = 0;
- chain->trns_cap = 0;
- chain->finalized = false;
- return chain;
-}
+#include "libpspp/str.h"
+
+#include "gl/xalloc.h"
-/* Finalizes all the transformations in CHAIN.
- A chain is only finalized once; afterward, calling this
- function is a no-op.
- Finalizers may add transformations to CHAIN, but after
- finalization the chain's contents are fixed, so that no more
- transformations may be added afterward. */
void
-trns_chain_finalize (struct trns_chain *chain)
+trns_chain_init (struct trns_chain *chain)
{
- if (!chain->finalized)
- {
- size_t i;
-
- for (i = 0; i < chain->trns_cnt; i++)
- {
- struct transformation *trns = &chain->trns[i];
- if (trns->finalize != NULL)
- trns->finalize (trns->aux);
- }
- chain->finalized = true;
- }
+ *chain = (struct trns_chain) TRNS_CHAIN_INIT;
}
-/* Destroys CHAIN, finalizing it in the process if it has not
- already been finalized. */
bool
-trns_chain_destroy (struct trns_chain *chain)
+trns_chain_uninit (struct trns_chain *chain)
{
bool ok = true;
-
- if (chain != NULL)
+ for (size_t i = 0; i < chain->n; i++)
{
- size_t i;
-
- /* Needed to ensure that the control stack gets cleared. */
- trns_chain_finalize (chain);
-
- for (i = 0; i < chain->trns_cnt; i++)
- {
- struct transformation *trns = &chain->trns[i];
- if (trns->free != NULL)
- ok = trns->free (trns->aux) && ok;
- }
- free (chain->trns);
- free (chain);
+ struct transformation *xform = &chain->xforms[i];
+ if (xform->class->destroy)
+ ok = xform->class->destroy (xform->aux) && ok;
}
-
+ free (chain->xforms);
return ok;
}
-/* Returns true if CHAIN contains any transformations,
- false otherwise. */
bool
-trns_chain_is_empty (const struct trns_chain *chain)
+trns_chain_clear (struct trns_chain *chain)
{
- return chain->trns_cnt == 0;
+ bool ok = trns_chain_uninit (chain);
+ trns_chain_init (chain);
+ return ok;
}
-/* Adds a transformation to CHAIN with finalize function
- FINALIZE, execute function EXECUTE, free function FREE, and
- auxiliary data AUX. */
void
-trns_chain_append (struct trns_chain *chain, trns_finalize_func *finalize,
- trns_proc_func *execute, trns_free_func *free,
- void *aux)
+trns_chain_append (struct trns_chain *chain, const struct transformation *t)
{
- struct transformation *trns;
-
- assert (!chain->finalized);
-
- if (chain->trns_cnt == chain->trns_cap)
- chain->trns = x2nrealloc (chain->trns, &chain->trns_cap,
- sizeof *chain->trns);
+ if (chain->n >= chain->allocated)
+ chain->xforms = x2nrealloc (chain->xforms, &chain->allocated,
+ sizeof *chain->xforms);
- trns = &chain->trns[chain->trns_cnt++];
- trns->idx_ofs = 0;
- trns->finalize = finalize;
- trns->execute = execute;
- trns->free = free;
- trns->aux = aux;
+ chain->xforms[chain->n++] = *t;
}
-/* Appends the transformations in SRC to those in DST,
- and destroys SRC.
- Both DST and SRC must already be finalized. */
void
-trns_chain_splice (struct trns_chain *dst, struct trns_chain *src)
+trns_chain_splice (struct trns_chain *dst, struct trns_chain *src)
{
- size_t i;
-
- assert (dst->finalized);
- assert (src->finalized);
-
- if (dst->trns_cnt + src->trns_cnt > dst->trns_cap)
- {
- dst->trns_cap = dst->trns_cnt + src->trns_cnt;
- dst->trns = xnrealloc (dst->trns, dst->trns_cap, sizeof *dst->trns);
- }
-
- for (i = 0; i < src->trns_cnt; i++)
+ if (dst->n + src->n >= dst->allocated)
{
- struct transformation *d = &dst->trns[i + dst->trns_cnt];
- const struct transformation *s = &src->trns[i];
- *d = *s;
- d->idx_ofs += src->trns_cnt;
+ dst->allocated = dst->n + src->n;
+ dst->xforms = xrealloc (dst->xforms,
+ dst->allocated * sizeof *dst->xforms);
}
- dst->trns_cnt += src->trns_cnt;
- trns_chain_destroy (src);
+ memcpy (&dst->xforms[dst->n], src->xforms, src->n * sizeof *src->xforms);
+ dst->n += src->n;
+ src->n = 0;
}
-/* Returns the index that a transformation execution function may
- return to "jump" to the next transformation to be added. */
-size_t
-trns_chain_next (struct trns_chain *chain)
-{
- return chain->trns_cnt;
-}
-
-/* Executes the given CHAIN of transformations on C,
- passing *CASE_NR as the case number.
- If a transformation modifies *CASE_NR, it will affect the case
- number passed to following transformations.
- Returns the result code that caused the transformations to
- terminate, or TRNS_CONTINUE if the transformations finished
- due to "falling off the end" of the set of transformations. */
+/* Executes the N transformations in XFORMS against case *C passing CASE_NR as
+ the case number. The transformations may replace *C by a new case. Returns
+ the result code that caused the transformations to terminate, or
+ TRNS_CONTINUE if the transformations finished due to "falling off the end"
+ of the set of transformations. */
enum trns_result
-trns_chain_execute (struct trns_chain *chain, enum trns_result start,
- struct ccase *c, const size_t *case_nr)
+trns_chain_execute (const struct trns_chain *chain,
+ casenumber case_nr, struct ccase **c)
{
- size_t i;
-
- assert (chain->finalized);
- for (i = start < 0 ? 0 : start; i < chain->trns_cnt; )
+ for (size_t i = 0; i < chain->n; i++)
{
- struct transformation *trns = &chain->trns[i];
- int retval = trns->execute (trns->aux, c, *case_nr);
- if (retval == TRNS_CONTINUE)
- i++;
- else if (retval >= 0)
- i = retval + trns->idx_ofs;
- else
- return retval == TRNS_END_CASE ? i + 1 : retval;
+ const struct transformation *trns = &chain->xforms[i];
+ int retval = trns->class->execute (trns->aux, c, case_nr);
+ if (retval != TRNS_CONTINUE)
+ return retval;
}
return TRNS_CONTINUE;