/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 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
corresponding source index. */
};
-static void translate_case (struct ccase *, struct ccase *, void *map_);
+static struct ccase *translate_case (struct ccase *, void *map_);
static bool destroy_case_map (void *map_);
/* Creates and returns an empty map. */
}
}
-/* Maps from SRC to DST, applying case map MAP. */
-void
-case_map_execute (const struct case_map *map,
- const struct ccase *src, struct ccase *dst)
-{
- size_t dst_idx;
+/* If MAP is nonnull, returns a new case that is the result of
+ applying case map MAP to SRC, and unrefs SRC.
- case_create (dst, map->value_cnt);
- for (dst_idx = 0; dst_idx < map->value_cnt; dst_idx++)
+ If MAP is null, returns SRC unchanged. */
+struct ccase *
+case_map_execute (const struct case_map *map, struct ccase *src)
+{
+ if (map != NULL)
{
- int src_idx = map->map[dst_idx];
- if (src_idx != -1)
- *case_data_rw_idx (dst, dst_idx) = *case_data_idx (src, src_idx);
+ struct ccase *dst;
+ size_t dst_idx;
+
+ dst = case_create (map->value_cnt);
+ for (dst_idx = 0; dst_idx < map->value_cnt; dst_idx++)
+ {
+ int src_idx = map->map[dst_idx];
+ if (src_idx != -1)
+ *case_data_rw_idx (dst, dst_idx) = *case_data_idx (src, src_idx);
+ }
+ case_unref (src);
+ return dst;
}
+ else
+ return src;
}
/* Returns the number of `union value's in cases created by
}
/* Casereader/casewriter translation callback. */
-static void
-translate_case (struct ccase *input, struct ccase *output, void *map_)
+static struct ccase *
+translate_case (struct ccase *input, void *map_)
{
struct case_map *map = map_;
- case_map_execute (map, input, output);
- case_destroy (input);
+ return case_map_execute (map, input);
}
/* Casereader/casewriter destruction callback. */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
struct case_map *case_map_create (void);
void case_map_destroy (struct case_map *);
-void case_map_execute (const struct case_map *,
- const struct ccase *, struct ccase *);
+struct ccase *case_map_execute (const struct case_map *, struct ccase *);
size_t case_map_get_value_cnt (const struct case_map *);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 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
struct case_matcher_input
{
struct subcase by_vars;
- const struct ccase *data;
+ struct ccase **data;
bool *is_minimal;
};
/* Adds a new input file to case matcher CM.
case_matcher_match() will compare the variables specified in
- BY in case DATA and set *IS_MINIMAL appropriately.
+ BY in case *DATA and set *IS_MINIMAL appropriately.
+ (The caller may change the case that *DATA points to from one
+ call to the next.)
All of the BY subcases provided to this function for a given
CM must be conformable (see subcase_conformable()). */
void
case_matcher_add_input (struct case_matcher *cm, const struct subcase *by,
- const struct ccase *data, bool *is_minimal)
+ struct ccase **data, bool *is_minimal)
{
struct case_matcher_input *input;
static int
compare_BY_3way (struct case_matcher_input *a, struct case_matcher_input *b)
{
- return subcase_compare_3way (&a->by_vars, a->data, &b->by_vars, b->data);
+ return subcase_compare_3way (&a->by_vars, *a->data, &b->by_vars, *b->data);
}
/* Compares the values of the BY variables in all of the nonnull
min = NULL;
for (file = cm->inputs; file < &cm->inputs[cm->n_inputs]; file++)
- if (!case_is_null (file->data))
+ if (*file->data != NULL)
{
int cmp = min != NULL ? compare_BY_3way (min, file) : 1;
if (cmp < 0)
{
for (file = cm->inputs; file < min; file++)
*file->is_minimal = false;
- subcase_extract (&min->by_vars, min->data, cm->by_values);
+ subcase_extract (&min->by_vars, *min->data, cm->by_values);
*by = cm->by_values;
return true;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 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
struct case_matcher *case_matcher_create (void);
void case_matcher_add_input (struct case_matcher *, const struct subcase *,
- const struct ccase *, bool *is_minimal);
+ struct ccase **, bool *is_minimal);
void case_matcher_destroy (struct case_matcher *);
bool case_matcher_match (struct case_matcher *, union value **by);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
&& do_read (ctf, sizeof *values * value_cnt, values));
}
-/* Reads the case numbered CASE_IDX from CTF into C.
- Returns true if successful, false if CTF is tainted or an I/O
- error occurs during the operation.
+/* Reads the case numbered CASE_IDX from CTF.
+ Returns the case if successful or a null pointer if CTF is
+ tainted or an I/O error occurs during the operation.
The results of this function are undefined if the case read
from CTF had not previously been written. */
-bool
-case_tmpfile_get_case (const struct case_tmpfile *ctf, casenumber case_idx,
- struct ccase *c)
+struct ccase *
+case_tmpfile_get_case (const struct case_tmpfile *ctf, casenumber case_idx)
{
- case_create (c, ctf->value_cnt);
+ struct ccase *c = case_create (ctf->value_cnt);
if (case_tmpfile_get_values (ctf, case_idx, 0,
case_data_all_rw (c), ctf->value_cnt))
- return true;
+ return c;
else
{
- case_destroy (c);
- case_nullify (c);
- return false;
+ case_unref (c);
+ return NULL;
}
}
{
bool ok = case_tmpfile_put_values (ctf, case_idx, 0,
case_data_all (c), ctf->value_cnt);
- case_destroy (c);
+ case_unref (c);
return ok;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
void case_tmpfile_force_error (struct case_tmpfile *);
const struct taint *case_tmpfile_get_taint (const struct case_tmpfile *);
-bool case_tmpfile_get_values (const struct case_tmpfile *,
+ bool case_tmpfile_get_values (const struct case_tmpfile *,
casenumber, size_t start_value,
union value[], size_t value_cnt);
-bool case_tmpfile_get_case (const struct case_tmpfile *,
- casenumber, struct ccase *);
+struct ccase *case_tmpfile_get_case (const struct case_tmpfile *, casenumber);
bool case_tmpfile_put_values (struct case_tmpfile *,
casenumber, size_t start_value,
/* PSPP - a program for statistical analysis.
- Copyright (C) 2004, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2007, 2009 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
#include <assert.h>
#include <limits.h>
+#include <stddef.h>
#include <stdlib.h>
#include <data/value.h>
#include "minmax.h"
#include "xalloc.h"
-/* Reference-counted case implementation. */
-struct case_data
- {
- size_t value_cnt; /* Number of values. */
- unsigned ref_cnt; /* Reference count. */
- union value values[1]; /* Values. */
- };
-
-/* Ensures that C does not share data with any other case. */
-static void
-case_unshare (struct ccase *c)
-{
- if (c->case_data->ref_cnt > 1)
- {
- struct case_data *cd = c->case_data;
- cd->ref_cnt--;
- case_create (c, cd->value_cnt);
- memcpy (c->case_data->values, cd->values,
- sizeof *cd->values * cd->value_cnt);
- }
-}
-
-/* Returns the number of bytes needed by a case with VALUE_CNT
+/* Returns the number of bytes needed by a case with N_VALUES
values. */
static size_t
-case_size (size_t value_cnt)
+case_size (size_t n_values)
{
- return (offsetof (struct case_data, values)
- + value_cnt * sizeof (union value));
+ return offsetof (struct ccase, values) + n_values * sizeof (union value);
}
-/* Initializes C as a null case. */
-void
-case_nullify (struct ccase *c)
+/* Returns true if case C contains COUNT cases starting at index
+ OFS, false if any of those values are out of range for case
+ C. */
+static inline bool UNUSED
+range_is_valid (const struct ccase *c, size_t ofs, size_t count)
{
- c->case_data = NULL;
+ return (count <= c->n_values
+ && ofs <= c->n_values
+ && ofs + count <= c->n_values);
}
-/* Returns true iff C is a null case. */
-bool
-case_is_null (const struct ccase *c)
-{
- return c->case_data == NULL;
-}
-
-/* Initializes C as a new case that can store VALUE_CNT values.
+/* Creates and returns a new case that can store N_VALUES values.
The values have indeterminate contents until explicitly
written. */
-void
-case_create (struct ccase *c, size_t value_cnt)
+struct ccase *
+case_create (size_t n_values)
{
- if (!case_try_create (c, value_cnt))
+ struct ccase *c = case_try_create (n_values);
+ if (c == NULL)
xalloc_die ();
+ return c;
}
-/* Initializes CLONE as a copy of ORIG. */
-void
-case_clone (struct ccase *clone, const struct ccase *orig)
+/* Like case_create, but returns a null pointer if not enough
+ memory is available. */
+struct ccase *
+case_try_create (size_t n_values)
{
- assert (orig->case_data->ref_cnt > 0);
-
- if (clone != orig)
- *clone = *orig;
- orig->case_data->ref_cnt++;
-#ifdef DEBUGGING
- case_unshare (clone);
-#endif
-}
-
-/* Replaces DST by SRC and nullifies SRC.
- DST and SRC must be initialized cases at entry. */
-void
-case_move (struct ccase *dst, struct ccase *src)
-{
- assert (src->case_data->ref_cnt > 0);
-
- if (dst != src)
+ struct ccase *c = malloc (case_size (n_values));
+ if (c)
{
- *dst = *src;
- case_nullify (src);
+ c->n_values = n_values;
+ c->ref_cnt = 1;
}
+ return c;
}
-/* Destroys case C. */
-void
-case_destroy (struct ccase *c)
+/* Resizes case C, which must not be shared, to N_VALUES union
+ values. If N_VALUES is greater than the current size of case
+ C, then the newly added values have indeterminate content that
+ the caller is responsible for initializing. Returns the new
+ case. */
+struct ccase *
+case_resize (struct ccase *c, size_t n_values)
{
- struct case_data *cd;
-
- cd = c->case_data;
- if (cd != NULL && --cd->ref_cnt == 0)
+ assert (!case_is_shared (c));
+ if (n_values != c->n_values)
{
- memset (cd->values, 0xcc, sizeof *cd->values * cd->value_cnt);
- cd->value_cnt = 0xdeadbeef;
- free (cd);
+ c->n_values = n_values;
+ return xrealloc (c, case_size (n_values));
}
+ else
+ return c;
}
-/* Returns the number of union values in C. */
-size_t
-case_get_value_cnt (const struct ccase *c)
-{
- return c->case_data->value_cnt;
-}
+/* case_unshare_and_resize(C, N) is equivalent to
+ case_resize(case_unshare(C), N), but it is faster if case C is
+ shared.
-/* Resizes case C to NEW_CNT union values. */
-void
-case_resize (struct ccase *c, size_t new_cnt)
+ Returns the new case.*/
+struct ccase *
+case_unshare_and_resize (struct ccase *c, size_t n_values)
{
- size_t old_cnt = case_get_value_cnt (c);
- if (old_cnt != new_cnt)
+ if (!case_is_shared (c))
+ return case_resize (c, n_values);
+ else
{
- struct ccase new;
-
- case_create (&new, new_cnt);
- case_copy (&new, 0, c, 0, MIN (old_cnt, new_cnt));
- case_swap (&new, c);
- case_destroy (&new);
+ struct ccase *new = case_create (n_values);
+ case_copy (new, 0, c, 0, MIN (n_values, c->n_values));
+ c->ref_cnt--;
+ return new;
}
}
-/* Swaps cases A and B. */
-void
-case_swap (struct ccase *a, struct ccase *b)
-{
- struct case_data *t = a->case_data;
- a->case_data = b->case_data;
- b->case_data = t;
-}
+/* Copies N_VALUES values from SRC (starting at SRC_IDX) to DST
+ (starting at DST_IDX).
-/* Attempts to create C as a new case that holds VALUE_CNT
- values. Returns true if successful, false if memory
- allocation failed. */
-bool
-case_try_create (struct ccase *c, size_t value_cnt)
-{
- c->case_data = malloc (case_size (value_cnt));
- if (c->case_data != NULL)
- {
- c->case_data->value_cnt = value_cnt;
- c->case_data->ref_cnt = 1;
- return true;
- }
-
- return false;
-}
-
-/* Tries to initialize CLONE as a copy of ORIG.
- Returns true if successful, false if memory allocation
- failed. */
-bool
-case_try_clone (struct ccase *clone, const struct ccase *orig)
-{
- case_clone (clone, orig);
- return true;
-}
-
-/* Copies VALUE_CNT values from SRC (starting at SRC_IDX) to DST
- (starting at DST_IDX). */
+ DST must not be shared. */
void
case_copy (struct ccase *dst, size_t dst_idx,
const struct ccase *src, size_t src_idx,
- size_t value_cnt)
+ size_t n_values)
{
- assert (dst->case_data->ref_cnt > 0);
- assert (dst_idx + value_cnt <= dst->case_data->value_cnt);
+ assert (!case_is_shared (dst));
+ assert (range_is_valid (dst, dst_idx, n_values));
+ assert (range_is_valid (src, dst_idx, n_values));
- assert (src->case_data->ref_cnt > 0);
- assert (src_idx + value_cnt <= src->case_data->value_cnt);
-
- if (dst->case_data != src->case_data || dst_idx != src_idx)
- {
- case_unshare (dst);
- memmove (dst->case_data->values + dst_idx,
- src->case_data->values + src_idx,
- sizeof *dst->case_data->values * value_cnt);
- }
+ if (dst != src || dst_idx != src_idx)
+ memmove (dst->values + dst_idx, src->values + src_idx,
+ sizeof *dst->values * n_values);
}
-/* Copies VALUE_CNT values out of case C to VALUES, starting at
+/* Copies N_VALUES values out of case C to VALUES, starting at
the given START_IDX. */
void
case_copy_out (const struct ccase *c,
- size_t start_idx, union value *values, size_t value_cnt)
+ size_t start_idx, union value *values, size_t n_values)
{
- assert (c->case_data->ref_cnt > 0);
- assert (value_cnt <= c->case_data->value_cnt);
- assert (start_idx + value_cnt <= c->case_data->value_cnt);
-
- memcpy (values, c->case_data->values + start_idx,
- value_cnt * sizeof *values);
+ assert (range_is_valid (c, start_idx, n_values));
+ memcpy (values, c->values + start_idx, n_values * sizeof *values);
}
-/* Copies VALUE_CNT values from VALUES into case C, staring at
- the given START_IDX. */
+/* Copies N_VALUES values from VALUES into case C, starting at
+ the given START_IDX.
+
+ C must not be shared. */
void
case_copy_in (struct ccase *c,
- size_t start_idx, const union value *values, size_t value_cnt)
+ size_t start_idx, const union value *values, size_t n_values)
{
- assert (c->case_data->ref_cnt > 0);
- assert (value_cnt <= c->case_data->value_cnt);
- assert (start_idx + value_cnt <= c->case_data->value_cnt);
-
- case_unshare (c);
- memcpy (c->case_data->values + start_idx, values,
- value_cnt * sizeof *values);
+ assert (!case_is_shared (c));
+ assert (range_is_valid (c, start_idx, n_values));
+ memcpy (c->values + start_idx, values, n_values * sizeof *values);
}
/* Returns a pointer to the `union value' used for the
return case_data_idx (c, var_get_case_index (v));
}
-/* Returns the numeric value of the `union value' in C for
- variable V.
- Case C must be drawn from V's dictionary. */
-double
-case_num (const struct ccase *c, const struct variable *v)
+/* Returns a pointer to the `union value' used for the element of
+ C numbered IDX. The caller must not modify the returned
+ data. */
+const union value *
+case_data_idx (const struct ccase *c, size_t idx)
{
- return case_num_idx (c, var_get_case_index (v));
+ assert (idx < c->n_values);
+ return &c->values[idx];
}
-/* Returns the string value of the `union value' in C for
- variable V.
- Case C must be drawn from V's dictionary.
- (Note that the value is not null-terminated.)
- The caller must not modify the return value. */
-const char *
-case_str (const struct ccase *c, const struct variable *v)
-{
- return case_str_idx (c, var_get_case_index (v));
-}
+/* Returns a pointer to the `union value' used for the element of
+ C for variable V. Case C must be drawn from V's dictionary.
+ The caller is allowed to modify the returned data.
-/* Returns a pointer to the `union value' used for the
- element of C for variable V.
- Case C must be drawn from V's dictionary.
- The caller is allowed to modify the returned data. */
+ Case C must not be shared. */
union value *
case_data_rw (struct ccase *c, const struct variable *v)
{
/* Returns a pointer to the `union value' used for the
element of C numbered IDX.
- The caller must not modify the returned data. */
-const union value *
-case_data_idx (const struct ccase *c, size_t idx)
+ The caller is allowed to modify the returned data.
+
+ Case C must not be shared. */
+union value *
+case_data_rw_idx (struct ccase *c, size_t idx)
{
- assert (c->case_data->ref_cnt > 0);
- assert (idx < c->case_data->value_cnt);
+ assert (!case_is_shared (c));
+ assert (idx < c->n_values);
+ return &c->values[idx];
+}
- return &c->case_data->values[idx];
+/* Returns the numeric value of the `union value' in C for
+ variable V.
+ Case C must be drawn from V's dictionary. */
+double
+case_num (const struct ccase *c, const struct variable *v)
+{
+ return case_num_idx (c, var_get_case_index (v));
}
/* Returns the numeric value of the `union value' in C numbered
double
case_num_idx (const struct ccase *c, size_t idx)
{
- assert (c->case_data->ref_cnt > 0);
- assert (idx < c->case_data->value_cnt);
-
- return c->case_data->values[idx].f;
+ assert (idx < c->n_values);
+ return c->values[idx].f;
}
-/* Returns the string value of the `union value' in C numbered
- IDX.
- (Note that the value is not null-terminated.)
- The caller must not modify the return value. */
+/* Returns the string value of the `union value' in C for
+ variable V. Case C must be drawn from V's dictionary. The
+ caller must not modify the return value.
+
+ Like all "union value"s, the return value is not
+ null-terminated. */
const char *
-case_str_idx (const struct ccase *c, size_t idx)
+case_str (const struct ccase *c, const struct variable *v)
{
- assert (c->case_data->ref_cnt > 0);
- assert (idx < c->case_data->value_cnt);
-
- return c->case_data->values[idx].s;
+ return case_str_idx (c, var_get_case_index (v));
}
-/* Returns a pointer to the `union value' used for the
- element of C numbered IDX.
- The caller is allowed to modify the returned data. */
-union value *
-case_data_rw_idx (struct ccase *c, size_t idx)
-{
- assert (c->case_data->ref_cnt > 0);
- assert (idx < c->case_data->value_cnt);
+/* Returns the string value of the `union value' in C numbered
+ IDX. The caller must not modify the return value.
- case_unshare (c);
- return &c->case_data->values[idx];
+ Like all "union value"s, the return value is not
+ null-terminated. */
+const char *
+case_str_idx (const struct ccase *c, size_t idx)
+{
+ assert (idx < c->n_values);
+ return c->values[idx].s;
}
-/* Compares the values of the VAR_CNT variables in VP
+/* Compares the values of the N_VARS variables in VP
in cases A and B and returns a strcmp()-type result. */
int
case_compare (const struct ccase *a, const struct ccase *b,
- const struct variable *const *vp, size_t var_cnt)
+ const struct variable *const *vp, size_t n_vars)
{
- return case_compare_2dict (a, b, vp, vp, var_cnt);
+ return case_compare_2dict (a, b, vp, vp, n_vars);
}
-/* Compares the values of the VAR_CNT variables in VAP in case CA
- to the values of the VAR_CNT variables in VBP in CB
+/* Compares the values of the N_VARS variables in VAP in case CA
+ to the values of the N_VARS variables in VBP in CB
and returns a strcmp()-type result. */
int
case_compare_2dict (const struct ccase *ca, const struct ccase *cb,
const struct variable *const *vap,
- const struct variable *const *vbp,
- size_t var_cnt)
+ const struct variable *const *vbp,
+ size_t n_vars)
{
- for (; var_cnt-- > 0; vap++, vbp++)
+ for (; n_vars-- > 0; vap++, vbp++)
{
const struct variable *va = *vap;
const struct variable *vb = *vbp;
/* Returns a pointer to the array of `union value's used for C.
The caller must *not* modify the returned data.
- NOTE: This function breaks the case abstraction. It should
- *not* be used often. Prefer the other case functions. */
+ This function breaks the case abstraction. It should *not* be
+ commonly used. Prefer the other case functions. */
const union value *
case_data_all (const struct ccase *c)
{
- assert (c->case_data->ref_cnt > 0);
-
- return c->case_data->values;
+ return c->values;
}
/* Returns a pointer to the array of `union value's used for C.
The caller is allowed to modify the returned data.
- NOTE: This function breaks the case abstraction. It should
- *not* be used often. Prefer the other case functions. */
+ Case C must not be shared.
+
+ This function breaks the case abstraction. It should *not* be
+ commonly used. Prefer the other case functions. */
union value *
case_data_all_rw (struct ccase *c)
{
- assert (c->case_data->ref_cnt > 0);
+ assert (!case_is_shared (c));
+ return c->values;
+}
- case_unshare (c);
- return c->case_data->values;
+/* Internal helper function for case_unshare. */
+struct ccase *
+case_unshare__ (struct ccase *old)
+{
+ struct ccase *new = case_create (old->n_values);
+ memcpy (new->values, old->values, old->n_values * sizeof old->values[0]);
+ --old->ref_cnt;
+ return new;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2004, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2007, 2009 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
#include <limits.h>
#include <stddef.h>
#include <stdbool.h>
+#include <stdlib.h>
+#include <libpspp/compiler.h>
#include "value.h"
struct variable;
#define CASENUMBER_MAX LONG_MAX
typedef long int casenumber;
-/* Opaque structure that represents a case. Use accessor
- functions instead of accessing any members directly. Use
- case_move() or case_clone() instead of copying. */
+/* Reference-counted case implementation.
+
+ A newly created case has a single owner (the code that created
+ it), represented by an initial reference count of 1. Other
+ code that receives the case may keep a virtual copy of it by
+ calling case_ref, which increments the case's reference count.
+ When this is done, the case becomes shared between its
+ original owner and each piece of code that incremented the
+ reference count.
+
+ A shared case (one whose reference count is greater than 1)
+ must not be modified, because this would make the case change
+ in the view of every reference count holder, not just the one
+ that intended to change the case. Because the purpose of
+ keeping the reference count is to make a virtual copy of the
+ case, this is undesirable behavior. The case_unshare function
+ provides a solution, by making a new, unshared copy of a
+ shared case. */
struct ccase
{
- struct case_data *case_data; /* Actual data. */
+ size_t n_values; /* Number of values. */
+ size_t ref_cnt; /* Reference count. */
+ union value values[1]; /* Values. */
};
-void case_nullify (struct ccase *);
-bool case_is_null (const struct ccase *);
+struct ccase *case_create (size_t n_values) MALLOC_LIKE;
+struct ccase *case_try_create (size_t n_values) MALLOC_LIKE;
-void case_create (struct ccase *, size_t value_cnt);
-void case_clone (struct ccase *, const struct ccase *);
-void case_move (struct ccase *, struct ccase *);
-void case_destroy (struct ccase *);
+static inline struct ccase *case_unshare (struct ccase *) WARN_UNUSED_RESULT;
+static inline struct ccase *case_ref (const struct ccase *);
+static inline void case_unref (struct ccase *);
+static inline bool case_is_shared (const struct ccase *);
-size_t case_get_value_cnt (const struct ccase *);
+static inline size_t case_get_value_cnt (const struct ccase *);
-void case_resize (struct ccase *, size_t new_cnt);
-void case_swap (struct ccase *, struct ccase *);
-
-bool case_try_create (struct ccase *, size_t value_cnt);
-bool case_try_clone (struct ccase *, const struct ccase *);
+struct ccase *case_resize (struct ccase *, size_t new_cnt) WARN_UNUSED_RESULT;
+struct ccase *case_unshare_and_resize (struct ccase *, size_t new_cnt)
+ WARN_UNUSED_RESULT;
void case_copy (struct ccase *dst, size_t dst_idx,
const struct ccase *src, size_t src_idx,
size_t cnt);
void case_copy_out (const struct ccase *,
- size_t start_idx, union value *, size_t value_cnt);
+ size_t start_idx, union value *, size_t n_values);
void case_copy_in (struct ccase *,
- size_t start_idx, const union value *, size_t value_cnt);
+ size_t start_idx, const union value *, size_t n_values);
const union value *case_data (const struct ccase *, const struct variable *);
-double case_num (const struct ccase *, const struct variable *);
-const char *case_str (const struct ccase *, const struct variable *);
+const union value *case_data_idx (const struct ccase *, size_t idx);
union value *case_data_rw (struct ccase *, const struct variable *);
+union value *case_data_rw_idx (struct ccase *, size_t idx);
-const union value *case_data_idx (const struct ccase *, size_t idx);
+double case_num (const struct ccase *, const struct variable *);
double case_num_idx (const struct ccase *, size_t idx);
+
+const char *case_str (const struct ccase *, const struct variable *);
const char *case_str_idx (const struct ccase *, size_t idx);
-union value *case_data_rw_idx (struct ccase *, size_t idx);
int case_compare (const struct ccase *, const struct ccase *,
- const struct variable *const *, size_t var_cnt);
+ const struct variable *const *, size_t n_vars);
int case_compare_2dict (const struct ccase *, const struct ccase *,
const struct variable *const *,
const struct variable *const *,
- size_t var_cnt);
+ size_t n_vars);
const union value *case_data_all (const struct ccase *);
union value *case_data_all_rw (struct ccase *);
+\f
+struct ccase *case_unshare__ (struct ccase *);
+
+/* If C is a shared case, that is, if it has a reference count
+ greater than 1, makes a new unshared copy and returns it,
+ decrementing C's reference count. If C is not shared (its
+ reference count is 1), returns C.
+
+ This function should be used before attempting to modify any
+ of the data in a case that might be shared, e.g.:
+ c = case_unshare (c); // Make sure that C is not shared.
+ case_data_rw (c, myvar)->f = 1; // Modify data in C.
+*/
+static inline struct ccase *
+case_unshare (struct ccase *c)
+{
+ if (case_is_shared (c))
+ c = case_unshare__ (c);
+ return c;
+}
+
+/* Increments case C's reference count and returns C. Afterward,
+ case C is shared among its reference count holders. */
+static inline struct ccase *
+case_ref (const struct ccase *c_)
+{
+ struct ccase *c = (struct ccase *) c_;
+ c->ref_cnt++;
+ return c;
+}
+
+/* Decrements case C's reference count. Frees C if its
+ reference count drops to 0.
+
+ If C is a null pointer, this function has no effect. */
+static inline void
+case_unref (struct ccase *c)
+{
+ if (c != NULL && !--c->ref_cnt)
+ free (c);
+}
+
+/* Returns true if case C is shared. A case that is shared
+ cannot be modified directly. Instead, an unshared copy must
+ first be made with case_unshare(). */
+static inline bool
+case_is_shared (const struct ccase *c)
+{
+ return c->ref_cnt > 1;
+}
+
+/* Returns the number of union values in C. */
+static inline size_t
+case_get_value_cnt (const struct ccase *c)
+{
+ return c->n_values;
+}
#endif /* data/case.h */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
if (grouper->same_group != NULL)
{
struct casewriter *writer;
- struct ccase group_case, tmp;
+ struct ccase *group_case, *tmp;
- if (!casereader_read (grouper->reader, &group_case))
+ group_case = casereader_read (grouper->reader);
+ if (group_case == NULL)
{
*reader = NULL;
return false;
}
writer = autopaging_writer_create (casereader_get_value_cnt (grouper->reader));
- case_clone (&tmp, &group_case);
- casewriter_write (writer, &tmp);
+ case_ref (group_case);
+ casewriter_write (writer, group_case);
- while (casereader_peek (grouper->reader, 0, &tmp)
- && grouper->same_group (&group_case, &tmp, grouper->aux))
+ while ((tmp = casereader_peek (grouper->reader, 0)) != NULL
+ && grouper->same_group (group_case, tmp, grouper->aux))
{
- struct ccase discard;
- casereader_read (grouper->reader, &discard);
- case_destroy (&discard);
- casewriter_write (writer, &tmp);
+ case_unref (casereader_read (grouper->reader));
+ casewriter_write (writer, tmp);
}
- case_destroy (&tmp);
- case_destroy (&group_case);
+ case_unref (group_case);
*reader = casewriter_make_reader (writer);
return true;
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
init_list_mark (&ci->left_values, &ci->preinited_values, LEAVE_LEFT, d);
}
-/* Initializes variables in C as described by CI. */
+/* Initializes variables in *C as described by CI.
+ C must not be shared. */
void
caseinit_init_vars (const struct caseinit *ci, struct ccase *c)
{
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
}
/* Internal read function for filtering casereader. */
-static bool
-casereader_filter_read (struct casereader *reader UNUSED, void *filter_,
- struct ccase *c)
+static struct ccase *
+casereader_filter_read (struct casereader *reader UNUSED, void *filter_)
{
struct casereader_filter *filter = filter_;
for (;;)
{
- if (!casereader_read (filter->subreader, c))
- return false;
+ struct ccase *c = casereader_read (filter->subreader);
+ if (c == NULL)
+ return NULL;
else if (filter->include (c, filter->aux))
- return true;
+ return c;
else if (filter->exclude != NULL)
casewriter_write (filter->exclude, c);
else
- case_destroy (c);
+ case_unref (c);
}
}
casewriter, if there is one. */
if (filter->exclude != NULL)
{
- struct ccase c;
- while (casereader_read (filter->subreader, &c))
- if (filter->include (&c, filter->aux))
- case_destroy (&c);
+ struct ccase *c;
+ while ((c = casereader_read (filter->subreader)) != NULL)
+ if (filter->include (c, filter->aux))
+ case_unref (c);
else
- casewriter_write (filter->exclude, &c);
+ casewriter_write (filter->exclude, c);
}
casereader_destroy (filter->subreader);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
{
/* Mandatory.
- Reads the next case from READER into case C, which the
- casereader must create and which the client is responsible
- for destroying. If successful, returns true and advances
- READER to the next case, so that the next call to this
- function will read the next case. The case just read will
- never be read again by a call to this function for READER.
+ Reads the next case from READER. If successful, returns
+ the case and advances READER, so that the next call to
+ this function will read the following case. The case just
+ read will never be read again by a call to this function
+ for READER.
- At end of file or upon an I/O error, returns false. After
- false is returned once, this function will not be called
- again for the given READER.
+ If a case is successfully returned, the client is
+ responsible for calling case_unref upon it when it is no
+ longer needed.
+
+ At end of file or upon an I/O error, returns a null
+ pointer. After null is returned once, this function will
+ not be called again for the given READER.
If an I/O error occurs, this function should call
casereader_force_error on READER. */
- bool (*read) (struct casereader *reader, void *aux, struct ccase *c);
+ struct ccase *(*read) (struct casereader *reader, void *aux);
/* Mandatory.
(But it might be easier to use the random-access
casereader wrapper instead.)
- Reads the case at 0-based offset IDX from the beginning of
- READER into case C, which the casereader must create and
- which the client is responsible for destroying.
+ Reads and returns the case at 0-based offset IDX from the
+ beginning of READER. If a case is successfully returned,
+ the client is responsible for calling case_unref upon it
+ when it is no longer needed.
- At end of file or upon an I/O error, returns false. If
- this function returns false, then it will never be called
- again for an equal or greater value of IDX, and the "read"
- member function will never be called to advance as far as
- IDX cases further into the casereader. That is, returning
- false indicates that the casereader has fewer than IDX
- cases left.
+ At end of file or upon an I/O error, returns a null
+ pointer. If this function returns null, then it will
+ never be called again for an equal or greater value of
+ IDX, and the "read" member function will never be called
+ to advance as far as IDX cases further into the
+ casereader. That is, returning null indicates that the
+ casereader has fewer than IDX cases left.
If an I/O error occurs, this function should call
casereader_force_error on READER. */
- bool (*peek) (struct casereader *reader, void *aux, casenumber idx,
- struct ccase *c);
+ struct ccase *(*peek) (struct casereader *reader, void *aux,
+ casenumber idx);
};
struct casereader *
/* Mandatory.
Reads the case at 0-based offset IDX from the beginning of
- READER into case C, which the casereader must create and
- which the client is responsible for destroying.
-
- At end of file or upon an I/O error, returns false. If
- this function returns false, then it will never be called
- again for an equal or greater value of IDX, and the "read"
- member function will never be called to advance as far as
- IDX cases further into the casereader. That is, returning
- false indicates that the casereader has fewer than IDX
- cases.
+ READER. If a case is successfully returned, the client is
+ responsible for calling case_unref upon it when it is no
+ longer needed.
+
+ At end of file or upon an I/O error, returns a null
+ pointer. If this function returns null, then it will
+ never be called again for an equal or greater value of
+ IDX, and the "read" member function will never be called
+ to advance as far as IDX cases further into the
+ casereader. That is, returning null indicates that the
+ casereader has fewer than IDX cases.
If an I/O error occurs, this function should call
casereader_force_error on READER. */
- bool (*read) (struct casereader *reader, void *aux, casenumber idx,
- struct ccase *c);
+ struct ccase *(*read) (struct casereader *reader, void *aux,
+ casenumber idx);
/* Mandatory.
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
{
struct casereader *subreader; /* Source of input cases. */
- void (*translate) (struct ccase *input, struct ccase *output, void *aux);
+ struct ccase *(*translate) (struct ccase *input, void *aux);
bool (*destroy) (void *aux);
void *aux;
};
/* Creates and returns a new casereader whose cases are produced
by reading from SUBREADER and passing through TRANSLATE, which
- must create case OUTPUT, with OUTPUT_VALUE_CNT values, and
- populate it based on INPUT and auxiliary data AUX. TRANSLATE
- must also destroy INPUT.
+ must return the translated case, with OUTPUT_VALUE_CNT values,
+ and populate it based on INPUT and auxiliary data AUX.
+ TRANSLATE must destroy its input case.
When the translating casereader is destroyed, DESTROY will be
called to allow any state maintained by TRANSLATE to be freed.
struct casereader *
casereader_create_translator (struct casereader *subreader,
size_t output_value_cnt,
- void (*translate) (struct ccase *input,
- struct ccase *output,
- void *aux),
+ struct ccase *(*translate) (struct ccase *input,
+ void *aux),
bool (*destroy) (void *aux),
void *aux)
{
}
/* Internal read function for translating casereader. */
-static bool
+static struct ccase *
casereader_translator_read (struct casereader *reader UNUSED,
- void *ct_, struct ccase *c)
+ void *ct_)
{
struct casereader_translator *ct = ct_;
- struct ccase tmp;
-
- if (casereader_read (ct->subreader, &tmp))
- {
- ct->translate (&tmp, c, ct->aux);
- return true;
- }
- else
- return false;
+ struct ccase *tmp = casereader_read (ct->subreader);
+ if (tmp)
+ tmp = ct->translate (tmp, ct->aux);
+ return tmp;
}
/* Internal destroy function for translating casereader. */
static bool can_destroy (void *can_);
-static void can_translate (struct ccase *input, struct ccase *output,
- void *can_);
+static struct ccase *can_translate (struct ccase *, void *can_);
/* Creates and returns a new casereader whose cases are produced
by reading from SUBREADER and appending an additional value,
}
-static void
-can_translate (struct ccase *input, struct ccase *output, void *can_)
+static struct ccase *
+can_translate (struct ccase *c, void *can_)
{
struct casereader_append_numeric *can = can_;
- double new_value = can->func (input, can->n++, can->aux);
- case_nullify (output);
- case_move (output, input);
- case_resize (output, can->value_ofs + 1);
- case_data_rw_idx (output, can->value_ofs)->f = new_value;
+ double new_value = can->func (c, can->n++, can->aux);
+ c = case_unshare_and_resize (c, can->value_ofs + 1);
+ case_data_rw_idx (c, can->value_ofs)->f = new_value;
+ return c;
}
static bool
static bool car_destroy (void *car_);
-static void car_translate (struct ccase *input, struct ccase *output,
- void *car_);
+static struct ccase *car_translate (struct ccase *input, void *car_);
/* Creates and returns a new casereader whose cases are produced
by reading from SUBREADER and appending an additional value,
return true;
}
-
-static void
-car_translate (struct ccase *input, struct ccase *output, void *car_)
+static struct ccase *
+car_translate (struct ccase *input, void *car_)
{
struct casereader_append_rank *car = car_;
do
{
- struct ccase c;
- if ( ! casereader_peek (car->clone, car->n + ++k, &c))
+ struct ccase *c = casereader_peek (car->clone, car->n + ++k);
+ if (c == NULL)
break;
- vxx = case_data (&c, car->var)->f;
+ vxx = case_data (c, car->var)->f;
if ( vxx == value)
{
if (car->weight)
{
- double w = case_data (&c, car->weight)->f;
+ double w = case_data (c, car->weight)->f;
if ( car->err && w < 0 )
*car->err |= RANK_ERR_NEGATIVE_WEIGHT;
weight += 1.0;
car->n_common++;
}
- case_destroy (&c);
+ case_unref (c);
}
while (vxx == value);
car->mean_rank = car->cc + (weight + 1) / 2.0;
car->n++;
- case_nullify (output);
- case_move (output, input);
- case_resize (output, car->value_ofs + 1);
- case_data_rw_idx (output, car->value_ofs)->f = car->mean_rank ;
+ input = case_unshare_and_resize (input, car->value_ofs + 1);
+ case_data_rw_idx (input, car->value_ofs)->f = car->mean_rank ;
car->prev_value = value;
+ return input;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
static void insert_shim (struct casereader *);
-/* Creates a new case in C and reads the next case from READER
- into it. The caller owns C and must destroy C when its data
- is no longer needed. Return true if successful, false when
- cases have been exhausted or upon detection of an I/O error.
- In the latter case, C is set to the null case.
+/* Reads and returns the next case from READER. The caller owns
+ the returned case and must call case_unref on it when its data
+ is no longer needed. Returns a null pointer if cases have
+ been exhausted or upon detection of an I/O error.
The case returned is effectively consumed: it can never be
read again through READER. If this is inconvenient, READER
may be cloned in advance with casereader_clone, or
casereader_peek may be used instead. */
-bool
-casereader_read (struct casereader *reader, struct ccase *c)
+struct ccase *
+casereader_read (struct casereader *reader)
{
if (reader->case_cnt != 0)
{
case_cnt after calling ->read, then this would actually
drop two cases from case_cnt instead of one, and we'd
lose the last case in the casereader. */
+ struct ccase *c;
if (reader->case_cnt != CASENUMBER_MAX)
reader->case_cnt--;
- if (reader->class->read (reader, reader->aux, c))
+ c = reader->class->read (reader, reader->aux);
+ if (c != NULL)
{
assert (case_get_value_cnt (c) >= reader->value_cnt);
- return true;
+ return c;
}
}
reader->case_cnt = 0;
- case_nullify (c);
- return false;
+ return NULL;
}
/* Destroys READER.
}
}
-/* Creates a new case in C and reads the (IDX + 1)'th case from
- READER into it. The caller owns C and must destroy C when its
- data is no longer needed. Return true if successful, false
- when cases have been exhausted or upon detection of an I/O
- error. In the latter case, C is set to the null case. */
-bool
-casereader_peek (struct casereader *reader, casenumber idx, struct ccase *c)
+/* Reads and returns the (IDX + 1)'th case from READER. The
+ caller owns the returned case and must call case_unref on it
+ when it is no longer needed. Returns a null pointer if cases
+ have been exhausted or upon detection of an I/O error. */
+struct ccase *
+casereader_peek (struct casereader *reader, casenumber idx)
{
if (idx < reader->case_cnt)
{
+ struct ccase *c;
if (reader->class->peek == NULL)
insert_shim (reader);
- if (reader->class->peek (reader, reader->aux, idx, c))
- return true;
+ c = reader->class->peek (reader, reader->aux, idx);
+ if (c != NULL)
+ return c;
else if (casereader_error (reader))
reader->case_cnt = 0;
}
if (reader->case_cnt > idx)
reader->case_cnt = idx;
- case_nullify (c);
- return false;
+ return NULL;
}
/* Returns true if no cases remain to be read from READER, or if
bool
casereader_is_empty (struct casereader *reader)
{
- struct ccase c;
- if (reader->case_cnt == 0 || !casereader_peek (reader, 0, &c))
+ if (reader->case_cnt == 0)
return true;
else
{
- case_destroy (&c);
- return false;
+ struct ccase *c = casereader_peek (reader, 0);
+ if (c == NULL)
+ return true;
+ else
+ {
+ case_unref (c);
+ return false;
+ }
}
}
if (reader->case_cnt == CASENUMBER_MAX)
{
casenumber n_cases = 0;
- struct ccase c;
+ struct ccase *c;
struct casereader *clone = casereader_clone (reader);
- for (; casereader_read (clone, &c); case_destroy (&c))
+ for (; (c = casereader_read (clone)) != NULL; case_unref (c))
n_cases++;
casereader_destroy (clone);
void
casereader_transfer (struct casereader *reader, struct casewriter *writer)
{
- struct ccase c;
+ struct ccase *c;
taint_propagate (casereader_get_taint (reader),
casewriter_get_taint (writer));
- while (casereader_read (reader, &c))
- casewriter_write (writer, &c);
+ while ((c = casereader_read (reader)) != NULL)
+ casewriter_write (writer, c);
casereader_destroy (reader);
}
}
/* struct casereader_class "read" function for random reader. */
-static bool
-random_reader_read (struct casereader *reader, void *br_, struct ccase *c)
+static struct ccase *
+random_reader_read (struct casereader *reader, void *br_)
{
struct random_reader *br = br_;
struct random_reader_shared *shared = br->shared;
-
- if (shared->class->read (reader, shared->aux,
- br->offset - shared->min_offset, c))
+ struct ccase *c = shared->class->read (reader, shared->aux,
+ br->offset - shared->min_offset);
+ if (c != NULL)
{
br->offset++;
heap_changed (shared->readers, &br->heap_node);
advance_random_reader (reader, shared);
- return true;
}
- else
- return false;
+ return c;
}
/* struct casereader_class "destroy" function for random
}
/* struct casereader_class "peek" function for random reader. */
-static bool
-random_reader_peek (struct casereader *reader, void *br_,
- casenumber idx, struct ccase *c)
+static struct ccase *
+random_reader_peek (struct casereader *reader, void *br_, casenumber idx)
{
struct random_reader *br = br_;
struct random_reader_shared *shared = br->shared;
return shared->class->read (reader, shared->aux,
- br->offset - shared->min_offset + idx, c);
+ br->offset - shared->min_offset + idx);
}
/* Casereader class for random reader. */
{
while (casewindow_get_case_cnt (b->window) < case_cnt)
{
- struct ccase tmp;
- if (!casereader_read (b->subreader, &tmp))
+ struct ccase *tmp = casereader_read (b->subreader);
+ if (tmp == NULL)
return false;
- casewindow_push_head (b->window, &tmp);
+ casewindow_push_head (b->window, tmp);
}
return true;
}
/* Reads the case at the given 0-based OFFSET from the front of
- the window into C. Returns true if successful, false if
- OFFSET is beyond the end of file or upon I/O error. */
-static bool
+ the window into C. Returns the case if successful, or a null
+ pointer if OFFSET is beyond the end of file or upon I/O error.
+ The caller must call case_unref() on the returned case when it
+ is no longer needed. */
+static struct ccase *
shim_read (struct casereader *reader UNUSED, void *b_,
- casenumber offset, struct ccase *c)
+ casenumber offset)
{
struct shim *b = b_;
- return (prime_buffer (b, offset + 1)
- && casewindow_get_case (b->window, offset, c));
+ if (!prime_buffer (b, offset + 1))
+ return NULL;
+ return casewindow_get_case (b->window, offset);
}
/* Destroys B. */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
struct casereader;
struct casewriter;
-bool casereader_read (struct casereader *, struct ccase *);
+struct ccase *casereader_read (struct casereader *);
bool casereader_destroy (struct casereader *);
struct casereader *casereader_clone (const struct casereader *);
struct casereader *casereader_rename (struct casereader *);
void casereader_swap (struct casereader *, struct casereader *);
-bool casereader_peek (struct casereader *, casenumber, struct ccase *)
- WARN_UNUSED_RESULT;
+struct ccase *casereader_peek (struct casereader *, casenumber);
bool casereader_is_empty (struct casereader *);
bool casereader_error (const struct casereader *);
struct casereader *
casereader_create_translator (struct casereader *, size_t output_value_cnt,
- void (*translate) (struct ccase *input,
- struct ccase *output,
- void *aux),
+ struct ccase *(*translate) (struct ccase *,
+ void *aux),
bool (*destroy) (void *aux),
void *aux);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
void (*destroy) (void *aux);
void (*push_head) (void *aux, struct ccase *);
void (*pop_tail) (void *aux, casenumber cnt);
- bool (*get_case) (void *aux, casenumber ofs, struct ccase *);
+ struct ccase *(*get_case) (void *aux, casenumber ofs);
casenumber (*get_case_cnt) (const void *aux);
};
new = do_casewindow_create (taint_clone (old->taint), old->value_cnt, 0);
while (casewindow_get_case_cnt (old) > 0 && !casewindow_error (new))
{
- struct ccase c;
- if (!casewindow_get_case (old, 0, &c))
+ struct ccase *c = casewindow_get_case (old, 0);
+ if (c == NULL)
break;
casewindow_pop_tail (old, 1);
- casewindow_push_head (new, &c);
+ casewindow_push_head (new, c);
}
casewindow_swap (old, new);
casewindow_destroy (new);
}
}
else
- case_destroy (c);
+ case_unref (c);
}
/* Deletes CASE_CNT cases at the tail of casewindow CW. */
cw->class->pop_tail (cw->aux, case_cnt);
}
-/* Copies the case that is CASE_IDX cases away from CW's tail
- into C. Returns true if successful, false on an I/O error or
- if CW is otherwise tainted. On failure, nullifies case C. */
-bool
-casewindow_get_case (const struct casewindow *cw_, casenumber case_idx,
- struct ccase *c)
+/* Returns the case that is CASE_IDX cases away from CW's tail
+ into C, or a null pointer on an I/O error or if CW is
+ otherwise tainted. The caller must call case_unref() on the
+ returned case when it is no longer needed. */
+struct ccase *
+casewindow_get_case (const struct casewindow *cw_, casenumber case_idx)
{
struct casewindow *cw = (struct casewindow *) cw_;
assert (case_idx >= 0 && case_idx < casewindow_get_case_cnt (cw));
- if (!casewindow_error (cw))
- return cw->class->get_case (cw->aux, case_idx, c);
- else
- {
- case_nullify (c);
- return false;
- }
+ if (casewindow_error (cw))
+ return NULL;
+ return cw->class->get_case (cw->aux, case_idx);
}
/* Returns the number of cases in casewindow CW. */
struct casewindow_memory
{
struct deque deque;
- struct ccase *cases;
+ struct ccase **cases;
};
static void *
{
struct casewindow_memory *cwm = cwm_;
while (!deque_is_empty (&cwm->deque))
- case_destroy (&cwm->cases[deque_pop_front (&cwm->deque)]);
+ case_unref (cwm->cases[deque_pop_front (&cwm->deque)]);
free (cwm->cases);
free (cwm);
}
struct casewindow_memory *cwm = cwm_;
if (deque_is_full (&cwm->deque))
cwm->cases = deque_expand (&cwm->deque, cwm->cases, sizeof *cwm->cases);
- case_move (&cwm->cases[deque_push_back (&cwm->deque)], c);
+ cwm->cases[deque_push_back (&cwm->deque)] = c;
}
static void
struct casewindow_memory *cwm = cwm_;
assert (deque_count (&cwm->deque) >= case_cnt);
while (case_cnt-- > 0)
- case_destroy (&cwm->cases[deque_pop_front (&cwm->deque)]);
+ case_unref (cwm->cases[deque_pop_front (&cwm->deque)]);
}
-static bool
-casewindow_memory_get_case (void *cwm_, casenumber ofs, struct ccase *c)
+static struct ccase *
+casewindow_memory_get_case (void *cwm_, casenumber ofs)
{
struct casewindow_memory *cwm = cwm_;
- case_clone (c, &cwm->cases[deque_front (&cwm->deque, ofs)]);
- return true;
+ return case_ref (cwm->cases[deque_front (&cwm->deque, ofs)]);
}
static casenumber
cwf->head = cwf->tail = 0;
}
-static bool
-casewindow_file_get_case (void *cwf_, casenumber ofs, struct ccase *c)
+static struct ccase *
+casewindow_file_get_case (void *cwf_, casenumber ofs)
{
struct casewindow_file *cwf = cwf_;
- return case_tmpfile_get_case (cwf->file, cwf->tail + ofs, c);
+ return case_tmpfile_get_case (cwf->file, cwf->tail + ofs);
}
static casenumber
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
void casewindow_push_head (struct casewindow *, struct ccase *);
void casewindow_pop_tail (struct casewindow *, casenumber cnt);
-bool casewindow_get_case (const struct casewindow *, casenumber case_idx,
- struct ccase *);
+struct ccase *casewindow_get_case (const struct casewindow *,
+ casenumber case_idx);
size_t casewindow_get_value_cnt (const struct casewindow *);
casenumber casewindow_get_case_cnt (const struct casewindow *);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 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
{
/* Mandatory.
- Writes case C to WRITER. Destroys C before returning.
+ Writes case C to WRITER. Ownership of C is transferred to
+ WRITER.
If an I/O error occurs, this function should call
casewriter_force_error on WRITER. Some I/O error
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
{
struct casewriter *subwriter;
- void (*translate) (struct ccase *input, struct ccase *output, void *aux);
+ struct ccase *(*translate) (struct ccase *, void *aux);
bool (*destroy) (void *aux);
void *aux;
};
static const struct casewriter_class casewriter_translator_class;
/* Creates and returns a new casewriter whose cases are passed
- through TRANSLATE, which must create case OUTPUT, with
- OUTPUT_VALUE_CNT values, and populate it based on INPUT and
- auxiliary data AUX. The translated cases are then written to
- SUBWRITER. TRANSLATE must also destroy INPUT.
+ through TRANSLATE, which must return a case with
+ OUTPUT_VALUE_CNT values, based on INPUT and auxiliary data
+ AUX. (TRANSLATE may also return a null pointer, in which case
+ no case is written to the output.) The translated cases are
+ then written to SUBWRITER.
+
+ TRANSLATE takes ownership of each case passed to it. Thus, it
+ should either unref each case and return a new case, or
+ (unshare and then) modify and return the same case.
When the translating casewriter is destroyed, DESTROY will be
called to allow any state maintained by TRANSLATE to be freed.
struct casewriter *
casewriter_create_translator (struct casewriter *subwriter,
size_t translated_value_cnt,
- void (*translate) (struct ccase *input,
- struct ccase *output,
- void *aux),
+ struct ccase *(*translate) (struct ccase *,
+ void *aux),
bool (*destroy) (void *aux),
void *aux)
{
void *ct_, struct ccase *c)
{
struct casewriter_translator *ct = ct_;
- struct ccase tmp;
-
- ct->translate (c, &tmp, ct->aux);
- casewriter_write (ct->subwriter, &tmp);
+ c = ct->translate (c, ct->aux);
+ if (c != NULL)
+ casewriter_write (ct->subwriter, c);
}
static void
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
return reader;
}
-/* Reads the case at the given 0-based OFFSET from the front of
- WINDOW into C. Returns true if successful, false if
- OFFSET is beyond the end of file or upon I/O error. */
-static bool
+/* Reads and returns the case at the given 0-based OFFSET from
+ the front of WINDOW into C. Returns a null pointer if OFFSET
+ is beyond the end of file or upon I/O error. The caller must
+ call case_unref() on the returned case when it is no longer
+ needed.*/
+static struct ccase *
casereader_window_read (struct casereader *reader UNUSED, void *window_,
- casenumber offset, struct ccase *c)
+ casenumber offset)
{
struct casewindow *window = window_;
if (offset >= casewindow_get_case_cnt (window))
- return false;
- else
- return casewindow_get_case (window, offset, c);
+ return NULL;
+ return casewindow_get_case (window, offset);
}
/* Destroys casewindow reader WINDOW. */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
\f
struct casewriter *
casewriter_create_translator (struct casewriter *, size_t translated_value_cnt,
- void (*translate) (struct ccase *input,
- struct ccase *output,
- void *aux),
+ struct ccase *(*translate) (struct ccase *input,
+ void *aux),
bool (*destroy) (void *aux),
void *aux);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
axis_move (ds->columns, old_start, new_start, cnt);
}
-/* Retrieves the contents of the given ROW in datasheet DS into
- newly created case C. Returns true if successful, false on
- I/O error. */
-bool
-datasheet_get_row (const struct datasheet *ds, casenumber row, struct ccase *c)
+/* Retrieves and returns the contents of the given ROW in
+ datasheet DS. The caller owns the returned case and must
+ unref it when it is no longer needed. Returns a null pointer
+ on I/O error. */
+struct ccase *
+datasheet_get_row (const struct datasheet *ds, casenumber row)
{
size_t column_cnt = datasheet_get_column_cnt (ds);
- case_create (c, column_cnt);
+ struct ccase *c = case_create (column_cnt);
if (rw_case ((struct datasheet *) ds, OP_READ,
row, 0, column_cnt, case_data_all_rw (c)))
- return true;
+ return c;
else
{
- case_destroy (c);
- return false;
+ case_unref (c);
+ return NULL;
}
}
size_t column_cnt = datasheet_get_column_cnt (ds);
bool ok = rw_case (ds, OP_WRITE, row, 0, column_cnt,
(union value *) case_data_all (c));
- case_destroy (c);
+ case_unref (c);
return ok;
}
(union value *) value);
}
-/* Inserts the CNT cases at C, which are destroyed, into
- datasheet DS just before row BEFORE. Returns true if
- successful, false on I/O error. On failure, datasheet DS is
- not modified. */
+/* Inserts the CNT cases at C into datasheet DS just before row
+ BEFORE. Returns true if successful, false on I/O error. On
+ failure, datasheet DS is not modified.
+
+ Regardless of success, this function unrefs all of the cases
+ in C. */
bool
datasheet_insert_rows (struct datasheet *ds,
- casenumber before, struct ccase c[],
+ casenumber before, struct ccase *c[],
casenumber cnt)
{
casenumber added = 0;
/* Initialize the new rows. */
for (i = 0; i < phy_cnt; i++)
- if (!datasheet_put_row (ds, before + i, &c[i]))
+ if (!datasheet_put_row (ds, before + i, c[i]))
{
while (++i < cnt)
- case_destroy (&c[i]);
+ case_unref (c[i]);
datasheet_delete_rows (ds, before - added, phy_cnt + added);
return false;
}
}
/* "read" function for the datasheet random casereader. */
-static bool
+static struct ccase *
datasheet_reader_read (struct casereader *reader UNUSED, void *ds_,
- casenumber case_idx, struct ccase *c)
+ casenumber case_idx)
{
struct datasheet *ds = ds_;
- if (case_idx >= datasheet_get_row_cnt (ds))
- return false;
- else if (datasheet_get_row (ds, case_idx, c))
- return true;
- else
+ if (case_idx < datasheet_get_row_cnt (ds))
{
- taint_set_taint (ds->taint);
- return false;
+ struct ccase *c = datasheet_get_row (ds, case_idx);
+ if (c == NULL)
+ taint_set_taint (ds->taint);
+ return c;
}
+ else
+ return NULL;
}
/* "destroy" function for the datasheet random casereader. */
return sparse_cases_read (source->data, row, column, values, value_cnt);
else
{
- struct ccase c;
- bool ok;
-
- assert (source->backing != NULL);
- ok = casereader_peek (source->backing, row, &c);
+ struct ccase *c = casereader_peek (source->backing, row);
+ bool ok = c != NULL;
if (ok)
{
- case_copy_out (&c, column, values, value_cnt);
- case_destroy (&c);
+ case_copy_out (c, column, values, value_cnt);
+ case_unref (c);
}
return ok;
}
ok = sparse_cases_write (source->data, row, column, values, value_cnt);
else
{
- struct ccase c;
+ struct ccase *c;
+
if (row < source->backing_rows)
- ok = casereader_peek (source->backing, row, &c);
+ c = case_unshare (casereader_peek (source->backing, row));
else
{
/* It's not one of the backed rows. Ideally, this
levels, so that we in fact usually write the full
contents of new, unbacked rows in multiple calls to
this function. Make this work. */
- case_create (&c, column_cnt);
- ok = true;
+ c = case_create (column_cnt);
}
+ ok = c != NULL;
+
if (ok)
{
- case_copy_in (&c, column, values, value_cnt);
+ case_copy_in (c, column, values, value_cnt);
ok = sparse_cases_write (source->data, row, 0,
- case_data_all (&c), column_cnt);
- case_destroy (&c);
+ case_data_all (c), column_cnt);
+ case_unref (c);
}
}
return ok;
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
/* Rows. */
casenumber datasheet_get_row_cnt (const struct datasheet *);
bool datasheet_insert_rows (struct datasheet *,
- casenumber before, struct ccase[],
+ casenumber before, struct ccase *[],
casenumber cnt);
void datasheet_delete_rows (struct datasheet *,
casenumber first, casenumber cnt);
size_t cnt);
/* Data. */
-bool datasheet_get_row (const struct datasheet *, casenumber, struct ccase *);
+struct ccase *datasheet_get_row (const struct datasheet *, casenumber);
bool datasheet_put_row (struct datasheet *, casenumber, struct ccase *);
bool datasheet_get_value (const struct datasheet *, casenumber, size_t column,
union value *, int width);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
static void gnm_file_casereader_destroy (struct casereader *, void *);
-static bool gnm_file_casereader_read (struct casereader *, void *,
- struct ccase *);
+static struct ccase *gnm_file_casereader_read (struct casereader *, void *);
static const struct casereader_class gnm_file_casereader_class =
{
size_t value_cnt;
struct dictionary *dict;
- struct ccase first_case;
+ struct ccase *first_case;
bool used_first_case;
};
xmlFreeTextReader (r->xtr);
if ( ! r->used_first_case )
- case_destroy (&r->first_case);
+ case_unref (r->first_case);
free (r);
}
goto error;
}
- case_create (&r->first_case, r->value_cnt);
- memset (case_data_rw_idx (&r->first_case, 0)->s,
+ r->first_case = case_create (r->value_cnt);
+ memset (case_data_rw_idx (r->first_case, 0)->s,
' ', MAX_SHORT_STRING * r->value_cnt);
for ( i = 0 ; i < n_var_specs ; ++i )
{
const struct variable *var = dict_get_var (r->dict, i);
- convert_xml_string_to_value (&r->first_case, var,
+ convert_xml_string_to_value (r->first_case, var,
var_spec[i].first_value);
}
};
-/* Reads one case from READER's file into C. Returns true only
- if successful. */
-static bool
-gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_,
- struct ccase *c)
+/* Reads and returns one case from READER's file. Returns a null
+ pointer on failure. */
+static struct ccase *
+gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_)
{
+ struct ccase *c;
int ret = 0;
struct gnumeric_reader *r = r_;
if ( !r->used_first_case )
{
- *c = r->first_case;
r->used_first_case = true;
- return true;
+ return r->first_case;
}
- case_create (c, r->value_cnt);
+ c = case_create (r->value_cnt);
memset (case_data_rw_idx (c, 0)->s, ' ', MAX_SHORT_STRING * r->value_cnt);
}
- return (ret == 1);
+ if (ret == 1)
+ return c;
+ else
+ {
+ case_unref (c);
+ return NULL;
+ }
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
casereader_destroy (subreader);
}
-static bool
-lazy_casereader_read (struct casereader *reader, void *lc_,
- struct ccase *c)
+static struct ccase *
+lazy_casereader_read (struct casereader *reader, void *lc_)
{
struct lazy_casereader *lc = lc_;
instantiate_lazy_casereader (reader, lc);
- return casereader_read (reader, c);
+ return casereader_read (reader);
}
static void
return casereader_clone (reader);
}
-static bool
-lazy_casereader_peek (struct casereader *reader, void *lc_,
- casenumber idx, struct ccase *c)
+static struct ccase *
+lazy_casereader_peek (struct casereader *reader, void *lc_, casenumber idx)
{
struct lazy_casereader *lc = lc_;
instantiate_lazy_casereader (reader, lc);
- return casereader_peek (reader, idx, c);
+ return casereader_peek (reader, idx);
}
static const struct casereader_class lazy_casereader_class =
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 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
}
}
-/* Reads one case from portable file R into C. */
-static bool
-por_file_casereader_read (struct casereader *reader, void *r_, struct ccase *c)
+/* Reads and returns one case from portable file R. Returns a
+ null pointer on failure. */
+static struct ccase *
+por_file_casereader_read (struct casereader *reader, void *r_)
{
struct pfm_reader *r = r_;
+ struct ccase *volatile c;
size_t i;
size_t idx;
- case_create (c, casereader_get_value_cnt (reader));
+ c = case_create (casereader_get_value_cnt (reader));
setjmp (r->bail_out);
if (!r->ok)
{
casereader_force_error (reader);
- case_destroy (c);
- return false;
+ case_unref (c);
+ return NULL;
}
/* Check for end of file. */
if (r->cc == 'Z')
{
- case_destroy (c);
- return false;
+ case_unref (c);
+ return NULL;
}
idx = 0;
}
}
- return true;
+ return c;
}
/* Returns true if FILE is an SPSS portable file,
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
struct dictionary;
struct file_handle;
-struct ccase;
struct casereader *pfm_open_reader (struct file_handle *,
struct dictionary **,
struct pfm_read_info *);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 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
else
casewriter_force_error (writer);
- case_destroy (c);
+ case_unref (c);
}
static void
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
struct file_handle;
struct dictionary;
-struct ccase;
struct casewriter *pfm_open_writer (struct file_handle *, struct dictionary *,
struct pfm_write_options);
struct pfm_write_options pfm_writer_default_options (void);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 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
/* Cases just before ("lagging") the current one. */
int n_lag; /* Number of cases to lag. */
struct deque lag; /* Deque of lagged cases. */
- struct ccase *lag_cases; /* Lagged cases managed by deque. */
+ struct ccase **lag_cases; /* Lagged cases managed by deque. */
/* Procedure data. */
enum
}
/* "read" function for procedure casereader. */
-static bool
-proc_casereader_read (struct casereader *reader UNUSED, void *ds_,
- struct ccase *c)
+static struct ccase *
+proc_casereader_read (struct casereader *reader UNUSED, void *ds_)
{
struct dataset *ds = ds_;
enum trns_result retval = TRNS_DROP_CASE;
+ struct ccase *c;
assert (ds->proc_state == PROC_OPEN);
- for (;;)
+ for (; ; case_unref (c))
{
casenumber case_nr;
if (retval == TRNS_ERROR)
ds->ok = false;
if (!ds->ok)
- return false;
+ return NULL;
/* Read a case from source. */
- if (!casereader_read (ds->source, c))
- return false;
- case_resize (c, dict_get_next_value_idx (ds->dict));
+ c = casereader_read (ds->source);
+ if (c == NULL)
+ return NULL;
+ c = case_unshare_and_resize (c, dict_get_next_value_idx (ds->dict));
caseinit_init_vars (ds->caseinit, c);
/* Execute permanent transformations. */
case_nr = ds->cases_written + 1;
retval = trns_chain_execute (ds->permanent_trns_chain, TRNS_CONTINUE,
- c, case_nr);
+ &c, case_nr);
caseinit_update_left_vars (ds->caseinit, c);
if (retval != TRNS_CONTINUE)
- {
- case_destroy (c);
- continue;
- }
+ continue;
/* Write case to collection of lagged cases. */
if (ds->n_lag > 0)
{
while (deque_count (&ds->lag) >= ds->n_lag)
- case_destroy (&ds->lag_cases[deque_pop_back (&ds->lag)]);
- case_clone (&ds->lag_cases[deque_push_front (&ds->lag)], c);
+ case_unref (ds->lag_cases[deque_pop_back (&ds->lag)]);
+ ds->lag_cases[deque_push_front (&ds->lag)] = case_ref (c);
}
/* Write case to replacement active file. */
ds->cases_written++;
if (ds->sink != NULL)
- {
- struct ccase tmp;
- if (ds->compactor != NULL)
- case_map_execute (ds->compactor, c, &tmp);
- else
- case_clone (&tmp, c);
- casewriter_write (ds->sink, &tmp);
- }
+ casewriter_write (ds->sink,
+ case_map_execute (ds->compactor, case_ref (c)));
/* Execute temporary transformations. */
if (ds->temporary_trns_chain != NULL)
{
retval = trns_chain_execute (ds->temporary_trns_chain, TRNS_CONTINUE,
- c, ds->cases_written);
+ &c, ds->cases_written);
if (retval != TRNS_CONTINUE)
- {
- case_destroy (c);
- continue;
- }
+ continue;
}
- return true;
+ return c;
}
}
proc_casereader_destroy (struct casereader *reader, void *ds_)
{
struct dataset *ds = ds_;
- struct ccase c;
+ struct ccase *c;
/* Make sure transformations happen for every input case, in
case they have side effects, and ensure that the replacement
active file gets all the cases it should. */
- while (casereader_read (reader, &c))
- case_destroy (&c);
+ while ((c = casereader_read (reader)) != NULL)
+ case_unref (c);
ds->proc_state = PROC_CLOSED;
ds->ok = casereader_destroy (ds->source) && ds->ok;
/* Free memory for lagged cases. */
while (!deque_is_empty (&ds->lag))
- case_destroy (&ds->lag_cases[deque_pop_back (&ds->lag)]);
+ case_unref (ds->lag_cases[deque_pop_back (&ds->lag)]);
free (ds->lag_cases);
/* Dictionary from before TEMPORARY becomes permanent. */
\f
/* Returns a pointer to the lagged case from N_BEFORE cases before the
current one, or NULL if there haven't been that many cases yet. */
-struct ccase *
+const struct ccase *
lagged_case (const struct dataset *ds, int n_before)
{
assert (n_before >= 1);
assert (n_before <= ds->n_lag);
if (n_before <= deque_count (&ds->lag))
- return &ds->lag_cases[deque_front (&ds->lag, n_before - 1)];
+ return ds->lag_cases[deque_front (&ds->lag, n_before - 1)];
else
return NULL;
}
*CASES_REMAINING. */
static int
case_limit_trns_proc (void *cases_remaining_,
- struct ccase *c UNUSED, casenumber case_nr UNUSED)
+ struct ccase **c UNUSED, casenumber case_nr UNUSED)
{
size_t *cases_remaining = cases_remaining_;
if (*cases_remaining > 0)
/* FILTER transformation. */
static int
filter_trns_proc (void *filter_var_,
- struct ccase *c UNUSED, casenumber case_nr UNUSED)
+ struct ccase **c UNUSED, casenumber case_nr UNUSED)
{
struct variable *filter_var = filter_var_;
- double f = case_num (c, filter_var);
+ double f = case_num (*c, filter_var);
return (f != 0.0 && !var_is_num_missing (filter_var, f, MV_ANY)
? TRNS_CONTINUE : TRNS_DROP_CASE);
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 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
const struct casereader *dataset_source (const struct dataset *ds);
-struct ccase *lagged_case (const struct dataset *ds, int n_before);
+const struct ccase *lagged_case (const struct dataset *ds, int n_before);
void dataset_need_lag (struct dataset *ds, int n_before);
#endif /* procedure.h */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 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
static void psql_casereader_destroy (struct casereader *reader UNUSED, void *r_);
-static bool psql_casereader_read (struct casereader *, void *,
- struct ccase *);
+static struct ccase *psql_casereader_read (struct casereader *, void *);
static const struct casereader_class psql_casereader_class =
{
};
-static bool set_value (struct psql_reader *r,
- struct ccase *cc);
+static struct ccase *set_value (struct psql_reader *r);
-static bool
-psql_casereader_read (struct casereader *reader UNUSED, void *r_,
- struct ccase *cc)
+static struct ccase *
+psql_casereader_read (struct casereader *reader UNUSED, void *r_)
{
struct psql_reader *r = r_;
return false;
}
- return set_value (r, cc);
+ return set_value (r);
}
-static bool
-set_value (struct psql_reader *r,
- struct ccase *c)
+static struct ccase *
+set_value (struct psql_reader *r)
{
- int i;
+ struct ccase *c;
int n_vars;
+ int i;
assert (r->res);
n_vars = PQnfields (r->res);
if ( r->tuple >= PQntuples (r->res))
- return false;
+ return NULL;
- case_create (c, r->value_cnt);
+ c = case_create (r->value_cnt);
memset (case_data_rw_idx (c, 0)->s, ' ', MAX_SHORT_STRING * r->value_cnt);
r->tuple++;
- return true;
+ return c;
}
#endif
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 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
struct dictionary;
struct file_handle;
-struct ccase;
struct casereader *scratch_reader_open (struct file_handle *,
struct dictionary **);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 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
struct ccase *c)
{
struct scratch_writer *writer = writer_;
- struct ccase tmp;
- if (writer->compactor)
- {
- case_map_execute (writer->compactor, c, &tmp);
- case_destroy (c);
- }
- else
- case_move (&tmp, c);
- casewriter_write (writer->subwriter, &tmp);
+ casewriter_write (writer->subwriter,
+ case_map_execute (writer->compactor, c));
}
/* Closes WRITER. */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 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
struct dictionary;
struct file_handle;
-struct ccase;
struct casewriter *scratch_writer_open (struct file_handle *,
const struct dictionary *);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
#include <stdlib.h>
#include <string.h>
+#include <data/case.h>
#include <data/settings.h>
#include <data/case-tmpfile.h>
#include <libpspp/assertion.h>
sc->column_cnt = column_cnt;
sc->default_columns = NULL;
sc->max_memory_cases = settings_get_workspace_cases (column_cnt);
- sc->memory = sparse_array_create (sizeof (struct ccase));
+ sc->memory = sparse_array_create (sizeof (struct ccase *));
sc->disk = NULL;
sc->disk_cases = NULL;
return sc;
if (old->memory != NULL)
{
unsigned long int idx;
- struct ccase *c;
+ struct ccase **cp;
- new->memory = sparse_array_create (sizeof (struct ccase));
- for (c = sparse_array_scan (old->memory, NULL, &idx); c != NULL;
- c = sparse_array_scan (old->memory, &idx, &idx))
- case_clone (sparse_array_insert (new->memory, idx), c);
+ new->memory = sparse_array_create (sizeof (struct ccase *));
+ for (cp = sparse_array_scan (old->memory, NULL, &idx); cp != NULL;
+ cp = sparse_array_scan (old->memory, &idx, &idx))
+ {
+ struct ccase **ncp = sparse_array_insert (new->memory, idx);
+ *ncp = case_ref (*cp);
+ }
}
else
new->memory = NULL;
unsigned long int start = range_set_node_get_start (node);
unsigned long int end = range_set_node_get_end (node);
unsigned long int idx;
- struct ccase c;
-
- for (idx = start; idx < end; idx++)
- if (!case_tmpfile_get_case (old->disk, idx, &c)
- || !case_tmpfile_put_case (new->disk, idx, &c))
- {
- sparse_cases_destroy (new);
- return NULL;
- }
+
+ for (idx = start; idx < end; idx++)
+ {
+ struct ccase *c = case_tmpfile_get_case (old->disk, idx);
+ if (c == NULL || !case_tmpfile_put_case (new->disk, idx, c))
+ {
+ sparse_cases_destroy (new);
+ return NULL;
+ }
+ }
}
}
else
if (sc->memory != NULL)
{
unsigned long int idx;
- struct ccase *c;
- for (c = sparse_array_scan (sc->memory, NULL, &idx); c != NULL;
- c = sparse_array_scan (sc->memory, &idx, &idx))
- case_destroy (c);
+ struct ccase **cp;
+ for (cp = sparse_array_scan (sc->memory, NULL, &idx); cp != NULL;
+ cp = sparse_array_scan (sc->memory, &idx, &idx))
+ case_unref (*cp);
sparse_array_destroy (sc->memory);
}
free (sc->default_columns);
dump_sparse_cases_to_disk (struct sparse_cases *sc)
{
unsigned long int idx;
- struct ccase *c;
+ struct ccase **cp;
assert (sc->memory != NULL);
assert (sc->disk == NULL);
sc->disk = case_tmpfile_create (sc->column_cnt);
sc->disk_cases = range_set_create ();
- for (c = sparse_array_scan (sc->memory, NULL, &idx); c != NULL;
- c = sparse_array_scan (sc->memory, &idx, &idx))
+ for (cp = sparse_array_scan (sc->memory, NULL, &idx); cp != NULL;
+ cp = sparse_array_scan (sc->memory, &idx, &idx))
{
- if (!case_tmpfile_put_case (sc->disk, idx, c))
+ if (!case_tmpfile_put_case (sc->disk, idx, *cp))
{
case_tmpfile_destroy (sc->disk);
sc->disk = NULL;
if (sparse_cases_contains_row (sc, row))
{
- struct ccase c;
+ struct ccase *c;
if (sc->memory != NULL)
- case_clone (&c, sparse_array_get (sc->memory, row));
- else if (!case_tmpfile_get_case (sc->disk, row, &c))
- return false;
- case_copy_out (&c, column, values, value_cnt);
- case_destroy (&c);
+ {
+ struct ccase **cp = sparse_array_get (sc->memory, row);
+ c = case_ref (*cp);
+ }
+ else
+ {
+ c = case_tmpfile_get_case (sc->disk, row);
+ if (c == NULL)
+ return false;
+ }
+ case_copy_out (c, column, values, value_cnt);
+ case_unref (c);
}
else
{
write_disk_case (struct sparse_cases *sc, casenumber row, size_t column,
const union value values[], size_t value_cnt)
{
- struct ccase c;
+ struct ccase *c;
bool ok;
/* Get current case data. */
if (column == 0 && value_cnt == sc->column_cnt)
- case_create (&c, sc->column_cnt);
- else if (!case_tmpfile_get_case (sc->disk, row, &c))
- return false;
+ c = case_create (sc->column_cnt);
+ else
+ {
+ c = case_tmpfile_get_case (sc->disk, row);
+ if (c == NULL)
+ return false;
+ }
/* Copy in new data. */
- case_copy_in (&c, column, values, value_cnt);
+ case_copy_in (c, column, values, value_cnt);
/* Write new case. */
- ok = case_tmpfile_put_case (sc->disk, row, &c);
+ ok = case_tmpfile_put_case (sc->disk, row, c);
if (ok)
range_set_insert (sc->disk_cases, row, 1);
{
if (sc->memory != NULL)
{
- struct ccase *c = sparse_array_get (sc->memory, row);
- if (c == NULL)
+ struct ccase *c, **cp;
+ cp = sparse_array_get (sc->memory, row);
+ if (cp != NULL)
+ c = *cp = case_unshare (*cp);
+ else
{
if (sparse_array_count (sc->memory) >= sc->max_memory_cases)
{
return write_disk_case (sc, row, column, values, value_cnt);
}
- c = sparse_array_insert (sc->memory, row);
- case_create (c, sc->column_cnt);
+ cp = sparse_array_insert (sc->memory, row);
+ c = *cp = case_create (sc->column_cnt);
if (sc->default_columns != NULL
&& (column != 0 || value_cnt != sc->column_cnt))
case_copy_in (c, 0, sc->default_columns, sc->column_cnt);
/* Set individual rows. */
if (sc->memory != NULL)
{
- struct ccase *c;
+ struct ccase **cp;
unsigned long int idx;
- for (c = sparse_array_scan (sc->memory, NULL, &idx); c != NULL;
- c = sparse_array_scan (sc->memory, &idx, &idx))
- case_copy_in (c, start_column, values, value_cnt);
+ for (cp = sparse_array_scan (sc->memory, NULL, &idx); cp != NULL;
+ cp = sparse_array_scan (sc->memory, &idx, &idx))
+ {
+ *cp = case_unshare (*cp);
+ case_copy_in (*cp, start_column, values, value_cnt);
+ }
}
else
{
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 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
/* Copies the fields in SRC represented by SRC_SC into the
corresponding fields in DST respresented by DST_SC. SRC_SC
and DST_SC must be conformable (as tested by
- subcase_conformable()). */
+ subcase_conformable()).
+
+ DST must not be shared. */
void
subcase_copy (const struct subcase *src_sc, const struct ccase *src,
const struct subcase *dst_sc, struct ccase *dst)
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 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
static bool read_whole_strings (struct sfm_reader *, char *, size_t);
static bool skip_whole_strings (struct sfm_reader *, size_t);
-/* Reads one case from READER's file into C. Returns true only
- if successful. */
-static bool
-sys_file_casereader_read (struct casereader *reader, void *r_,
- struct ccase *c)
+/* Reads and returns one case from READER's file. Returns a null
+ pointer if not successful. */
+static struct ccase *
+sys_file_casereader_read (struct casereader *reader, void *r_)
{
struct sfm_reader *r = r_;
+ struct ccase *volatile c;
int i;
if (r->error)
- return false;
+ return NULL;
- case_create (c, r->value_cnt);
+ c = case_create (r->value_cnt);
if (setjmp (r->bail_out))
{
casereader_force_error (reader);
- case_destroy (c);
- return false;
+ case_unref (c);
+ return NULL;
}
for (i = 0; i < r->sfm_var_cnt; i++)
partial_record (r);
}
}
- return true;
+ return c;
eof:
- case_destroy (c);
+ case_unref (c);
if (i != 0)
partial_record (r);
if (r->case_cnt != -1)
read_error (reader, r);
- return false;
+ return NULL;
}
/* Issues an error that R ends in a partial record. */
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
struct dictionary;
struct file_handle;
-struct ccase;
struct casereader *sfm_open_reader (struct file_handle *,
struct dictionary **,
struct sfm_read_info *);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 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
static void write_spaces (struct sfm_writer *, size_t);
static void write_value (struct sfm_writer *, const union value *, int width);
-static void write_case_uncompressed (struct sfm_writer *, struct ccase *);
-static void write_case_compressed (struct sfm_writer *, struct ccase *);
+static void write_case_uncompressed (struct sfm_writer *,
+ const struct ccase *);
+static void write_case_compressed (struct sfm_writer *, const struct ccase *);
static void flush_compressed (struct sfm_writer *);
static void put_cmp_opcode (struct sfm_writer *, uint8_t);
static void put_cmp_number (struct sfm_writer *, double);
if (ferror (w->file))
{
casewriter_force_error (writer);
- case_destroy (c);
+ case_unref (c);
return;
}
else
write_case_compressed (w, c);
- case_destroy (c);
+ case_unref (c);
}
/* Destroys system file writer W. */
\f
/* Writes case C to system file W, without compressing it. */
static void
-write_case_uncompressed (struct sfm_writer *w, struct ccase *c)
+write_case_uncompressed (struct sfm_writer *w, const struct ccase *c)
{
size_t i;
/* Writes case C to system file W, with compression. */
static void
-write_case_compressed (struct sfm_writer *w, struct ccase *c)
+write_case_compressed (struct sfm_writer *w, const struct ccase *c)
{
size_t i;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
struct file_handle;
struct dictionary;
-struct ccase;
struct casewriter *sfm_open_writer (struct file_handle *, struct dictionary *,
struct sfm_write_options);
struct sfm_write_options sfm_writer_default_options (void);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 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
return chain->trns_cnt;
}
-/* Executes the given CHAIN of transformations on C,
+/* Executes the given CHAIN of transformations on *C,
passing CASE_NR as the case number.
+ *C may be replaced 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 (const struct trns_chain *chain, enum trns_result start,
- struct ccase *c, casenumber case_nr)
+ struct ccase **c, casenumber case_nr)
{
size_t i;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 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
struct ccase;
typedef void trns_finalize_func (void *);
-typedef int trns_proc_func (void *, struct ccase *, casenumber);
+typedef int trns_proc_func (void *, struct ccase **, casenumber);
typedef bool trns_free_func (void *);
\f
/* Transformation chains. */
void trns_chain_append (struct trns_chain *, trns_finalize_func *,
trns_proc_func *, trns_free_func *, void *);
size_t trns_chain_next (struct trns_chain *);
-enum trns_result trns_chain_execute (const struct trns_chain *, enum trns_result,
- struct ccase *, casenumber case_nr);
+enum trns_result trns_chain_execute (const struct trns_chain *,
+ enum trns_result, struct ccase **,
+ casenumber case_nr);
void trns_chain_splice (struct trns_chain *, struct trns_chain *);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
Checks each clause and jumps to the appropriate
transformation. */
static int
-do_if_trns_proc (void *do_if_, struct ccase *c, casenumber case_num UNUSED)
+do_if_trns_proc (void *do_if_, struct ccase **c, casenumber case_num UNUSED)
{
struct do_if_trns *do_if = do_if_;
struct clause *clause;
{
if (clause->condition != NULL)
{
- double boolean = expr_evaluate_num (clause->condition, c, case_num);
+ double boolean = expr_evaluate_num (clause->condition, *c, case_num);
if (boolean == 1.0)
return clause->target_index;
else if (boolean == SYSMIS)
/* Breaks out of a DO IF construct. */
static int
-break_trns_proc (void *do_if_, struct ccase *c UNUSED, casenumber case_num UNUSED)
+break_trns_proc (void *do_if_, struct ccase **c UNUSED,
+ casenumber case_num UNUSED)
{
struct do_if_trns *do_if = do_if_;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
/* Sets up LOOP for the first pass. */
static int
-loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num)
+loop_trns_proc (void *loop_, struct ccase **c, casenumber case_num)
{
struct loop_trns *loop = loop_;
if (loop->index_var != NULL)
{
/* Evaluate loop index expressions. */
- loop->cur = expr_evaluate_num (loop->first_expr, c, case_num);
+ loop->cur = expr_evaluate_num (loop->first_expr, *c, case_num);
if (loop->by_expr != NULL)
- loop->by = expr_evaluate_num (loop->by_expr, c, case_num);
- loop->last = expr_evaluate_num (loop->last_expr, c, case_num);
+ loop->by = expr_evaluate_num (loop->by_expr, *c, case_num);
+ loop->last = expr_evaluate_num (loop->last_expr, *c, case_num);
/* Even if the loop is never entered, set the index
variable to the initial value. */
- case_data_rw (c, loop->index_var)->f = loop->cur;
+ *c = case_unshare (*c);
+ case_data_rw (*c, loop->index_var)->f = loop->cur;
/* Throw out pathological cases. */
if (!isfinite (loop->cur) || !isfinite (loop->by)
/* Check condition. */
if (loop->loop_condition != NULL
- && expr_evaluate_num (loop->loop_condition, c, case_num) != 1.0)
+ && expr_evaluate_num (loop->loop_condition, *c, case_num) != 1.0)
goto zero_pass;
return loop->past_LOOP_index;
/* Finishes a pass through the loop and starts the next. */
static int
-end_loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num UNUSED)
+end_loop_trns_proc (void *loop_, struct ccase **c, casenumber case_num UNUSED)
{
struct loop_trns *loop = loop_;
if (loop->end_loop_condition != NULL
- && expr_evaluate_num (loop->end_loop_condition, c, case_num) != 0.0)
+ && expr_evaluate_num (loop->end_loop_condition, *c, case_num) != 0.0)
goto break_out;
/* MXLOOPS limiter. */
if ((loop->by > 0.0 && loop->cur > loop->last)
|| (loop->by < 0.0 && loop->cur < loop->last))
goto break_out;
- case_data_rw (c, loop->index_var)->f = loop->cur;
+ *c = case_unshare (*c);
+ case_data_rw (*c, loop->index_var)->f = loop->cur;
}
if (loop->loop_condition != NULL
- && expr_evaluate_num (loop->loop_condition, c, case_num) != 1.0)
+ && expr_evaluate_num (loop->loop_condition, *c, case_num) != 1.0)
goto break_out;
return loop->past_LOOP_index;
/* Executes BREAK. */
static int
-break_trns_proc (void *loop_, struct ccase *c UNUSED, casenumber case_num UNUSED)
+break_trns_proc (void *loop_, struct ccase **c UNUSED,
+ casenumber case_num UNUSED)
{
struct loop_trns *loop = loop_;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2008, 2009 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
struct file_handle *handle; /* Input file handle. */
struct dictionary *dict; /* Input file dictionary. */
struct casereader *reader; /* Input data source. */
- struct ccase data; /* The current input case. */
+ struct ccase *data; /* The current input case. */
bool is_minimal; /* Does 'data' have minimum BY values across
all input files? */
bool is_sorted; /* Is file presorted on the BY variables? */
members used. */
struct variable *first; /* Variable specified on FIRST (if any). */
struct variable *last; /* Variable specified on LAST (if any). */
- struct ccase buffered_case; /* Case ready for output except that we don't
- know the value for the LAST variable yet. */
+ struct ccase *buffered_case; /* Case ready for output except that we don't
+ know the value for the LAST var yet. */
union value *prev_BY; /* Values of BY vars in buffered_case. */
};
subcase_init_empty (&proc.by_vars);
proc.first = NULL;
proc.last = NULL;
- case_nullify (&proc.buffered_case);
+ proc.buffered_case = NULL;
proc.prev_BY = NULL;
dict_set_case_limit (proc.dict, dict_get_case_limit (dataset_dict (ds)));
file->handle = NULL;
file->dict = NULL;
file->reader = NULL;
- case_nullify (&file->data);
+ file->data = NULL;
file->is_sorted = true;
file->in_name[0] = '\0';
file->in_var = NULL;
if (!file->is_sorted)
file->reader = sort_execute (file->reader, &file->by_vars);
taint_propagate (casereader_get_taint (file->reader), taint);
- casereader_read (file->reader, &file->data);
+ file->data = casereader_read (file->reader);
if (file->type == COMB_FILE)
case_matcher_add_input (proc.matcher, &file->by_vars,
&file->data, &file->is_minimal);
fh_unref (file->handle);
dict_destroy (file->dict);
casereader_destroy (file->reader);
- case_destroy (&file->data);
+ case_unref (file->data);
}
free (proc->files);
proc->files = NULL;
casewriter_destroy (proc->output);
case_matcher_destroy (proc->matcher);
subcase_destroy (&proc->by_vars);
- case_destroy (&proc->buffered_case);
+ case_unref (proc->buffered_case);
free (proc->prev_BY);
}
\f
static bool scan_table (struct comb_file *, union value by[]);
-static void create_output_case (const struct comb_proc *, struct ccase *);
+static struct ccase *create_output_case (const struct comb_proc *);
static void apply_case (const struct comb_file *, struct ccase *);
static void apply_file_case_and_advance (struct comb_file *, struct ccase *,
union value by[]);
while (case_matcher_match (proc->matcher, &by))
{
- struct ccase output;
size_t i;
for (i = 0; i < proc->n_files; i++)
struct comb_file *file = &proc->files[i];
while (file->is_minimal)
{
- create_output_case (proc, &output);
- apply_file_case_and_advance (file, &output, by);
- output_case (proc, &output, by);
+ struct ccase *output = create_output_case (proc);
+ apply_file_case_and_advance (file, output, by);
+ output_case (proc, output, by);
}
}
}
while (case_matcher_match (proc->matcher, &by))
{
- struct ccase output;
+ struct ccase *output;
size_t i;
- create_output_case (proc, &output);
+ output = create_output_case (proc);
for (i = proc->n_files; i-- > 0; )
{
struct comb_file *file = &proc->files[i];
if (file->type == COMB_FILE)
{
if (file->is_minimal)
- apply_file_case_and_advance (file, &output, NULL);
+ apply_file_case_and_advance (file, output, NULL);
}
else
{
if (scan_table (file, by))
- apply_case (file, &output);
+ apply_case (file, output);
}
}
- output_case (proc, &output, by);
+ output_case (proc, output, by);
}
output_buffered_case (proc);
}
while (case_matcher_match (proc->matcher, &by))
{
struct comb_file *first, *file;
- struct ccase output;
+ struct ccase *output;
/* Find first nonnull case in array and make an output case
from it. */
- create_output_case (proc, &output);
+ output = create_output_case (proc);
for (first = &proc->files[0]; ; first++)
if (first->is_minimal)
break;
- apply_file_case_and_advance (first, &output, by);
+ apply_file_case_and_advance (first, output, by);
/* Read additional cases and update the output case from
them. (Don't update the output case from any duplicate
file < &proc->files[proc->n_files]; file++)
{
while (file->is_minimal)
- apply_file_case_and_advance (file, &output, by);
+ apply_file_case_and_advance (file, output, by);
}
- casewriter_write (proc->output, &output);
+ casewriter_write (proc->output, output);
/* Write duplicate cases in the master file directly to the
output. */
n_duplicates++;
while (first->is_minimal)
{
- create_output_case (proc, &output);
- apply_file_case_and_advance (first, &output, by);
- casewriter_write (proc->output, &output);
+ output = create_output_case (proc);
+ apply_file_case_and_advance (first, output, by);
+ casewriter_write (proc->output, output);
}
}
}
static bool
scan_table (struct comb_file *file, union value by[])
{
- while (!case_is_null (&file->data))
+ while (file->data != NULL)
{
- int cmp = subcase_compare_3way_xc (&file->by_vars, by, &file->data);
+ int cmp = subcase_compare_3way_xc (&file->by_vars, by, file->data);
if (cmp > 0)
{
- case_destroy (&file->data);
- casereader_read (file->reader, &file->data);
+ case_unref (file->data);
+ file->data = casereader_read (file->reader);
}
else
return cmp == 0;
return false;
}
-/* Creates OUTPUT as an output case for PROC, by initializing each of
- its values to system-missing or blanks, except that the values
- of IN variables are set to 0. */
-static void
-create_output_case (const struct comb_proc *proc, struct ccase *output)
+/* Creates and returns an output case for PROC, initializing each
+ of its values to system-missing or blanks, except that the
+ values of IN variables are set to 0. */
+static struct ccase *
+create_output_case (const struct comb_proc *proc)
{
size_t n_vars = dict_get_var_cnt (proc->dict);
+ struct ccase *output;
size_t i;
- case_create (output, dict_get_next_value_idx (proc->dict));
+ output = case_create (dict_get_next_value_idx (proc->dict));
for (i = 0; i < n_vars; i++)
{
struct variable *v = dict_get_var (proc->dict, i);
if (file->in_var != NULL)
case_data_rw (output, file->in_var)->f = false;
}
+ return output;
}
/* Copies the data from FILE's case into output case OUTPUT.
static void
apply_case (const struct comb_file *file, struct ccase *output)
{
- subcase_copy (&file->src, &file->data, &file->dst, output);
+ subcase_copy (&file->src, file->data, &file->dst, output);
if (file->in_var != NULL)
case_data_rw (output, file->in_var)->f = true;
}
union value by[])
{
apply_case (file, output);
- case_destroy (&file->data);
- casereader_read (file->reader, &file->data);
+ case_unref (file->data);
+ file->data = casereader_read (file->reader);
if (by)
- file->is_minimal = (!case_is_null (&file->data)
- && subcase_equal_cx (&file->by_vars, &file->data, by));
+ file->is_minimal = (file->data != NULL
+ && subcase_equal_cx (&file->by_vars, file->data, by));
}
/* Writes OUTPUT, whose BY values has been extracted into BY, to
{
new_BY = !subcase_equal_xx (&proc->by_vars, proc->prev_BY, by);
if (proc->last != NULL)
- case_data_rw (&proc->buffered_case, proc->last)->f = new_BY;
- casewriter_write (proc->output, &proc->buffered_case);
+ case_data_rw (proc->buffered_case, proc->last)->f = new_BY;
+ casewriter_write (proc->output, proc->buffered_case);
}
else
new_BY = true;
- case_move (&proc->buffered_case, output);
+ proc->buffered_case = output;
if (proc->first != NULL)
- case_data_rw (&proc->buffered_case, proc->first)->f = new_BY;
+ case_data_rw (proc->buffered_case, proc->first)->f = new_BY;
if (new_BY)
{
if (proc->prev_BY != NULL)
{
if (proc->last != NULL)
- case_data_rw (&proc->buffered_case, proc->last)->f = 1.0;
- casewriter_write (proc->output, &proc->buffered_case);
- case_nullify (&proc->buffered_case);
+ case_data_rw (proc->buffered_case, proc->last)->f = 1.0;
+ casewriter_write (proc->output, proc->buffered_case);
+ proc->buffered_case = NULL;
}
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 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
return true;
}
-/* Handle DATA LIST transformation TRNS, parsing data into C. */
+/* Handle DATA LIST transformation TRNS, parsing data into *C. */
static int
-data_list_trns_proc (void *trns_, struct ccase *c, casenumber case_num UNUSED)
+data_list_trns_proc (void *trns_, struct ccase **c, casenumber case_num UNUSED)
{
struct data_list_trns *trns = trns_;
int retval;
- if (data_parser_parse (trns->parser, trns->reader, c))
+ *c = case_unshare (*c);
+ if (data_parser_parse (trns->parser, trns->reader, *c))
retval = TRNS_CONTINUE;
else if (dfm_reader_error (trns->reader) || dfm_eof (trns->reader) > 1)
{
/* If there was an END subcommand handle it. */
if (trns->end != NULL)
{
- double *end = &case_data_rw (c, trns->end)->f;
+ double *end = &case_data_rw (*c, trns->end)->f;
if (retval == TRNS_END_FILE)
{
*end = 1.0;
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
static bool parse_fixed (const struct data_parser *,
struct dfm_reader *, struct ccase *);
-/* Reads a case from DFM into C, parsing it with PARSER.
- Returns true if successful, false at end of file or on I/O error. */
+/* Reads a case from DFM into C, parsing it with PARSER. Returns
+ true if successful, false at end of file or on I/O error.
+
+ Case C must not be shared. */
bool
data_parser_parse (struct data_parser *parser, struct dfm_reader *reader,
struct ccase *c)
{
bool retval;
+ assert (!case_is_shared (c));
assert (data_parser_any_fields (parser));
/* Skip the requested number of records before reading the
proc_set_active_file (ds, casereader, dict);
}
-static bool
-data_parser_casereader_read (struct casereader *reader UNUSED, void *r_,
- struct ccase *c)
+static struct ccase *
+data_parser_casereader_read (struct casereader *reader UNUSED, void *r_)
{
struct data_parser_casereader *r = r_;
- bool ok;
-
- case_create (c, r->value_cnt);
- ok = data_parser_parse (r->parser, r->reader, c);
- if (!ok)
- case_destroy (c);
- return ok;
+ struct ccase *c = case_create (r->value_cnt);
+ if (data_parser_parse (r->parser, r->reader, c))
+ return c;
+ else
+ {
+ case_unref (c);
+ return NULL;
+ }
}
static void
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
|| state >= 0);
}
-/* Reads one case into C.
- Returns true if successful, false at end of file or if an
+/* Reads and returns one case.
+ Returns the case if successful, null at end of file or if an
I/O error occurred. */
-static bool
-input_program_casereader_read (struct casereader *reader UNUSED, void *inp_,
- struct ccase *c)
+static struct ccase *
+input_program_casereader_read (struct casereader *reader UNUSED, void *inp_)
{
struct input_program_pgm *inp = inp_;
-
- case_create (c, inp->value_cnt);
+ struct ccase *c = case_create (inp->value_cnt);
do
{
assert (is_valid_state (inp->restart));
if (inp->restart == TRNS_ERROR || inp->restart == TRNS_END_FILE)
{
- case_destroy (c);
- return false;
+ case_unref (c);
+ return NULL;
}
+ c = case_unshare (c);
caseinit_init_vars (inp->init, c);
inp->restart = trns_chain_execute (inp->trns_chain, inp->restart,
- c, inp->case_nr);
+ &c, inp->case_nr);
assert (is_valid_state (inp->restart));
caseinit_update_left_vars (inp->init, c);
}
while (inp->restart < 0);
- return true;
+ return c;
}
static void
/* Outputs the current case */
int
-end_case_trns_proc (void *inp_, struct ccase *c UNUSED,
+end_case_trns_proc (void *inp_, struct ccase **c UNUSED,
casenumber case_nr UNUSED)
{
struct input_program_pgm *inp = inp_;
/* Executes a REREAD transformation. */
static int
-reread_trns_proc (void *t_, struct ccase *c, casenumber case_num)
+reread_trns_proc (void *t_, struct ccase **c, casenumber case_num)
{
struct reread_trns *t = t_;
dfm_reread_record (t->reader, 1);
else
{
- double column = expr_evaluate_num (t->column, c, case_num);
+ double column = expr_evaluate_num (t->column, *c, case_num);
if (!isfinite (column) || column < 1)
{
msg (SE, _("REREAD: Column numbers must be positive finite "
/* Executes an END FILE transformation. */
static int
-end_file_trns_proc (void *trns_ UNUSED, struct ccase *c UNUSED,
+end_file_trns_proc (void *trns_ UNUSED, struct ccase **c UNUSED,
casenumber case_num UNUSED)
{
return TRNS_END_FILE;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 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
static void write_line (struct outp_driver *d, const char *s);
/* Other functions. */
-static void list_case (struct ccase *, casenumber case_idx,
+static void list_case (const struct ccase *, casenumber case_idx,
const struct dataset *);
static void determine_layout (void);
static void clean_up (void);
casegrouper_get_next_group (grouper, &group);
casereader_destroy (group))
{
- struct ccase c;
+ struct ccase *c;
write_all_headers (group, ds);
- for (; casereader_read (group, &c); case_destroy (&c))
+ for (; (c = casereader_read (group)) != NULL; case_unref (c))
{
case_idx++;
if (case_idx >= cmd.first && case_idx <= cmd.last
&& (case_idx - cmd.first) % cmd.step == 0)
- list_case (&c, case_idx, ds);
+ list_case (c, case_idx, ds);
}
}
ok = casegrouper_destroy (grouper);
write_all_headers (struct casereader *input, const struct dataset *ds)
{
struct outp_driver *d;
- struct ccase c;
+ struct ccase *c;
- if (!casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c == NULL)
return;
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
for (d = outp_drivers (NULL); d; d = outp_drivers (d))
{
/* Writes case C to output. */
static void
-list_case (struct ccase *c, casenumber case_idx, const struct dataset *ds)
+list_case (const struct ccase *c, casenumber case_idx,
+ const struct dataset *ds)
{
struct dictionary *dict = dataset_dict (ds);
struct outp_driver *d;
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 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
/* Executes a PRINT SPACE transformation. */
static int
-print_space_trns_proc (void *t_, struct ccase *c,
+print_space_trns_proc (void *t_, struct ccase **c,
casenumber case_num UNUSED)
{
struct print_space_trns *trns = t_;
n = 1;
if (trns->expr)
{
- double f = expr_evaluate_num (trns->expr, c, case_num);
+ double f = expr_evaluate_num (trns->expr, *c, case_num);
if (f == SYSMIS)
msg (SW, _("The expression on PRINT SPACE evaluated to the "
"system-missing value."));
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 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
/* Performs the transformation inside print_trns T on case C. */
static int
-print_trns_proc (void *trns_, struct ccase *c, casenumber case_num UNUSED)
+print_trns_proc (void *trns_, struct ccase **c, casenumber case_num UNUSED)
{
struct print_trns *trns = trns_;
bool eject = trns->eject;
ds_set_length (&trns->line, spec->first_column, encoded_space);
if (spec->type == PRT_VAR)
{
- const union value *input = case_data (c, spec->var);
+ const union value *input = case_data (*c, spec->var);
char *output = ds_put_uninit (&trns->line, spec->format.w);
if (!spec->sysmis_as_spaces || input->f != SYSMIS)
data_out_legacy (input, trns->encoding, &spec->format, output);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2008, 2009 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
return NULL;
}
-/* Writes case C to the system file specified on XSAVE or XEXPORT. */
+/* Writes case *C to the system file specified on XSAVE or XEXPORT. */
static int
-output_trns_proc (void *trns_, struct ccase *c, casenumber case_num UNUSED)
+output_trns_proc (void *trns_, struct ccase **c, casenumber case_num UNUSED)
{
struct output_trns *t = trns_;
- struct ccase tmp;
- case_clone (&tmp, c);
- casewriter_write (t->writer, &tmp);
+ casewriter_write (t->writer, case_ref (*c));
return TRNS_CONTINUE;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 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
}
if (c == NULL)
- {
- c = xmalloc (sizeof *c);
- case_create (c, dict_get_next_value_idx (d));
- }
+ c = case_create (dict_get_next_value_idx (d));
else
- case_resize (c, dict_get_next_value_idx (d));
+ c = case_resize (c, dict_get_next_value_idx (d));
if (lex_is_number (lexer))
case_data_rw (c, v)->f = lex_tokval (lexer);
if (ds)
destroy_dataset (ds);
- if (c != NULL)
- {
- case_destroy (c);
- free (c);
- }
+ case_unref (c);
return retval;
}
// -*- c -*-
//
// PSPP - a program for statistical analysis.
-// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+// Copyright (C) 2005, 2006, 2009 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
no_opt perm_only function LAG (num_var v, pos_int n_before)
dataset ds;
{
- struct ccase *c = lagged_case (ds, n_before);
+ const struct ccase *c = lagged_case (ds, n_before);
if (c != NULL)
{
double x = case_num (c, v);
no_opt perm_only function LAG (num_var v)
dataset ds;
{
- struct ccase *c = lagged_case (ds, 1);
+ const struct ccase *c = lagged_case (ds, 1);
if (c != NULL)
{
double x = case_num (c, v);
expression e;
dataset ds;
{
- struct ccase *c = lagged_case (ds, n_before);
+ const struct ccase *c = lagged_case (ds, n_before);
if (c != NULL)
return copy_string (e, case_str (c, v), var_get_width (v));
else
expression e;
dataset ds;
{
- struct ccase *c = lagged_case (ds, 1);
+ const struct ccase *c = lagged_case (ds, 1);
if (c != NULL)
return copy_string (e, case_str (c, v), var_get_width (v));
else
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2008, 2009 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
struct subcase sort; /* Sort criteria (break variables). */
const struct variable **break_vars; /* Break variables. */
size_t break_var_cnt; /* Number of break variables. */
- struct ccase break_case; /* Last values of break variables. */
+ struct ccase *break_case; /* Last values of break variables. */
enum missing_treatment missing; /* How to treat missing values. */
struct agr_var *agr_vars; /* First aggregate variable. */
memset(&agr, 0 , sizeof (agr));
agr.missing = ITEMWISE;
- case_nullify (&agr.break_case);
+ agr.break_case = NULL;
agr.dict = dict_create ();
agr.src_dict = dict;
casegrouper_get_next_group (grouper, &group);
casereader_destroy (group))
{
- struct ccase c;
-
- if (!casereader_peek (group, 0, &c))
+ struct ccase *c = casereader_peek (group, 0);
+ if (c == NULL)
{
casereader_destroy (group);
continue;
}
- initialize_aggregate_info (&agr, &c);
- case_destroy (&c);
+ initialize_aggregate_info (&agr, c);
+ case_unref (c);
- for (; casereader_read (group, &c); case_destroy (&c))
- accumulate_aggregate_info (&agr, &c);
+ for (; (c = casereader_read (group)) != NULL; case_unref (c))
+ accumulate_aggregate_info (&agr, c);
dump_aggregate_info (&agr, output);
}
if (!casegrouper_destroy (grouper))
subcase_destroy (&agr->sort);
free (agr->break_vars);
- case_destroy (&agr->break_case);
+ case_unref (agr->break_case);
for (iter = agr->agr_vars; iter; iter = next)
{
next = iter->next;
case MEDIAN:
{
double wv ;
- struct ccase cout;
- case_create (&cout, 2);
+ struct ccase *cout = case_create (2);
- case_data_rw (&cout, iter->subject)->f =
- case_data (input, iter->src)->f;
+ case_data_rw (cout, iter->subject)->f
+ = case_data (input, iter->src)->f;
wv = dict_get_case_weight (agr->src_dict, input, NULL);
- case_data_rw (&cout, iter->weight)->f = wv;
+ case_data_rw (cout, iter->weight)->f = wv;
iter->cc += wv;
- casewriter_write (iter->writer, &cout);
- case_destroy (&cout);
+ casewriter_write (iter->writer, cout);
}
break;
case SD:
static void
dump_aggregate_info (struct agr_proc *agr, struct casewriter *output)
{
- struct ccase c;
-
- case_create (&c, dict_get_next_value_idx (agr->dict));
+ struct ccase *c = case_create (dict_get_next_value_idx (agr->dict));
{
int value_idx = 0;
{
const struct variable *v = agr->break_vars[i];
size_t value_cnt = var_get_value_cnt (v);
- memcpy (case_data_rw_idx (&c, value_idx),
- case_data (&agr->break_case, v),
+ memcpy (case_data_rw_idx (c, value_idx),
+ case_data (agr->break_case, v),
sizeof (union value) * value_cnt);
value_idx += value_cnt;
}
for (i = agr->agr_vars; i; i = i->next)
{
- union value *v = case_data_rw (&c, i->dest);
+ union value *v = case_data_rw (c, i->dest);
if (agr->missing == COLUMNWISE && i->saw_missing
}
}
- casewriter_write (output, &c);
+ casewriter_write (output, c);
}
/* Resets the state for all the aggregate functions. */
{
struct agr_var *iter;
- case_destroy (&agr->break_case);
- case_clone (&agr->break_case, input);
+ case_unref (agr->break_case);
+ agr->break_case = case_ref (input);
for (iter = agr->agr_vars; iter; iter = iter->next)
{
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
{
struct autorecode_pgm arc;
struct casereader *input;
- struct ccase c;
+ struct ccase *c;
size_t dst_cnt;
size_t i;
bool ok;
}
input = proc_open (ds);
- for (; casereader_read (input, &c); case_destroy (&c))
+ for (; (c = casereader_read (input)) != NULL; case_unref (c))
for (i = 0; i < arc.var_cnt; i++)
{
union arc_value v, *vp, **vpp;
if (var_is_numeric (arc.src_vars[i]))
- v.f = case_num (&c, arc.src_vars[i]);
+ v.f = case_num (c, arc.src_vars[i]);
else
- v.c = (char *) case_str (&c, arc.src_vars[i]);
+ v.c = (char *) case_str (c, arc.src_vars[i]);
vpp = (union arc_value **) hsh_probe (arc.src_values[i], &v);
if (*vpp == NULL)
/* Executes an AUTORECODE transformation. */
static int
-autorecode_trns_proc (void *trns_, struct ccase *c, casenumber case_idx UNUSED)
+autorecode_trns_proc (void *trns_, struct ccase **c,
+ casenumber case_idx UNUSED)
{
struct autorecode_trns *trns = trns_;
size_t i;
+ *c = case_unshare (*c);
for (i = 0; i < trns->spec_cnt; i++)
{
struct arc_spec *spec = &trns->specs[i];
union arc_value v;
if (var_is_numeric (spec->src))
- v.f = case_num (c, spec->src);
+ v.f = case_num (*c, spec->src);
else
- v.c = (char *) case_str (c, spec->src);
+ v.c = (char *) case_str (*c, spec->src);
item = hsh_force_find (spec->items, &v);
- case_data_rw (c, spec->dest)->f = item->to;
+ case_data_rw (*c, spec->dest)->f = item->to;
}
return TRNS_CONTINUE;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 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
bool warn = true;
const struct one_sample_test *ost = (const struct one_sample_test *) bst;
- struct ccase c;
+ struct ccase *c;
- while (casereader_read(input, &c))
+ while ((c = casereader_read(input)) != NULL)
{
int v;
- double w = dict_get_case_weight (dict, &c, &warn);
+ double w = dict_get_case_weight (dict, c, &warn);
for (v = 0 ; v < ost->n_vars ; ++v )
{
const struct variable *var = ost->vars[v];
- const union value *value = case_data (&c, var);
+ const union value *value = case_data (c, var);
int width = var_get_width (var);
if (var_is_value_missing (var, value, exclude))
msg (ME, _("Variable %s is not dichotomous"), var_get_name (var));
}
- case_destroy (&c);
+ case_unref (c);
}
return casereader_destroy (input);
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2007, 2009 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
{
bool warn = true;
float i_d;
- struct ccase c;
+ struct ccase *c;
struct hsh_table *freq_hash =
hsh_create (4, compare_freq, hash_freq,
hsh_insert (freq_hash, fr);
}
- while (casereader_read (input, &c))
+ while ((c = casereader_read (input)) != NULL)
{
union value obs_value;
struct freq **existing_fr;
struct freq *fr = xmalloc(sizeof (*fr));
- fr->value = case_data (&c, var);
+ fr->value = case_data (c, var);
- fr->count = dict_get_case_weight (dict, &c, &warn);
+ fr->count = dict_get_case_weight (dict, c, &warn);
obs_value.f = trunc (fr->value->f);
if ( obs_value.f < lo || obs_value.f > hi)
{
free (fr);
- case_destroy (&c);
+ case_unref (c);
continue;
}
(*existing_fr)->count += fr->count;
free (fr);
- case_destroy (&c);
+ case_unref (c);
}
if (casereader_destroy (input))
return freq_hash;
const struct variable *var)
{
bool warn = true;
- struct ccase c;
+ struct ccase *c;
struct hsh_table *freq_hash =
hsh_create (4, compare_freq, hash_freq,
free_freq_mutable_hash,
(void *) var);
- for (; casereader_read (input, &c); case_destroy (&c))
+ for (; (c = casereader_read (input)) != NULL; case_unref (c))
{
struct freq **existing_fr;
struct freq *fr = xmalloc(sizeof (*fr));
- fr->value = case_data (&c, var);
+ fr->value = case_data (c, var);
- fr->count = dict_get_case_weight (dict, &c, &warn);
+ fr->count = dict_get_case_weight (dict, c, &warn);
existing_fr = (struct freq **) hsh_probe (freq_hash, fr);
if ( *existing_fr)
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 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
static int internal_cmd_crosstabs (struct lexer *lexer, struct dataset *ds);
static void precalc (struct casereader *, const struct dataset *);
-static void calc_general (struct ccase *, const struct dataset *);
-static void calc_integer (struct ccase *, const struct dataset *);
+static void calc_general (const struct ccase *, const struct dataset *);
+static void calc_integer (const struct ccase *, const struct dataset *);
static void postcalc (void);
static void submit (struct tab_table *);
grouper = casegrouper_create_splits (input, dataset_dict (ds));
while (casegrouper_get_next_group (grouper, &group))
{
- struct ccase c;
+ struct ccase *c;
precalc (group, ds);
- for (; casereader_read (group, &c); case_destroy (&c))
+ for (; (c = casereader_read (group)) != NULL; case_unref (c))
{
if (mode == GENERAL)
- calc_general (&c, ds);
+ calc_general (c, ds);
else
- calc_integer (&c, ds);
+ calc_integer (c, ds);
}
casereader_destroy (group);
static void
precalc (struct casereader *input, const struct dataset *ds)
{
- struct ccase c;
+ struct ccase *c;
- if (casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c != NULL)
{
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
}
if (mode == GENERAL)
/* Form crosstabulations for general mode. */
static void
-calc_general (struct ccase *c, const struct dataset *ds)
+calc_general (const struct ccase *c, const struct dataset *ds)
{
/* Missing values to exclude. */
enum mv_class exclude = (cmd.miss == CRS_TABLE ? MV_ANY
}
static void
-calc_integer (struct ccase *c, const struct dataset *ds)
+calc_integer (const struct ccase *c, const struct dataset *ds)
{
bool bad_warn = true;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
(either system or user-missing values that weren't included).
*/
static int
-descriptives_trns_proc (void *trns_, struct ccase * c,
+descriptives_trns_proc (void *trns_, struct ccase **c,
casenumber case_idx UNUSED)
{
struct dsc_trns *t = trns_;
assert(t->vars);
for (vars = t->vars; vars < t->vars + t->var_cnt; vars++)
{
- double score = case_num (c, *vars);
+ double score = case_num (*c, *vars);
if (var_is_num_missing (*vars, score, t->exclude))
{
all_sysmis = 1;
}
}
+ *c = case_unshare (*c);
for (z = t->z_scores; z < t->z_scores + t->z_score_cnt; z++)
{
- double input = case_num (c, z->src_var);
- double *output = &case_data_rw (c, z->z_var)->f;
+ double input = case_num (*c, z->src_var);
+ double *output = &case_data_rw (*c, z->z_var)->f;
if (z->mean == SYSMIS || z->std_dev == SYSMIS || all_sysmis
|| var_is_num_missing (z->src_var, input, t->exclude))
struct dataset *ds)
{
struct casereader *pass1, *pass2;
- struct ccase c;
+ struct ccase *c;
size_t i;
- if (!casereader_peek (group, 0, &c))
+ c = casereader_peek (group, 0);
+ if (c == NULL)
{
casereader_destroy (group);
return;
}
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
group = casereader_create_filter_weight (group, dataset_dict (ds),
NULL, NULL);
dsc->valid = 0.;
/* First pass to handle most of the work. */
- for (; casereader_read (pass1, &c); case_destroy (&c))
+ for (; (c = casereader_read (pass1)) != NULL; case_unref (c))
{
- double weight = dict_get_case_weight (dataset_dict (ds), &c, NULL);
+ double weight = dict_get_case_weight (dataset_dict (ds), c, NULL);
/* Check for missing values. */
- if (listwise_missing (dsc, &c))
+ if (listwise_missing (dsc, c))
{
dsc->missing_listwise += weight;
if (dsc->missing_type == DSC_LISTWISE)
for (i = 0; i < dsc->var_cnt; i++)
{
struct dsc_var *dv = &dsc->vars[i];
- double x = case_num (&c, dv->v);
+ double x = case_num (c, dv->v);
if (var_is_num_missing (dv->v, x, dsc->exclude))
{
/* Second pass for higher-order moments. */
if (dsc->max_moment > MOMENT_MEAN)
{
- for (; casereader_read (pass2, &c); case_destroy (&c))
+ for (; (c = casereader_read (pass2)) != NULL; case_unref (c))
{
- double weight = dict_get_case_weight (dataset_dict (ds), &c, NULL);
+ double weight = dict_get_case_weight (dataset_dict (ds), c, NULL);
/* Check for missing values. */
- if (dsc->missing_type == DSC_LISTWISE && listwise_missing (dsc, &c))
+ if (dsc->missing_type == DSC_LISTWISE && listwise_missing (dsc, c))
continue;
for (i = 0; i < dsc->var_cnt; i++)
{
struct dsc_var *dv = &dsc->vars[i];
- double x = case_num (&c, dv->v);
+ double x = case_num (c, dv->v);
if (var_is_num_missing (dv->v, x, dsc->exclude))
continue;
/* PSPP - a program for statistical analysis.
- Copyright (C) 2004, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2008, 2009 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
chart_write_yscale (dnp_chart, np->dns_min, np->dns_max, 5);
{
- struct ccase c;
struct casereader *reader = casewriter_make_reader (np->writer);
- while (casereader_read (reader, &c))
+ struct ccase *c;
+ while ((c = casereader_read (reader)) != NULL)
{
- chart_datum (np_chart, 0, case_data_idx (&c, NP_IDX_Y)->f, case_data_idx (&c, NP_IDX_NS)->f);
- chart_datum (dnp_chart, 0, case_data_idx (&c, NP_IDX_Y)->f, case_data_idx (&c, NP_IDX_DNS)->f);
+ chart_datum (np_chart, 0, case_data_idx (c, NP_IDX_Y)->f, case_data_idx (c, NP_IDX_NS)->f);
+ chart_datum (dnp_chart, 0, case_data_idx (c, NP_IDX_Y)->f, case_data_idx (c, NP_IDX_DNS)->f);
- case_destroy (&c);
+ case_unref (c);
}
casereader_destroy (reader);
}
examine_group (struct cmd_examine *cmd, struct casereader *reader, int level,
const struct dictionary *dict, struct xfactor *factor)
{
- struct ccase c;
+ struct ccase *c;
const struct variable *wv = dict_get_weight (dict);
int v;
int n_extrema = 1;
n_extrema = cmd->st_n;
- if (casereader_peek (reader, 0, &c))
+ c = casereader_peek (reader, 0);
+ if (c != NULL)
{
if ( level > 0)
{
result->value[0] =
- value_dup (case_data (&c, factor->indep_var[0]),
+ value_dup (case_data (c, factor->indep_var[0]),
var_get_width (factor->indep_var[0]));
if ( level > 1)
result->value[1] =
- value_dup (case_data (&c, factor->indep_var[1]),
+ value_dup (case_data (c, factor->indep_var[1]),
var_get_width (factor->indep_var[1]));
}
- case_destroy (&c);
+ case_unref (c);
}
for (v = 0; v < n_dependent_vars; ++v)
/* Sort or just iterate, whilst calculating moments etc */
- while (casereader_read (input, &c))
+ while ((c = casereader_read (input)) != NULL)
{
const casenumber loc =
- case_data_idx (&c, casereader_get_value_cnt (reader) - 1)->f;
+ case_data_idx (c, casereader_get_value_cnt (reader) - 1)->f;
- const double weight = wv ? case_data (&c, wv)->f : 1.0;
+ const double weight = wv ? case_data (c, wv)->f : 1.0;
if (weight != SYSMIS)
minimize (&result->metrics[v].cmin, weight);
moments1_add (result->metrics[v].moments,
- case_data (&c, dependent_vars[v])->f,
+ case_data (c, dependent_vars[v])->f,
weight);
result->metrics[v].n += weight;
extrema_add (result->metrics[v].maxima,
- case_data (&c, dependent_vars[v])->f,
+ case_data (c, dependent_vars[v])->f,
weight,
loc);
extrema_add (result->metrics[v].minima,
- case_data (&c, dependent_vars[v])->f,
+ case_data (c, dependent_vars[v])->f,
weight,
loc);
- casewriter_write (writer, &c);
+ casewriter_write (writer, c);
}
casereader_destroy (input);
result->metrics[v].up_reader = casewriter_make_reader (writer);
/* FIXME: Do this in the above loop */
if ( cmd->a_plot[XMN_PLT_HISTOGRAM] )
{
- struct ccase c;
+ struct ccase *c;
struct casereader *input = casereader_clone (reader);
for (v = 0; v < n_dependent_vars; ++v)
metric->histogram = histogram_create (10, min->value, max->value);
}
- while (casereader_read (input, &c))
+ while ((c = casereader_read (input)) != NULL)
{
- const double weight = wv ? case_data (&c, wv)->f : 1.0;
+ const double weight = wv ? case_data (c, wv)->f : 1.0;
for (v = 0; v < n_dependent_vars; ++v)
{
struct factor_metrics *metric = &result->metrics[v];
if ( metric->histogram)
histogram_add ((struct histogram *) metric->histogram,
- case_data (&c, dependent_vars[v])->f, weight);
+ case_data (c, dependent_vars[v])->f, weight);
}
- case_destroy (&c);
+ case_unref (c);
}
casereader_destroy (input);
}
{
struct ll *ll;
const struct dictionary *dict = dataset_dict (ds);
- struct ccase c;
+ struct ccase *c;
struct casereader *level0 = casereader_clone (input);
- if (!casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c == NULL)
{
casereader_destroy (input);
return;
}
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
ll_init (&level0_factor.result_list);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
struct flip_pgm *flip;
struct casereader *input, *reader;
union value *output_buf;
- struct ccase c;
+ struct ccase *c;
size_t i;
bool ok;
proc_discard_output (ds);
input = proc_open (ds);
- while (casereader_read (input, &c))
+ while ((c = casereader_read (input)) != NULL)
{
- write_flip_case (flip, &c);
- case_destroy (&c);
+ write_flip_case (flip, c);
+ case_unref (c);
}
ok = casereader_destroy (input);
ok = proc_commit (ds) && ok;
return true;
}
-/* Reads one case into C.
- Returns true if successful, false at end of file or if an
- I/O error occurred. */
-static bool
-flip_casereader_read (struct casereader *reader UNUSED, void *flip_,
- struct ccase *c)
+/* Reads and returns one case.
+ Returns a null pointer at end of file or if an I/O error occurred. */
+static struct ccase *
+flip_casereader_read (struct casereader *reader UNUSED, void *flip_)
{
struct flip_pgm *flip = flip_;
+ struct ccase *c;
size_t i;
if (flip->error || flip->cases_read >= flip->var_cnt)
- return false;
+ return NULL;
- case_create (c, flip->case_cnt);
+ c = case_create (flip->case_cnt);
for (i = 0; i < flip->case_cnt; i++)
{
double in;
if (fread (&in, sizeof in, 1, flip->file) != 1)
{
- case_destroy (c);
+ case_unref (c);
if (ferror (flip->file))
msg (SE, _("Error reading FLIP temporary file: %s."),
strerror (errno));
else
NOT_REACHED ();
flip->error = true;
- return false;
+ return NULL;
}
case_data_rw_idx (c, i)->f = in;
}
flip->cases_read++;
- return true;
+ return c;
}
/* Destroys the source.
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2007, 2009 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
for (; casegrouper_get_next_group (grouper, &group);
casereader_destroy (group))
{
- struct ccase c;
+ struct ccase *c;
precalc (group, ds);
- for (; casereader_read (group, &c); case_destroy (&c))
- calc (&c, ds);
+ for (; (c = casereader_read (group)) != NULL; case_unref (c))
+ calc (c, ds);
postcalc ();
}
ok = casegrouper_destroy (grouper);
static void
precalc (struct casereader *input, struct dataset *ds)
{
- struct ccase c;
+ struct ccase *c;
size_t i;
- if (casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c != NULL)
{
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
}
pool_destroy (data_pool);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
int n_indep = 0;
pspp_linreg_cache *model = NULL;
pspp_linreg_opts lopts;
- struct ccase c;
+ struct ccase *c;
size_t i;
size_t n_all_vars;
size_t n_data; /* Number of valid cases. */
struct casereader *reader;
struct covariance_matrix *cov;
- if (!casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c == NULL)
{
casereader_destroy (input);
return true;
}
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
if (!v_dependent)
{
cov = covariance_matrix_init (n_all_vars, all_vars, ONE_PASS, PAIRWISE, MV_ANY);
reader = casereader_create_counter (reader, &row, -1);
- for (; casereader_read (reader, &c); case_destroy (&c))
+ for (; (c = casereader_read (reader)) != NULL; case_unref (c))
{
/*
Accumulate the covariance matrix.
*/
- covariance_matrix_accumulate (cov, &c);
+ covariance_matrix_accumulate (cov, c);
n_data++;
}
covariance_matrix_compute (cov);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 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
double maximum = -DBL_MAX;
double var;
struct moments1 *moments = moments1_create (MOMENT_VARIANCE);
- struct ccase c;
+ struct ccase *c;
const struct variable *v = *vv++;
struct casereader *pass;
&v, 1,
filter, NULL, NULL);
pass = casereader_create_filter_weight (pass, dict, NULL, NULL);
- while (casereader_read(pass, &c))
+ while ((c = casereader_read (pass)) != NULL)
{
- double val = case_num (&c, v);
- double w = dict_get_case_weight (dict, &c, NULL);
+ double val = case_num (c, v);
+ double w = dict_get_case_weight (dict, c, NULL);
minimum = MIN (minimum, val);
maximum = MAX (maximum, val);
moments1_add (moments, val, w);
- case_destroy (&c);
+ case_unref (c);
}
casereader_destroy (pass);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2007, 2009 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
struct dictionary *dict = dataset_dict (ds);
enum mv_class exclude;
struct casereader *reader;
- struct ccase c;
+ struct ccase *c;
- if (!casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c == NULL)
{
casereader_destroy (input);
return;
}
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
taint = taint_clone (casereader_get_taint (input));
input = casereader_create_filter_weight (input, dict, NULL, NULL);
reader = casereader_clone (input);
- for (; casereader_read (reader, &c); case_destroy (&c))
+ for (; (c = casereader_read (reader)) != NULL; case_unref (c))
{
size_t i;
- const double weight = dict_get_case_weight (dict, &c, NULL);
+ const double weight = dict_get_case_weight (dict, c, NULL);
- const union value *indep_val = case_data (&c, indep_var);
+ const union value *indep_val = case_data (c, indep_var);
void **p = hsh_probe (global_group_hash, indep_val);
if (*p == NULL)
*p = value_dup (indep_val, var_get_width (indep_var));
{
const struct variable *v = vars[i];
- const union value *val = case_data (&c, v);
+ const union value *val = case_data (c, v);
struct group_proc *gp = group_proc_get (vars[i]);
struct hsh_table *group_hash = gp->group_hash;
/* PSPP - a program for statistical analysis.
- Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006, 2007, 2009 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
{
struct casereader *pass1, *pass2, *pass2_1;
struct casegrouper *tie_grouper;
- struct ccase c;
+ struct ccase *c;
double w = 0.0;
double cc = 0.0;
int tie_group = 1;
casereader_split (input, &pass1, &pass2);
/* Pass 1: Get total group weight. */
- for (; casereader_read (pass1, &c); case_destroy (&c))
- w += dict_get_case_weight (dict, &c, NULL);
+ for (; (c = casereader_read (pass1)) != NULL; case_unref (c))
+ w += dict_get_case_weight (dict, c, NULL);
casereader_destroy (pass1);
/* Pass 2: Do ranking. */
casewriter_get_taint (output));
/* Pass 2.1: Sum up weight for tied cases. */
- for (; casereader_read (pass2_1, &c); case_destroy (&c))
- tw += dict_get_case_weight (dict, &c, NULL);
+ for (; (c = casereader_read (pass2_1)) != NULL; case_unref (c))
+ tw += dict_get_case_weight (dict, c, NULL);
cc += tw;
casereader_destroy (pass2_1);
/* Pass 2.2: Rank tied cases. */
- while (casereader_read (pass2_2, &c))
+ while ((c = casereader_read (pass2_2)) != NULL)
{
+ c = case_unshare (c);
for (i = 0; i < n_rank_specs; ++i)
{
const struct variable *dst_var = rs[i].destvars[dest_idx];
- double *dst_value = &case_data_rw (&c, dst_var)->f;
+ double *dst_value = &case_data_rw (c, dst_var)->f;
*dst_value = rank_func[rs[i].rfunc] (tw, cc, cc_1, tie_group, w);
}
- casewriter_write (output, &c);
+ casewriter_write (output, c);
}
casereader_destroy (pass2_2);
/* Transformation function to enumerate all the cases */
static int
-create_resort_key (void *key_var_, struct ccase *cc, casenumber case_num)
+create_resort_key (void *key_var_, struct ccase **cc, casenumber case_num)
{
struct variable *key_var = key_var_;
- case_data_rw(cc, key_var)->f = case_num;
+ *cc = case_unshare (*cc);
+ case_data_rw (*cc, key_var)->f = case_num;
return TRNS_CONTINUE;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2009 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
Gets the predicted values.
*/
static int
-regression_trns_pred_proc (void *t_, struct ccase *c,
+regression_trns_pred_proc (void *t_, struct ccase **c,
casenumber case_idx UNUSED)
{
size_t i;
n_vals = (*model->get_vars) (model, vars);
vals = xnmalloc (n_vals, sizeof (*vals));
- output = case_data_rw (c, model->pred);
- assert (output != NULL);
+ *c = case_unshare (*c);
+ output = case_data_rw (*c, model->pred);
for (i = 0; i < n_vals; i++)
{
- vals[i] = case_data (c, vars[i]);
+ vals[i] = case_data (*c, vars[i]);
}
output->f = (*model->predict) ((const struct variable **) vars,
vals, model, n_vals);
Gets the residuals.
*/
static int
-regression_trns_resid_proc (void *t_, struct ccase *c,
+regression_trns_resid_proc (void *t_, struct ccase **c,
casenumber case_idx UNUSED)
{
size_t i;
n_vals = (*model->get_vars) (model, vars);
vals = xnmalloc (n_vals, sizeof (*vals));
- output = case_data_rw (c, model->resid);
+ *c = case_unshare (*c);
+ output = case_data_rw (*c, model->resid);
assert (output != NULL);
for (i = 0; i < n_vals; i++)
{
- vals[i] = case_data (c, vars[i]);
+ vals[i] = case_data (*c, vars[i]);
}
- obs = case_data (c, model->depvar);
+ obs = case_data (*c, model->depvar);
output->f = (*model->residual) ((const struct variable **) vars,
vals, obs, model, n_vals);
free (vals);
struct moments_var *mom)
{
int n_data;
- struct ccase c;
+ struct ccase *c;
size_t i;
assert (vars != NULL);
cat_stored_values_create (vars[i]);
n_data = 0;
- for (; casereader_read (input, &c); case_destroy (&c))
+ for (; (c = casereader_read (input)) != NULL; case_unref (c))
{
/*
The second condition ensures the program will run even if
*/
for (i = 0; i < n_vars; i++)
{
- const union value *val = case_data (&c, vars[i]);
+ const union value *val = case_data (c, vars[i]);
if (var_is_alpha (vars[i]))
cat_value_update (vars[i], val);
else
size_t i;
int n_indep = 0;
int k;
- struct ccase c;
+ struct ccase *c;
const struct variable **indep_vars;
struct design_matrix *X;
struct moments_var *mom;
assert (models != NULL);
- if (!casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c == NULL)
{
casereader_destroy (input);
return true;
}
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
if (!v_variables)
{
const struct variable *dep_var;
struct casereader *reader;
casenumber row;
- struct ccase c;
+ struct ccase *c;
size_t n_data; /* Number of valid cases. */
dep_var = cmd->v_dependent[k];
The second pass fills the design matrix.
*/
reader = casereader_create_counter (reader, &row, -1);
- for (; casereader_read (reader, &c); case_destroy (&c))
+ for (; (c = casereader_read (reader)) != NULL; case_unref (c))
{
for (i = 0; i < n_indep; ++i)
{
const struct variable *v = indep_vars[i];
- const union value *val = case_data (&c, v);
+ const union value *val = case_data (c, v);
if (var_is_alpha (v))
design_matrix_set_categorical (X, row, v, val);
else
design_matrix_set_numeric (X, row, v, val);
}
- gsl_vector_set (Y, row, case_num (&c, dep_var));
+ gsl_vector_set (Y, row, case_num (c, dep_var));
}
/*
Now that we know the number of coefficients, allocate space
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 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
{
int i;
int si;
- struct ccase c;
+ struct ccase *c;
casenumber n_missing ;
casenumber n_valid = 0;
s, NULL);
}
- for (; casereader_read (input, &c); case_destroy (&c))
+ for (; (c = casereader_read (input)) != NULL; case_unref (c))
{
double weight = 1.0;
n_valid ++;
struct cronbach *s = &rel->sc[si];
for (i = 0 ; i < s->n_items ; ++i )
- moments1_add (s->m[i], case_data (&c, s->items[i])->f, weight);
+ moments1_add (s->m[i], case_data (c, s->items[i])->f, weight);
- moments1_add (s->total, case_data_idx (&c, s->totals_idx)->f, weight);
+ moments1_add (s->total, case_data_idx (c, s->totals_idx)->f, weight);
}
}
casereader_destroy (input);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
struct casereader *pass1, *pass2, *pass3;
struct taint *taint;
- struct ccase c;
+ struct ccase *c;
enum mv_class exclude = cmd->miss != TTS_INCLUDE ? MV_ANY : MV_SYSTEM;
- if (!casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c == NULL)
{
casereader_destroy (input);
return;
}
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
if ( cmd->miss == TTS_LISTWISE )
input = casereader_create_filter_missing (input,
casereader_split (input, &pass1, &pass2);
common_precalc (cmd);
- for (; casereader_read (pass1, &c); case_destroy (&c))
- common_calc (dict, &c, cmd, exclude);
+ for (; (c = casereader_read (pass1)) != NULL; case_unref (c))
+ common_calc (dict, c, cmd, exclude);
casereader_destroy (pass1);
common_postcalc (cmd);
{
case T_1_SAMPLE:
one_sample_precalc (cmd);
- for (; casereader_read (pass2, &c); case_destroy (&c))
- one_sample_calc (dict, &c, cmd, exclude);
+ for (; (c = casereader_read (pass2)) != NULL; case_unref (c))
+ one_sample_calc (dict, c, cmd, exclude);
one_sample_postcalc (cmd);
break;
case T_PAIRED:
paired_precalc (cmd);
- for (; casereader_read (pass2, &c); case_destroy (&c))
- paired_calc (dict, &c, cmd, exclude);
+ for (; (c = casereader_read (pass2)) != NULL; case_unref (c))
+ paired_calc (dict, c, cmd, exclude);
paired_postcalc (cmd);
break;
case T_IND_SAMPLES:
pass3 = casereader_clone (pass2);
group_precalc (cmd);
- for (; casereader_read (pass2, &c); case_destroy (&c))
- group_calc (dict, &c, cmd, exclude);
+ for (; (c = casereader_read (pass2)) != NULL; case_unref (c))
+ group_calc (dict, c, cmd, exclude);
group_postcalc (cmd);
levene (dict, pass3, indep_var, cmd->n_variables, cmd->v_variables,
/* Pspp - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 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
{
struct casereader *r = casereader_clone (input);
struct casewriter *writer;
- struct ccase c;
+ struct ccase *c;
struct subcase ordering;
variable_pair *vp = &t2s->pairs[i];
writer = sort_create_writer (&ordering, reader_width);
subcase_destroy (&ordering);
- while (casereader_read (r, &c))
+ for (; (c = casereader_read (r)) != NULL; case_unref (c))
{
- struct ccase output;
- double d = append_difference (&c, 0, vp);
-
- case_create (&output, reader_width);
+ struct ccase *output = case_create (reader_width);
+ double d = append_difference (c, 0, vp);
if (d > 0)
{
- case_data_rw (&output, ws[i].sign)->f = 1.0;
+ case_data_rw (output, ws[i].sign)->f = 1.0;
}
else if (d < 0)
{
- case_data_rw (&output, ws[i].sign)->f = -1.0;
+ case_data_rw (output, ws[i].sign)->f = -1.0;
}
else
{
double w = 1.0;
if (weight)
- w = case_data (&c, weight)->f;
+ w = case_data (c, weight)->f;
/* Central point values should be dropped */
ws[i].n_zeros += w;
- case_destroy (&c);
- continue;
+ continue;
}
- case_data_rw (&output, ws[i].absdiff)->f = fabs (d);
+ case_data_rw (output, ws[i].absdiff)->f = fabs (d);
if (weight)
- case_data_rw (&output, weightx)->f = case_data (&c, weight)->f;
+ case_data_rw (output, weightx)->f = case_data (c, weight)->f;
- casewriter_write (writer, &output);
- case_destroy (&c);
+ casewriter_write (writer, output);
}
casereader_destroy (r);
ws[i].reader = casewriter_make_reader (writer);
for (i = 0 ; i < t2s->n_pairs; ++i )
{
struct casereader *rr ;
- struct ccase c;
+ struct ccase *c;
enum rank_error err = 0;
rr = casereader_create_append_rank (ws[i].reader, ws[i].absdiff,
distinct_callback, &ws[i]
);
- while (casereader_read (rr, &c))
+ for (; (c = casereader_read (rr)) != NULL; case_unref (c))
{
- double sign = case_data (&c, ws[i].sign)->f;
- double rank = case_data_idx (&c, weight ? 3 : 2)->f;
+ double sign = case_data (c, ws[i].sign)->f;
+ double rank = case_data_idx (c, weight ? 3 : 2)->f;
double w = 1.0;
if (weight)
- w = case_data (&c, weightx)->f;
+ w = case_data (c, weightx)->f;
if ( sign > 0 )
{
}
else
NOT_REACHED ();
-
- case_destroy (&c);
}
casereader_destroy (rr);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
casereader_get_value_cnt (reader), column_cnt);
else
{
- struct ccase c;
+ struct ccase *c;
size_t row;
for (row = 0; row < row_cnt; row++)
{
size_t col;
- if (!casereader_read (reader, &c))
+ c = casereader_read (reader);
+ if (c == NULL)
{
mc_error (mc, "casereader_read failed reading row %zu of %zu "
"(%zu columns)", row, row_cnt, column_cnt);
}
for (col = 0; col < column_cnt; col++)
- if (case_num_idx (&c, col) != array[row][col])
+ if (case_num_idx (c, col) != array[row][col])
mc_error (mc, "element %zu,%zu (of %zu,%zu) differs: "
"%g != %g",
row, col, row_cnt, column_cnt,
- case_num_idx (&c, col), array[row][col]);
+ case_num_idx (c, col), array[row][col]);
- case_destroy (&c);
+ case_unref (c);
}
- if (casereader_read (reader, &c))
+ c = casereader_read (reader);
+ if (c != NULL)
mc_error (mc, "casereader has extra cases (expected %zu)", row_cnt);
}
}
writer = mem_writer_create (params->backing_cols);
for (row = 0; row < params->backing_rows; row++)
{
- struct ccase c;
+ struct ccase *c;
int col;
- case_create (&c, params->backing_cols);
+ c = case_create (params->backing_cols);
for (col = 0; col < params->backing_cols; col++)
{
double value = params->next_value++;
data[row][col] = value;
- case_data_rw_idx (&c, col)->f = value;
+ case_data_rw_idx (c, col)->f = value;
}
- casewriter_write (writer, &c);
+ casewriter_write (writer, c);
}
reader = casewriter_make_reader (writer);
assert (reader != NULL);
if (mc_include_state (mc))
{
struct datasheet *ds;
- struct ccase c[MAX_ROWS];
+ struct ccase *c[MAX_ROWS];
size_t i, j;
clone_model (ods, odata, &ds, data);
for (i = 0; i < cnt; i++)
{
- case_create (&c[i], column_cnt);
+ c[i] = case_create (column_cnt);
for (j = 0; j < column_cnt; j++)
- case_data_rw_idx (&c[i], j)->f = params->next_value++;
+ case_data_rw_idx (c[i], j)->f = params->next_value++;
}
insert_range (data, row_cnt, sizeof data[pos], pos, cnt);
for (i = 0; i < cnt; i++)
for (j = 0; j < column_cnt; j++)
- data[i + pos][j] = case_num_idx (&c[i], j);
+ data[i + pos][j] = case_num_idx (c[i], j);
if (!datasheet_insert_rows (ds, pos, c, cnt))
mc_error (mc, "datasheet_insert_rows failed");
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
/* Rows. */
casenumber datasheet_get_row_cnt (const struct datasheet *);
bool datasheet_insert_rows (struct datasheet *,
- casenumber before, struct ccase[],
+ casenumber before, struct ccase *rows[],
casenumber cnt);
void datasheet_delete_rows (struct datasheet *,
casenumber first, casenumber cnt);
size_t cnt);
/* Data. */
-bool datasheet_get_row (const struct datasheet *, casenumber, struct ccase *);
+struct ccase *datasheet_get_row (const struct datasheet *, casenumber);
bool datasheet_put_row (struct datasheet *, casenumber, struct ccase *);
bool datasheet_get_value (const struct datasheet *, casenumber, size_t column,
union value *, int width);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
/* Handle COMPUTE or IF with numeric target variable. */
static int
-compute_num (void *compute_, struct ccase *c, casenumber case_num)
+compute_num (void *compute_, struct ccase **c, casenumber case_num)
{
struct compute_trns *compute = compute_;
if (compute->test == NULL
- || expr_evaluate_num (compute->test, c, case_num) == 1.0)
- case_data_rw (c, compute->variable)->f
- = expr_evaluate_num (compute->rvalue, c, case_num);
+ || expr_evaluate_num (compute->test, *c, case_num) == 1.0)
+ {
+ *c = case_unshare (*c);
+ case_data_rw (*c, compute->variable)->f
+ = expr_evaluate_num (compute->rvalue, *c, case_num);
+ }
return TRNS_CONTINUE;
}
/* Handle COMPUTE or IF with numeric vector element target
variable. */
static int
-compute_num_vec (void *compute_, struct ccase *c, casenumber case_num)
+compute_num_vec (void *compute_, struct ccase **c, casenumber case_num)
{
struct compute_trns *compute = compute_;
if (compute->test == NULL
- || expr_evaluate_num (compute->test, c, case_num) == 1.0)
+ || expr_evaluate_num (compute->test, *c, case_num) == 1.0)
{
double index; /* Index into the vector. */
int rindx; /* Rounded index value. */
- index = expr_evaluate_num (compute->element, c, case_num);
+ index = expr_evaluate_num (compute->element, *c, case_num);
rindx = floor (index + EPSILON);
if (index == SYSMIS
|| rindx < 1 || rindx > vector_get_var_cnt (compute->vector))
index, vector_get_name (compute->vector));
return TRNS_CONTINUE;
}
- case_data_rw (c, vector_get_var (compute->vector, rindx - 1))->f
- = expr_evaluate_num (compute->rvalue, c, case_num);
+
+ *c = case_unshare (*c);
+ case_data_rw (*c, vector_get_var (compute->vector, rindx - 1))->f
+ = expr_evaluate_num (compute->rvalue, *c, case_num);
}
return TRNS_CONTINUE;
/* Handle COMPUTE or IF with string target variable. */
static int
-compute_str (void *compute_, struct ccase *c, casenumber case_num)
+compute_str (void *compute_, struct ccase **c, casenumber case_num)
{
struct compute_trns *compute = compute_;
if (compute->test == NULL
- || expr_evaluate_num (compute->test, c, case_num) == 1.0)
- expr_evaluate_str (compute->rvalue, c, case_num,
- case_data_rw (c, compute->variable)->s, compute->width);
+ || expr_evaluate_num (compute->test, *c, case_num) == 1.0)
+ {
+ *c = case_unshare (*c);
+ expr_evaluate_str (compute->rvalue, *c, case_num,
+ case_data_rw (*c, compute->variable)->s,
+ compute->width);
+ }
return TRNS_CONTINUE;
}
/* Handle COMPUTE or IF with string vector element target
variable. */
static int
-compute_str_vec (void *compute_, struct ccase *c, casenumber case_num)
+compute_str_vec (void *compute_, struct ccase **c, casenumber case_num)
{
struct compute_trns *compute = compute_;
if (compute->test == NULL
- || expr_evaluate_num (compute->test, c, case_num) == 1.0)
+ || expr_evaluate_num (compute->test, *c, case_num) == 1.0)
{
double index; /* Index into the vector. */
int rindx; /* Rounded index value. */
struct variable *vr; /* Variable reference by indexed vector. */
- index = expr_evaluate_num (compute->element, c, case_num);
+ index = expr_evaluate_num (compute->element, *c, case_num);
rindx = floor (index + EPSILON);
if (index == SYSMIS)
{
}
vr = vector_get_var (compute->vector, rindx - 1);
- expr_evaluate_str (compute->rvalue, c, case_num,
- case_data_rw (c, vr)->s,
+ *c = case_unshare (*c);
+ expr_evaluate_str (compute->rvalue, *c, case_num,
+ case_data_rw (*c, vr)->s,
var_get_width (vr));
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
/* Transformation. */
/* Counts the number of values in case C matching CRIT. */
-static inline int
-count_numeric (struct criteria *crit, struct ccase *c)
+static int
+count_numeric (struct criteria *crit, const struct ccase *c)
{
int counter = 0;
size_t i;
}
/* Counts the number of values in case C matching CRIT. */
-static inline int
-count_string (struct criteria *crit, struct ccase *c)
+static int
+count_string (struct criteria *crit, const struct ccase *c)
{
int counter = 0;
size_t i;
/* Performs the COUNT transformation T on case C. */
static int
-count_trns_proc (void *trns_, struct ccase *c,
+count_trns_proc (void *trns_, struct ccase **c,
casenumber case_num UNUSED)
{
struct count_trns *trns = trns_;
struct dst_var *dv;
+ *c = case_unshare (*c);
for (dv = trns->dst_vars; dv; dv = dv->next)
{
struct criteria *crit;
counter = 0;
for (crit = dv->crit; crit; crit = crit->next)
if (var_is_numeric (crit->vars[0]))
- counter += count_numeric (crit, c);
+ counter += count_numeric (crit, *c);
else
- counter += count_string (crit, c);
- case_data_rw (c, dv->var)->f = counter;
+ counter += count_string (crit, *c);
+ case_data_rw (*c, dv->var)->f = counter;
}
return TRNS_CONTINUE;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
#include <language/command.h>
#include <language/lexer/lexer.h>
-static int trns_fail (void *x, struct ccase *c, casenumber n);
+static int trns_fail (void *x, struct ccase **c, casenumber n);
\f
/* A transformation which is guaranteed to fail. */
static int
-trns_fail (void *x UNUSED, struct ccase *c UNUSED,
+trns_fail (void *x UNUSED, struct ccase **c UNUSED,
casenumber n UNUSED)
{
return TRNS_ERROR;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
/* Performs RECODE transformation. */
static int
-recode_trns_proc (void *trns_, struct ccase *c, casenumber case_idx UNUSED)
+recode_trns_proc (void *trns_, struct ccase **c, casenumber case_idx UNUSED)
{
struct recode_trns *trns = trns_;
size_t i;
+ *c = case_unshare (*c);
for (i = 0; i < trns->var_cnt; i++)
{
const struct variable *src_var = trns->src_vars[i];
const struct variable *dst_var = trns->dst_vars[i];
- const union value *src_data = case_data (c, src_var);
- union value *dst_data = case_data_rw (c, dst_var);
+ const union value *src_data = case_data (*c, src_var);
+ union value *dst_data = case_data_rw (*c, dst_var);
const struct map_out *out;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
/* Executes a SAMPLE transformation. */
static int
-sample_trns_proc (void *t_, struct ccase *c UNUSED,
+sample_trns_proc (void *t_, struct ccase **c UNUSED,
casenumber case_num UNUSED)
{
struct sample_trns *t = t_;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
/* Performs the SELECT IF transformation T on case C. */
static int
-select_if_proc (void *t_, struct ccase *c,
+select_if_proc (void *t_, struct ccase **c,
casenumber case_num)
{
struct select_if_trns *t = t_;
- return (expr_evaluate_num (t->e, c, case_num) == 1.0
+ return (expr_evaluate_num (t->e, *c, case_num) == 1.0
? TRNS_CONTINUE : TRNS_DROP_CASE);
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2009 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
enum mv_class exclude)
{
struct casereader *pass1, *pass2;
- struct ccase c;
+ struct ccase *c;
struct levene_info l;
l.n_dep = n_dep;
casereader_split (reader, &pass1, &pass2);
levene_precalc (&l);
- for (; casereader_read (pass1, &c); case_destroy (&c))
- levene_calc (dict, &c, &l);
+ for (; (c = casereader_read (pass1)) != NULL; case_unref (c))
+ levene_calc (dict, c, &l);
casereader_destroy (pass1);
levene_postcalc (&l);
levene2_precalc(&l);
- for (; casereader_read (pass2, &c); case_destroy (&c))
- levene2_calc (dict, &c, &l);
+ for (; (c = casereader_read (pass2)) != NULL; case_unref (c))
+ levene2_calc (dict, c, &l);
casereader_destroy (pass2);
levene2_postcalc (&l);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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
struct merge_input
{
struct casereader *reader;
- struct ccase c;
+ struct ccase *c;
};
struct merge
{
struct merge_input *i = &m->inputs[idx];
- if (casereader_read (i->reader, &i->c))
+ i->c = casereader_read (i->reader);
+ if (i->c)
return true;
else
{
min = 0;
for (i = 1; i < m->input_cnt; i++)
- if (subcase_compare_3way (&m->ordering, &m->inputs[i].c,
- &m->ordering, &m->inputs[min].c) < 0)
+ if (subcase_compare_3way (&m->ordering, m->inputs[i].c,
+ &m->ordering, m->inputs[min].c) < 0)
min = i;
- casewriter_write (w, &m->inputs[min].c);
+ casewriter_write (w, m->inputs[min].c);
read_input_case (m, min);
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 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
acc (struct statistic *s, const struct ccase *cx UNUSED,
double c, double cc, double y)
{
- struct ccase cp;
+ struct ccase *cp;
struct np *np = (struct np *) s;
double rank = np->prev_cc + (c + 1) / 2.0;
maximize (&np->y_max, y);
minimize (&np->y_min, y);
- case_create (&cp, n_NP_IDX);
-
- case_data_rw_idx (&cp, NP_IDX_Y)->f = y;
- case_data_rw_idx (&cp, NP_IDX_NS)->f = ns;
- case_data_rw_idx (&cp, NP_IDX_DNS)->f = dns;
-
- casewriter_write (np->writer, &cp);
+ cp = case_create (n_NP_IDX);
+ case_data_rw_idx (cp, NP_IDX_Y)->f = y;
+ case_data_rw_idx (cp, NP_IDX_NS)->f = ns;
+ case_data_rw_idx (cp, NP_IDX_DNS)->f = dns;
+ casewriter_write (np->writer, cp);
np->prev_cc = cc;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 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
const struct variable *var,
enum mv_class exclude)
{
- struct ccase cx;
- struct ccase prev_cx;
+ struct ccase *cx;
+ struct ccase *prev_cx = NULL;
double prev_value = -DBL_MAX;
double cc_i = 0;
double c_i = 0;
- case_nullify (&prev_cx);
-
- for (; casereader_read (reader, &cx); case_destroy (&cx))
+ for (; (cx = casereader_read (reader)) != NULL; case_unref (cx))
{
- const double weight = wv ? case_data (&cx, wv)->f : 1.0;
- const double this_value = case_data (&cx, var)->f;
+ const double weight = wv ? case_data (cx, wv)->f : 1.0;
+ const double this_value = case_data (cx, var)->f;
/* The casereader MUST be sorted */
assert (this_value >= prev_value);
- if ( var_is_value_missing (var, case_data (&cx, var), exclude))
+ if ( var_is_value_missing (var, case_data (cx, var), exclude))
continue;
- case_destroy (&prev_cx);
+ case_unref (prev_cx);
if ( prev_value == -DBL_MAX || prev_value == this_value)
c_i += weight;
if ( prev_value > -DBL_MAX && this_value > prev_value)
{
- update_k_values (&prev_cx, prev_value, c_i, cc_i, os, nos);
+ update_k_values (prev_cx, prev_value, c_i, cc_i, os, nos);
c_i = weight;
}
cc_i += weight;
prev_value = this_value;
- case_clone (&prev_cx, &cx);
+ prev_cx = case_ref (cx);
}
- update_k_values (&prev_cx, prev_value, c_i, cc_i, os, nos);
- case_destroy (&prev_cx);
+ update_k_values (prev_cx, prev_value, c_i, cc_i, os, nos);
+ case_unref (prev_cx);
casereader_destroy (reader);
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 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
struct casewriter *run;
casenumber run_id;
- struct ccase run_end;
+ struct ccase *run_end;
};
static struct casewriter_class sort_casewriter_class;
static bool pqueue_is_full (const struct pqueue *);
static bool pqueue_is_empty (const struct pqueue *);
static void pqueue_push (struct pqueue *, struct ccase *, casenumber);
-static void pqueue_pop (struct pqueue *, struct ccase *, casenumber *);
+static struct ccase *pqueue_pop (struct pqueue *, casenumber *);
static void output_record (struct sort_writer *);
sort->pqueue = pqueue_create (ordering, value_cnt);
sort->run = NULL;
sort->run_id = 0;
- case_nullify (&sort->run_end);
+ sort->run_end = NULL;
return casewriter_create (value_cnt, &sort_casewriter_class, sort);
}
if (pqueue_is_full (sort->pqueue))
output_record (sort);
- next_run = (case_is_null (&sort->run_end)
+ next_run = (sort->run_end == NULL
|| subcase_compare_3way (&sort->ordering, c,
- &sort->ordering, &sort->run_end) < 0);
+ &sort->ordering, sort->run_end) < 0);
pqueue_push (sort->pqueue, c, sort->run_id + (next_run ? 1 : 0));
}
merge_destroy (sort->merge);
pqueue_destroy (sort->pqueue);
casewriter_destroy (sort->run);
- case_destroy (&sort->run_end);
+ case_unref (sort->run_end);
free (sort);
}
static void
output_record (struct sort_writer *sort)
{
- struct ccase min_case;
+ struct ccase *min_case;
casenumber min_run_id;
- pqueue_pop (sort->pqueue, &min_case, &min_run_id);
+ min_case = pqueue_pop (sort->pqueue, &min_run_id);
#if 0
- printf ("\toutput: %f to run %d\n", case_num_idx (&min_case, 0), min_run_id);
+ printf ("\toutput: %f to run %d\n", case_num_idx (min_case, 0), min_run_id);
#endif
if (sort->run_id != min_run_id && sort->run != NULL)
sort->run_id = min_run_id;
}
- case_destroy (&sort->run_end);
- case_clone (&sort->run_end, &min_case);
-
- casewriter_write (sort->run, &min_case);
+ case_unref (sort->run_end);
+ sort->run_end = case_ref (min_case);
+ casewriter_write (sort->run, min_case);
}
static struct casewriter_class sort_casewriter_class =
struct pqueue_record
{
casenumber id;
- struct ccase c;
+ struct ccase *c;
casenumber idx;
};
{
while (!pqueue_is_empty (pq))
{
- struct ccase c;
casenumber id;
- pqueue_pop (pq, &c, &id);
- case_destroy (&c);
+ struct ccase *c = pqueue_pop (pq, &id);
+ case_unref (c);
}
subcase_destroy (&pq->ordering);
free (pq->records);
r = &pq->records[pq->record_cnt++];
r->id = id;
- case_move (&r->c, c);
+ r->c = c;
r->idx = pq->idx++;
push_heap (pq->records, pq->record_cnt, sizeof *pq->records,
compare_pqueue_records_minheap, pq);
}
-static void
-pqueue_pop (struct pqueue *pq, struct ccase *c, casenumber *id)
+static struct ccase *
+pqueue_pop (struct pqueue *pq, casenumber *id)
{
struct pqueue_record *r;
r = &pq->records[pq->record_cnt];
*id = r->id;
- case_move (c, &r->c);
+ return r->c;
}
/* Compares record-run tuples A and B on id, then on case data,
const struct pqueue *pq = pq_;
int result = a->id < b->id ? -1 : a->id > b->id;
if (result == 0)
- result = subcase_compare_3way (&pq->ordering, &a->c,
- &pq->ordering, &b->c);
+ result = subcase_compare_3way (&pq->ordering, a->c, &pq->ordering, b->c);
if (result == 0)
result = a->idx < b->idx ? -1 : a->idx > b->idx;
return -result;
/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 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
writer = autopaging_writer_create (dict_get_next_value_idx (clip_dict));
for (i = range.row0; i <= range.rowi ; ++i )
{
- struct ccase old;
-
- if (psppire_data_store_get_case (ds, i, &old))
- {
- struct ccase new;
-
- case_map_execute (map, &old, &new);
- case_destroy (&old);
- casewriter_write (writer, &new);
- }
+ struct ccase *old = psppire_data_store_get_case (ds, i);
+ if (old != NULL)
+ casewriter_write (writer, case_map_execute (map, old));
else
casewriter_force_error (writer);
}
for (r = 0 ; r < case_cnt ; ++r )
{
int c;
- struct ccase cc;
- if ( ! casereader_peek (clip_datasheet, r, &cc))
+ struct ccase *cc;
+
+ cc = casereader_peek (clip_datasheet, r);
+ if (cc == NULL)
{
g_warning ("Clipboard seems to have inexplicably shrunk");
break;
for (c = 0 ; c < var_cnt ; ++c)
{
const struct variable *v = dict_get_var (clip_dict, c);
- data_out_g_string (string, v, &cc);
+ data_out_g_string (string, v, cc);
if ( c < val_cnt - 1 )
g_string_append (string, "\t");
}
if ( r < case_cnt)
g_string_append (string, "\n");
- case_destroy (&cc);
+ case_unref (cc);
}
return string;
for (r = 0 ; r < case_cnt ; ++r )
{
int c;
- struct ccase cc;
- if ( ! casereader_peek (clip_datasheet, r, &cc))
+ struct ccase *cc = casereader_peek (clip_datasheet, r);
+ if (cc == NULL)
{
g_warning ("Clipboard seems to have inexplicably shrunk");
break;
{
const struct variable *v = dict_get_var (clip_dict, c);
g_string_append (string, "<td>");
- data_out_g_string (string, v, &cc);
+ data_out_g_string (string, v, cc);
g_string_append (string, "</td>\n");
}
g_string_append (string, "</tr>\n");
- case_destroy (&cc);
+ case_unref (cc);
}
g_string_append (string, "</table>\n");
/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2006, 2008 Free Software Foundation
+ Copyright (C) 2006, 2008, 2009 Free Software Foundation
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
{
gboolean result;
gint val_cnt, v;
- struct ccase cc;
+ struct ccase *cc;
g_return_val_if_fail (ds, FALSE);
val_cnt = datasheet_get_column_cnt (ds->datasheet) ;
g_return_val_if_fail (posn <= psppire_data_store_get_case_count (ds), FALSE);
- case_create (&cc, val_cnt);
+ cc = case_create (val_cnt);
- memset ( case_data_rw_idx (&cc, 0), 0, val_cnt * MAX_SHORT_STRING);
+ memset ( case_data_rw_idx (cc, 0), 0, val_cnt * MAX_SHORT_STRING);
for (v = 0 ; v < psppire_dict_get_var_cnt (ds->dict) ; ++v)
{
if ( var_is_alpha (pv))
continue;
- case_data_rw (&cc, pv)->f = SYSMIS;
+ case_data_rw (cc, pv)->f = SYSMIS;
}
- result = psppire_data_store_insert_case (ds, &cc, posn);
+ result = psppire_data_store_insert_case (ds, cc, posn);
- case_destroy (&cc);
+ case_unref (cc);
return result;
}
\f
-/* Fills C with the CASENUMth case.
- Returns true on success, false otherwise.
+/* Returns the CASENUMth case, or a null pointer on failure.
*/
-gboolean
+struct ccase *
psppire_data_store_get_case (const PsppireDataStore *ds,
- casenumber casenum,
- struct ccase *c)
+ casenumber casenum)
{
g_return_val_if_fail (ds, FALSE);
g_return_val_if_fail (ds->datasheet, FALSE);
- return datasheet_get_row (ds->datasheet, casenum, c);
+ return datasheet_get_row (ds->datasheet, casenum);
}
struct ccase *cc,
casenumber posn)
{
- struct ccase tmp;
bool result ;
g_return_val_if_fail (ds, FALSE);
g_return_val_if_fail (ds->datasheet, FALSE);
- case_clone (&tmp, cc);
- result = datasheet_insert_rows (ds->datasheet, posn, &tmp, 1);
+ case_ref (cc);
+ result = datasheet_insert_rows (ds->datasheet, posn, &cc, 1);
if ( result )
{
/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2006 Free Software Foundation
+ Copyright (C) 2006, 2009 Free Software Foundation
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
\f
-gboolean psppire_data_store_get_case (const PsppireDataStore *ds,
- casenumber casenum,
- struct ccase *c);
+struct ccase *psppire_data_store_get_case (const PsppireDataStore *ds,
+ casenumber casenum);