Make cases simpler, faster, and easier to understand.
authorBen Pfaff <blp@gnu.org>
Wed, 7 Jan 2009 07:17:32 +0000 (23:17 -0800)
committerBen Pfaff <blp@gnu.org>
Wed, 7 Jan 2009 07:17:32 +0000 (23:17 -0800)
Cases (struct ccase) is reference-counted to avoid copying more
data than necessary.  But the existing implementation that uses
separate structures for references to cases (struct ccase) and
the cases themselves (struct case_data) has a number of issues:

   - The semantics of struct ccase are tricky to remember; one
     has to remember to treat struct ccase as essentially a
     pointer type.  I get confused sometimes myself.

     (One of the symptoms of this was the existence of
      the case_nullify and case_is_null functions, which are
      exactly analogous to setting a pointer to null and comparing
      one against null, respectively.)

   - Every reference to data in a case involves two levels of
     indirection, which is one more than actually necessary.

   - The implementation is somewhat complicated.

This commit simplifies things, by dropping a level of indirection.
Now, a case is just a pointer to a struct ccase, which contains
the actual data.  Reference counting is still present, but it is
simplified.  The only thing that must be remembered is that, before
modifying a case that may be shared, it must be passed through
case_unshare() to make a new unshared copy if necessary.

88 files changed:
src/data/case-map.c
src/data/case-map.h
src/data/case-matcher.c
src/data/case-matcher.h
src/data/case-tmpfile.c
src/data/case-tmpfile.h
src/data/case.c
src/data/case.h
src/data/casegrouper.c
src/data/caseinit.c
src/data/casereader-filter.c
src/data/casereader-provider.h
src/data/casereader-translator.c
src/data/casereader.c
src/data/casereader.h
src/data/casewindow.c
src/data/casewindow.h
src/data/casewriter-provider.h
src/data/casewriter-translator.c
src/data/casewriter.c
src/data/casewriter.h
src/data/datasheet.c
src/data/datasheet.h
src/data/gnumeric-reader.c
src/data/lazy-casereader.c
src/data/por-file-reader.c
src/data/por-file-reader.h
src/data/por-file-writer.c
src/data/por-file-writer.h
src/data/procedure.c
src/data/procedure.h
src/data/psql-reader.c
src/data/scratch-reader.h
src/data/scratch-writer.c
src/data/scratch-writer.h
src/data/sparse-cases.c
src/data/subcase.c
src/data/sys-file-reader.c
src/data/sys-file-reader.h
src/data/sys-file-writer.c
src/data/sys-file-writer.h
src/data/transformations.c
src/data/transformations.h
src/language/control/do-if.c
src/language/control/loop.c
src/language/data-io/combine-files.c
src/language/data-io/data-list.c
src/language/data-io/data-parser.c
src/language/data-io/inpt-pgm.c
src/language/data-io/list.q
src/language/data-io/print-space.c
src/language/data-io/print.c
src/language/data-io/save.c
src/language/expressions/evaluate.c
src/language/expressions/operations.def
src/language/stats/aggregate.c
src/language/stats/autorecode.c
src/language/stats/binomial.c
src/language/stats/chisquare.c
src/language/stats/crosstabs.q
src/language/stats/descriptives.c
src/language/stats/examine.q
src/language/stats/flip.c
src/language/stats/frequencies.q
src/language/stats/glm.q
src/language/stats/npar-summary.c
src/language/stats/oneway.q
src/language/stats/rank.q
src/language/stats/regression.q
src/language/stats/reliability.q
src/language/stats/t-test.q
src/language/stats/wilcoxon.c
src/language/tests/datasheet-check.c
src/language/tests/datasheet-check.h
src/language/xforms/compute.c
src/language/xforms/count.c
src/language/xforms/fail.c
src/language/xforms/recode.c
src/language/xforms/sample.c
src/language/xforms/select-if.c
src/math/levene.c
src/math/merge.c
src/math/np.c
src/math/order-stats.c
src/math/sort.c
src/ui/gui/psppire-data-editor.c
src/ui/gui/psppire-data-store.c
src/ui/gui/psppire-data-store.h

index 8d309580acca22bcaa811acccf8fe85963369523..cff621f3456df7438562aa57d79dd78c4905fb3e 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -38,7 +38,7 @@ struct case_map
                            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. */
@@ -83,20 +83,30 @@ case_map_destroy (struct case_map *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
@@ -147,12 +157,11 @@ case_map_create_output_translator (struct case_map *map,
 }
 
 /* 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. */
index 1c8608c291b7d09df64d692142f4c5915c6aa9a2..010dd487274d537af9035a53b5e5dac21ef12a91 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -34,8 +34,7 @@ struct dictionary;
 
 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 *);
 
index 9cfc0083c2b2b4ff624989cd2b42097ddd4b5f7e..a1251cb74cbfd816c7dab2ed54129659a0215e0b 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -30,7 +30,7 @@
 struct case_matcher_input
   {
     struct subcase by_vars;
-    const struct ccase *data;
+    struct ccase **data;
     bool *is_minimal;
   };
 
@@ -55,13 +55,15 @@ case_matcher_create (void)
 
 /* 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;
 
@@ -101,7 +103,7 @@ case_matcher_destroy (struct case_matcher *cm)
 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
@@ -121,7 +123,7 @@ case_matcher_match (struct case_matcher *cm, union value **by)
 
   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)
@@ -140,7 +142,7 @@ case_matcher_match (struct case_matcher *cm, union value **by)
     {
       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;
     }
index d172f6113bcc6bcc84bd85b1a8e3158322b569f7..fa40781f0060d552b63840a24d304a9ab9ec3318 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -25,7 +25,7 @@ union value;
 
 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);
index e6fc3de46c834e6acc48566d8c35847150244be3..ca3a6a564421552f4241900caa2fb21708f08226 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -198,25 +198,23 @@ case_tmpfile_get_values (const struct case_tmpfile *ctf,
           && 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;
     }
 }
 
@@ -246,7 +244,7 @@ case_tmpfile_put_case (struct case_tmpfile *ctf, casenumber case_idx,
 {
   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;
 }
 
index 3a92debc6e8e1b40be4e98342b96cd50a3487629..a5916249d45fcf04ca55d2845da70ff8ebe618f2 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -38,11 +38,10 @@ bool case_tmpfile_error (const struct case_tmpfile *);
 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,
index cec6f21e1be8ae94ccd7dcbc2284841e91ec9cab..8ae989002f016f2b6978ede795415715c1fe585a 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -20,6 +20,7 @@
 
 #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
@@ -247,30 +163,21 @@ case_data (const struct ccase *c, const struct variable *v)
   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)
 {
@@ -279,14 +186,24 @@ 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
@@ -294,57 +211,53 @@ case_data_idx (const struct ccase *c, size_t idx)
 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;
@@ -375,26 +288,34 @@ case_compare_2dict (const struct ccase *ca, const struct ccase *cb,
 /* 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;
 }
index aa5b9dd0d7c99397ebcb00c7ef908f6ee6a4d719..6f53772688c3c1f29ba15cc0475735d0803762e4 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -20,6 +20,8 @@
 #include <limits.h>
 #include <stddef.h>
 #include <stdbool.h>
+#include <stdlib.h>
+#include <libpspp/compiler.h>
 #include "value.h"
 
 struct variable;
@@ -29,57 +31,130 @@ 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 */
index 75925650f277ad8fbdf0f83b548eebb217b9138f..86788ba7a3bc5afcbd280ad2be920685a48e76db 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -80,28 +80,26 @@ casegrouper_get_next_group (struct casegrouper *grouper,
   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;
index f789244dd53b13d4b41a3498c89112bb5ea2cdf7..4f7ece7e03bac3dc6950a2d977a0203ddad62c23 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -247,7 +247,8 @@ caseinit_mark_for_init (struct caseinit *ci, const struct dictionary *d)
   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)
 {
index fcd264e9dc35e08f8d7737b83973ca9c5d4f9e40..d387f5ea03181794e790ea297a3b10cdc8337880 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -86,22 +86,22 @@ casereader_create_filter_func (struct casereader *subreader,
 }
 
 /* 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);
     }
 }
 
@@ -115,12 +115,12 @@ casereader_filter_destroy (struct casereader *reader, void *filter_)
      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);
index 772209810a85e44c2f7474a44fcb25235735cf98..31d8a6d4c88e67a6afab5ad2e372c0b5041f6790 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -43,20 +43,23 @@ struct casereader_class
   {
     /* 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.
 
@@ -88,22 +91,23 @@ struct casereader_class
        (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 *
@@ -119,21 +123,22 @@ struct casereader_random_class
     /* 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.
 
index ae22f1297e19dbe5a12e6d9e2ec49f75ce8de087..d55e18e50292282a6e7c6d95233802fb42c920ed 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -32,7 +32,7 @@ struct casereader_translator
   {
     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;
   };
@@ -41,9 +41,9 @@ static const struct casereader_class casereader_translator_class;
 
 /* 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.
@@ -54,9 +54,8 @@ static const struct casereader_class casereader_translator_class;
 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)
 {
@@ -75,20 +74,15 @@ casereader_create_translator (struct casereader *subreader,
 }
 
 /* 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. */
@@ -123,8 +117,7 @@ struct casereader_append_numeric
 
 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,
@@ -152,15 +145,14 @@ casereader_create_append_numeric (struct casereader *subreader,
 }
 
 
-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
@@ -231,8 +223,7 @@ struct casereader_append_rank
 
 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,
@@ -293,9 +284,8 @@ car_destroy (void *car_)
   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_;
 
@@ -321,16 +311,16 @@ car_translate (struct ccase *input, struct ccase *output,  void *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;
@@ -341,7 +331,7 @@ car_translate (struct ccase *input, struct ccase *output,  void *car_)
                weight += 1.0;
              car->n_common++;
            }
-         case_destroy (&c);
+          case_unref (c);
        }
       while (vxx == value);
       car->mean_rank = car->cc + (weight + 1) / 2.0;
@@ -355,11 +345,10 @@ car_translate (struct ccase *input, struct ccase *output,  void *car_)
 
   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;
 }
 
 
index ee7facb769dbf9a26dc96d717f1249a7fe44879b..3d27a9192a79bd63466e25e2059ce91824e94241 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -43,18 +43,17 @@ struct casereader
 
 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)
     {
@@ -69,17 +68,18 @@ casereader_read (struct casereader *reader, struct ccase *c)
          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.
@@ -160,27 +160,27 @@ casereader_swap (struct casereader *a, struct casereader *b)
     }
 }
 
-/* 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
@@ -191,13 +191,18 @@ casereader_peek (struct casereader *reader, casenumber idx, struct ccase *c)
 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;
+        }
     }
 }
 
@@ -263,11 +268,11 @@ casereader_count_cases (struct casereader *reader)
   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);
@@ -289,12 +294,12 @@ casereader_get_value_cnt (struct casereader *reader)
 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);
 }
 
@@ -475,22 +480,20 @@ advance_random_reader (struct casereader *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
@@ -529,15 +532,14 @@ random_reader_clone (struct casereader *reader, void *br_)
 }
 
 /* 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. */
@@ -607,24 +609,27 @@ prime_buffer (struct shim *b, casenumber case_cnt)
 {
   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. */
index 3df80cb08fb8d38acc302e0654a0217dd666287a..deab5641661ec111d6751254f77c73ca77200550 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -59,7 +59,7 @@ struct dictionary;
 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 *);
@@ -68,8 +68,7 @@ void casereader_split (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 *);
@@ -107,9 +106,8 @@ casereader_create_counter (struct casereader *, casenumber *counter,
 
 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);
 
index 0d735c4dc3ff909c41278df40b5179bdb3dbd2cd..d2be9cfaad3b2a6a0653834dae5b173f0e93568a 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -52,7 +52,7 @@ struct casewindow_class
     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);
   };
 
@@ -120,11 +120,11 @@ casewindow_to_disk (struct casewindow *old)
   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);
@@ -147,7 +147,7 @@ casewindow_push_head (struct casewindow *cw, struct ccase *c)
         }
     }
   else
-    case_destroy (c);
+    case_unref (c);
 }
 
 /* Deletes CASE_CNT cases at the tail of casewindow CW. */
@@ -158,23 +158,19 @@ casewindow_pop_tail (struct casewindow *cw, casenumber case_cnt)
     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. */
@@ -218,7 +214,7 @@ casewindow_get_taint (const struct casewindow *cw)
 struct casewindow_memory
   {
     struct deque deque;
-    struct ccase *cases;
+    struct ccase **cases;
   };
 
 static void *
@@ -234,7 +230,7 @@ casewindow_memory_destroy (void *cwm_)
 {
   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);
 }
@@ -245,7 +241,7 @@ casewindow_memory_push_head (void *cwm_, struct ccase *c)
   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
@@ -254,15 +250,14 @@ casewindow_memory_pop_tail (void *cwm_, casenumber case_cnt)
   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
@@ -325,11 +320,11 @@ casewindow_file_pop_tail (void *cwf_, casenumber cnt)
     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
index c3971231afe2d1ed5ac5f89e9b5b61e719505212..f0a200f449de014638d8114ce9b50cb13a4fccb8 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -37,8 +37,8 @@ bool casewindow_destroy (struct casewindow *);
 
 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 *);
 
index 8298af465da9d88640fe813f6a12309c6effd036..1680fe28303c5f1fa4dd6d8887954a39b494abc9 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -23,7 +23,8 @@ struct casewriter_class
   {
     /* 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
index c630b44cda397dfffccd980c9d3ecb65255e91dc..a19533d65d330b6f443b308522e88d61b25687f6 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -29,7 +29,7 @@ struct casewriter_translator
   {
     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;
   };
@@ -37,10 +37,15 @@ struct casewriter_translator
 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.
@@ -51,9 +56,8 @@ static const struct casewriter_class casewriter_translator_class;
 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)
 {
@@ -75,10 +79,9 @@ casewriter_translator_write (struct casewriter *writer UNUSED,
                              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
index 4461d85e84cfc191821746df34e44b02dfc0f4ef..56e6c291cbb4fb7722a310eeb504b20bb58a37d5 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -250,18 +250,19 @@ casewriter_window_convert_to_reader (struct casewriter *writer UNUSED,
   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. */
index a92c417680116ffbfc438e52877b64f74f62e1e3..05ef707246060eb215e0b880d6c4e9b0117013d1 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -43,9 +43,8 @@ struct casewriter *autopaging_writer_create (size_t value_cnt);
 \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);
 
index fd07ed30e71e48647462e163b3e6991e83e42f54..83a2a677e3b55a671a10f71d5347fb2b4b312b07 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -389,21 +389,22 @@ datasheet_move_columns (struct datasheet *ds,
   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;
     }
 }
 
@@ -417,7 +418,7 @@ datasheet_put_row (struct datasheet *ds, casenumber row, struct ccase *c)
   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;
 }
 
@@ -445,13 +446,15 @@ datasheet_put_value (struct datasheet *ds, casenumber row, size_t column,
                   (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;
@@ -476,10 +479,10 @@ datasheet_insert_rows (struct datasheet *ds,
 
       /* 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;
           }
@@ -540,20 +543,20 @@ datasheet_make_reader (struct datasheet *ds)
 }
 
 /* "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. */
@@ -1136,15 +1139,12 @@ source_read (const struct source *source,
     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;
     }
@@ -1169,9 +1169,10 @@ source_write (struct source *source,
     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
@@ -1182,15 +1183,16 @@ source_write (struct source *source,
              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;
index 2a05fe0da516bef80ea9ee7abafb7b38c33e4892..860f236ec33af74b1ba8f53be1d5108a40644501 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -50,7 +50,7 @@ void datasheet_move_columns (struct datasheet *,
 /* 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);
@@ -59,7 +59,7 @@ void datasheet_move_rows (struct datasheet *,
                           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);
index 522176640489c87ec57027115582cbb9bc26d617..5a0c75ede293a21052228a87b295a070398f3e1f 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -60,8 +60,7 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
 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 =
   {
@@ -172,7 +171,7 @@ struct gnumeric_reader
 
   size_t value_cnt;
   struct dictionary *dict;
-  struct ccase first_case;
+  struct ccase *first_case;
   bool used_first_case;
 };
 
@@ -193,7 +192,7 @@ gnm_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
     xmlFreeTextReader (r->xtr);
 
   if ( ! r->used_first_case )
-    case_destroy (&r->first_case);
+    case_unref (r->first_case);
 
   free (r);
 }
@@ -537,15 +536,15 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
       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);
     }
 
@@ -580,12 +579,12 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 };
 
 
-/* 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_;
@@ -593,12 +592,11 @@ gnm_file_casereader_read (struct casereader *reader UNUSED, void *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);
 
@@ -632,7 +630,13 @@ gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_,
 
     }
 
-  return (ret == 1);
+  if (ret == 1)
+    return c;
+  else
+    {
+      case_unref (c);
+      return NULL;
+    }
 }
 
 
index 2cb8911fe29770559eee3c7c2ea702e88a38b9f5..65d10aea2477640a826077a7da01c17f78fbf665 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -117,13 +117,12 @@ instantiate_lazy_casereader (struct casereader *reader,
   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
@@ -143,13 +142,12 @@ lazy_casereader_clone (struct casereader *reader, void *lc_)
   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 =
index 52c0cc8edab5dca9a59b142d83cf9c3466489a3e..7e65c28bdf51c11b54f1f6ddd9eced26670b6197 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -814,28 +814,30 @@ read_documents (struct pfm_reader *r, struct dictionary *dict)
     }
 }
 
-/* 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;
@@ -857,7 +859,7 @@ por_file_casereader_read (struct casereader *reader, void *r_, struct ccase *c)
         }
     }
 
-  return true;
+  return c;
 }
 
 /* Returns true if FILE is an SPSS portable file,
index f227fd9a7761b1381c04c3598281cad5de114aae..326514f9a78e58adc9ebd46205565a0262e394f5 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -34,7 +34,6 @@ struct pfm_read_info
 
 struct dictionary;
 struct file_handle;
-struct ccase;
 struct casereader *pfm_open_reader (struct file_handle *,
                                     struct dictionary **,
                                     struct pfm_read_info *);
index 8a27f6b785ccc548d5a14436cfe221ee7476d3e6..773969302ebcb9ddc3b06fea93aa1da6c66c313c 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -463,7 +463,7 @@ por_file_casewriter_write (struct casewriter *writer, void *w_,
   else
     casewriter_force_error (writer);
 
-  case_destroy (c);
+  case_unref (c);
 }
 
 static void
index b018a4f4206ad47611823c81891a5a30c33d8b6e..04eaaa2c724865a9887c043f7b3a7bb49ed71f4a 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -38,7 +38,6 @@ struct pfm_write_options
 
 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);
index 98414a2b0478dbb5e44f306e0f99d90684b86003..91e185a45a43f3d78802338d6b26536f0a9dc6b0 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -79,7 +79,7 @@ struct dataset {
   /* 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
@@ -203,15 +203,15 @@ proc_is_open (const struct dataset *ds)
 }
 
 /* "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;
 
@@ -219,58 +219,47 @@ proc_casereader_read (struct casereader *reader UNUSED, void *ds_,
       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;
     }
 }
 
@@ -279,13 +268,13 @@ static void
 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;
@@ -306,7 +295,7 @@ proc_commit (struct dataset *ds)
 
   /* 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. */
@@ -361,14 +350,14 @@ update_last_proc_invocation (struct dataset *ds)
 \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;
 }
@@ -679,7 +668,7 @@ add_case_limit_trns (struct dataset *ds)
    *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)
@@ -718,11 +707,11 @@ add_filter_trns (struct dataset *ds)
 /* 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);
 }
index 336725dfdeca934a1a315db32a666d5a17c7ac4f..5d998030a644d8d20ac2f030f90a70e685959bb6 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -82,7 +82,7 @@ struct dictionary *dataset_dict (const struct dataset *ds);
 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 */
index 244248a20aeecdf34bcabedbbf188047e5c9b71c..a54b9f8b3888c58320623ea1d53086bc8650a155 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -75,8 +75,7 @@ psql_open_reader (struct psql_read_info *info UNUSED, struct dictionary **dict U
 
 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 =
   {
@@ -109,8 +108,7 @@ struct psql_reader
 };
 
 
-static bool set_value (struct psql_reader *r,
-                      struct ccase *cc);
+static struct ccase *set_value (struct psql_reader *r);
 
 
 
@@ -546,9 +544,8 @@ psql_casereader_destroy (struct casereader *reader UNUSED, void *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_;
 
@@ -558,24 +555,24 @@ psql_casereader_read (struct casereader *reader UNUSED, void *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);
 
 
@@ -870,7 +867,7 @@ set_value (struct psql_reader *r,
 
   r->tuple++;
 
-  return true;
+  return c;
 }
 
 #endif
index 44531a494f5465bd439aec03bcd6044e640581c1..a5ee005efda9b521db198cdbc4dda387c1fa2646 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -21,7 +21,6 @@
 
 struct dictionary;
 struct file_handle;
-struct ccase;
 struct casereader *scratch_reader_open (struct file_handle *,
                                         struct dictionary **);
 
index ed88af6db4ee1a211443702de9545c251546abc7..952860cdc5887e00104be1239f089f3eaf2c71b8 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -99,15 +99,8 @@ scratch_writer_casewriter_write (struct casewriter *w UNUSED, void *writer_,
                                  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. */
index d2fda12a915c85341d304974b9eee75cc555948f..a9c7a4d9c1e8dfd96974aa142eb44a014e1dc0c8 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -21,7 +21,6 @@
 
 struct dictionary;
 struct file_handle;
-struct ccase;
 struct casewriter *scratch_writer_open (struct file_handle *,
                                         const struct dictionary *);
 
index 1f3fb092a12b77a0601cdce75717a4e87d883a24..13fcf7888feae74f2a2489f7ea5df3c678807a71 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <data/case.h>
 #include <data/settings.h>
 #include <data/case-tmpfile.h>
 #include <libpspp/assertion.h>
@@ -49,7 +50,7 @@ sparse_cases_create (size_t column_cnt)
   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;
@@ -76,12 +77,15 @@ sparse_cases_clone (const struct sparse_cases *old)
   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;
@@ -98,15 +102,16 @@ sparse_cases_clone (const struct sparse_cases *old)
           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
@@ -127,10 +132,10 @@ sparse_cases_destroy (struct sparse_cases *sc)
       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);
@@ -154,7 +159,7 @@ static bool
 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);
@@ -162,10 +167,10 @@ dump_sparse_cases_to_disk (struct sparse_cases *sc)
   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;
@@ -202,13 +207,20 @@ sparse_cases_read (struct sparse_cases *sc, casenumber row, size_t column,
 
   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
     {
@@ -225,20 +237,24 @@ static bool
 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);
 
@@ -255,8 +271,11 @@ sparse_cases_write (struct sparse_cases *sc, casenumber row, size_t column,
 {
   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)
             {
@@ -265,8 +284,8 @@ sparse_cases_write (struct sparse_cases *sc, casenumber row, size_t column,
               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);
@@ -302,12 +321,15 @@ sparse_cases_write_columns (struct sparse_cases *sc, size_t start_column,
   /* 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
     {
index 3e019c7c8497bf3340bf1dc2cce256fe6d85aad4..d4b137830608374637bed3aeca1cc98083909dc9 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -168,7 +168,9 @@ subcase_inject (const struct subcase *sc,
 /* 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)
index c80bd5f557246cead2e3cc0feeb743834a48d0f5..af09189e1fa0721919597bb18eef4d1508e07f1d 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -1304,24 +1304,24 @@ static bool read_compressed_string (struct sfm_reader *, char *);
 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++)
@@ -1342,15 +1342,15 @@ sys_file_casereader_read (struct casereader *reader, void *r_,
             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. */
index eaf051fed7a6cc73c7e5a82628100d38554ea55d..242857494ee365af5238936bdd8c7e2027c30c0a 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -47,7 +47,6 @@ struct sfm_read_info
 
 struct dictionary;
 struct file_handle;
-struct ccase;
 struct casereader *sfm_open_reader (struct file_handle *,
                                     struct dictionary **,
                                     struct sfm_read_info *);
index aa539a51364fb6804aa1ddfc2b14d2ee545ebbc3..393be4e1265292b58fc37daa64bfaf4a4ff40a15 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -126,8 +126,9 @@ static void write_zeros (struct sfm_writer *, size_t);
 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);
@@ -747,7 +748,7 @@ sys_file_casewriter_write (struct casewriter *writer, void *w_,
   if (ferror (w->file))
     {
       casewriter_force_error (writer);
-      case_destroy (c);
+      case_unref (c);
       return;
     }
 
@@ -758,7 +759,7 @@ sys_file_casewriter_write (struct casewriter *writer, void *w_,
   else
     write_case_compressed (w, c);
 
-  case_destroy (c);
+  case_unref (c);
 }
 
 /* Destroys system file writer W. */
@@ -836,7 +837,7 @@ static const struct casewriter_class sys_file_casewriter_class =
 \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;
 
@@ -857,7 +858,7 @@ write_case_uncompressed (struct sfm_writer *w, struct ccase *c)
 
 /* 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;
 
index c6128d45677009a5cff5cff45e249a5cd53c658f..fdff49fe52a165d02488e51d67c0efd758e3047b 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -31,7 +31,6 @@ struct sfm_write_options
 
 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);
index 08b43139e9ff118de981f61808f4bea52ea52d12..2a73cade41bbcf6e4c55622c5d00b9d8b18505b6 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -178,14 +178,15 @@ trns_chain_next (struct trns_chain *chain)
   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;
 
index 0a8c53e2c8bc33c571d7e0cffef3fac7d31099a3..59001f1139da18a544775337b9921baa435b7e6c 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -33,7 +33,7 @@ enum trns_result
 
 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. */
@@ -47,8 +47,9 @@ bool trns_chain_is_empty (const struct trns_chain *);
 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 *);
 
index 61c450a52359b76683a5c7f9c6ca926801c8c032..b3b6135f6ec4336e26a30e71da855d25c41d1e4f 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -240,7 +240,7 @@ do_if_finalize_func (void *do_if_ UNUSED)
    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;
@@ -250,7 +250,7 @@ do_if_trns_proc (void *do_if_, struct ccase *c, casenumber case_num UNUSED)
     {
       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)
@@ -279,7 +279,8 @@ do_if_trns_free (void *do_if_)
 
 /* 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_;
 
index 40a33c11bbafc451adddb40f9529356ed12c6776..f5d205d4303e864bf2a6203c3f6bc5792bed1657 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -304,21 +304,22 @@ loop_trns_finalize (void *do_if_ UNUSED)
 
 /* 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)
@@ -336,7 +337,7 @@ loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num)
 
   /* 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;
@@ -357,12 +358,12 @@ loop_trns_free (void *loop_)
 
 /* 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. */
@@ -380,11 +381,12 @@ end_loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num UNUSED)
       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;
@@ -395,7 +397,8 @@ end_loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num UNUSED)
 
 /* 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_;
 
index 1451743dc882e651751cc9b3ccdbc2d1b8f1829e..ccbe7679d15a6331c93c7f4054ac168cae9f3c00 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -72,7 +72,7 @@ struct comb_file
     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? */
@@ -98,8 +98,8 @@ struct comb_proc
        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. */
   };
 
@@ -165,7 +165,7 @@ combine_files (enum comb_command_type command,
   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)));
@@ -198,7 +198,7 @@ combine_files (enum comb_command_type command,
       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;
@@ -444,7 +444,7 @@ combine_files (enum comb_command_type command,
       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);
@@ -605,7 +605,7 @@ close_all_comb_files (struct comb_proc *proc)
       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;
@@ -621,12 +621,12 @@ free_comb_proc (struct comb_proc *proc)
   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[]);
@@ -641,7 +641,6 @@ execute_add_files (struct comb_proc *proc)
 
   while (case_matcher_match (proc->matcher, &by))
     {
-      struct ccase output;
       size_t i;
 
       for (i = 0; i < proc->n_files; i++)
@@ -649,9 +648,9 @@ execute_add_files (struct comb_proc *proc)
           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);
             }
         }
     }
@@ -666,25 +665,25 @@ execute_match_files (struct comb_proc *proc)
 
   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);
 }
@@ -699,15 +698,15 @@ execute_update (struct comb_proc *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
@@ -716,9 +715,9 @@ execute_update (struct comb_proc *proc)
            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.  */
@@ -727,9 +726,9 @@ execute_update (struct comb_proc *proc)
           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);
             }
         }
     }
@@ -746,13 +745,13 @@ execute_update (struct comb_proc *proc)
 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;
@@ -760,16 +759,17 @@ scan_table (struct comb_file *file, union value by[])
   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);
@@ -781,6 +781,7 @@ create_output_case (const struct comb_proc *proc, struct ccase *output)
       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.
@@ -788,7 +789,7 @@ create_output_case (const struct comb_proc *proc, struct ccase *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;
 }
@@ -802,11 +803,11 @@ apply_file_case_and_advance (struct comb_file *file, struct ccase *output,
                              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
@@ -828,15 +829,15 @@ output_case (struct comb_proc *proc, struct ccase *output, union value by[])
         {
           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)
         {
@@ -857,8 +858,8 @@ output_buffered_case (struct comb_proc *proc)
   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;
     }
 }
index 7a2a074b59e763eebe322780c96e86f057991ed6..d07eae5c554f7cb19b665175e2a45f9146e08102 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -463,14 +463,15 @@ data_list_trns_free (void *trns_)
   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)
     {
@@ -484,7 +485,7 @@ data_list_trns_proc (void *trns_, struct ccase *c, casenumber case_num UNUSED)
   /* 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;
index dfc04be44c52b2cfc5f09a2b2dfc9432018ca10d..87fd1b7919f6de9de5ec076dd1c1dc794840f47f 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -364,14 +364,17 @@ static bool parse_delimited_no_span (const struct data_parser *,
 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
@@ -746,18 +749,18 @@ data_parser_make_active_file (struct data_parser *parser, struct dataset *ds,
   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
index 609c9b2c92bec4b85894b6ab26daca928b0031d9..c2e5dc0f721438a7af412fc936e19cb20a99b1d1 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -180,35 +180,34 @@ is_valid_state (enum trns_result state)
           || 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
@@ -251,7 +250,7 @@ cmd_end_case (struct lexer *lexer, struct dataset *ds UNUSED)
 
 /* 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_;
@@ -323,7 +322,7 @@ cmd_reread (struct lexer *lexer, struct dataset *ds)
 
 /* 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_;
 
@@ -331,7 +330,7 @@ reread_trns_proc (void *t_, struct ccase *c, casenumber case_num)
     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 "
@@ -368,7 +367,7 @@ cmd_end_file (struct lexer *lexer, struct dataset *ds)
 
 /* 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;
index 8e8bba9b69a281ae707cd021d2bd777e0176bf6f..28820a8504b5fdfc15c8ede3338439ab0f1b4d7a 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -83,7 +83,7 @@ static unsigned n_chars_width (struct outp_driver *d);
 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);
@@ -236,15 +236,15 @@ cmd_list (struct lexer *lexer, struct dataset *ds)
        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);
@@ -265,12 +265,13 @@ static void
 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))
     {
@@ -649,7 +650,8 @@ determine_layout (void)
 
 /* 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;
index c3a2e09a3d93f6f56de75da1a12346ee2329a8b7..3f73ee25a8de16fb1f1883608e2c6fa8cf25fdba 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -102,7 +102,7 @@ cmd_print_space (struct lexer *lexer, struct dataset *ds)
 
 /* 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_;
@@ -111,7 +111,7 @@ print_space_trns_proc (void *t_, struct ccase *c,
   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."));
index 408224afb921acd9900d53b44a092d1a28302725..ab25ec758d784128a09e15c1ebc336f8d7e24ce8 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -450,7 +450,7 @@ static void flush_records (struct print_trns *, int target_record,
 
 /* 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;
@@ -467,7 +467,7 @@ print_trns_proc (void *trns_, struct ccase *c, casenumber case_num UNUSED)
       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);
index e94c020b168d3a59473b396c0c64aa405bcf1877..c34d446225bd250a76687ef736aeed697d7027be 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -326,14 +326,12 @@ parse_write_command (struct lexer *lexer, struct dataset *ds,
   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;
 }
 
index fc5b74a3ab57b7727e96226c785640e5a3e8ee43..91b9c84249b76c0e7d799ad7dc089f66874c314a 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -170,12 +170,9 @@ cmd_debug_evaluate (struct lexer *lexer, struct dataset *dsother UNUSED)
             }
 
           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);
@@ -255,11 +252,7 @@ cmd_debug_evaluate (struct lexer *lexer, struct dataset *dsother UNUSED)
   if (ds)
     destroy_dataset (ds);
 
-  if (c != NULL)
-    {
-      case_destroy (c);
-      free (c);
-    }
+  case_unref (c);
 
   return retval;
 }
index ea640e18e194a27aa1d99cd6676eb495417186e7..2d31bd47182dcb158d9f9c50e644fb03bb7b07bf 100644 (file)
@@ -1,7 +1,7 @@
 // -*- 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
@@ -988,7 +988,7 @@ no_opt string operator STR_VAR ()
 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);
@@ -1001,7 +1001,7 @@ no_opt perm_only function LAG (num_var v, pos_int n_before)
 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);
@@ -1015,7 +1015,7 @@ no_opt perm_only string function LAG (str_var v, pos_int n_before)
      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
@@ -1026,7 +1026,7 @@ no_opt perm_only string function LAG (str_var v)
      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
index 02257f9434f29555bcb2538f5b321a961d099788..c217310910271f2639830eb09d44b2fcdffd69db 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -146,7 +146,7 @@ struct agr_proc
     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. */
@@ -187,7 +187,7 @@ cmd_aggregate (struct lexer *lexer, struct dataset *ds)
 
   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;
@@ -295,18 +295,17 @@ cmd_aggregate (struct lexer *lexer, struct dataset *ds)
        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))
@@ -694,7 +693,7 @@ agr_destroy (struct agr_proc *agr)
 
   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;
@@ -770,20 +769,18 @@ accumulate_aggregate_info (struct agr_proc *agr, const struct ccase *input)
          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:
@@ -916,9 +913,7 @@ accumulate_aggregate_info (struct agr_proc *agr, const struct ccase *input)
 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;
@@ -928,8 +923,8 @@ dump_aggregate_info (struct agr_proc *agr, struct casewriter *output)
       {
         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;
       }
@@ -940,7 +935,7 @@ dump_aggregate_info (struct agr_proc *agr, struct casewriter *output)
 
     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
@@ -1067,7 +1062,7 @@ dump_aggregate_info (struct agr_proc *agr, struct casewriter *output)
       }
   }
 
-  casewriter_write (output, &c);
+  casewriter_write (output, c);
 }
 
 /* Resets the state for all the aggregate functions. */
@@ -1076,8 +1071,8 @@ initialize_aggregate_info (struct agr_proc *agr, const struct ccase *input)
 {
   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)
     {
index af9280b557c5669e4ec0033de09b8c17ca4c2e9d..de9416821c15bf5fa8c37d5e9a241d7a647fd804 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -103,7 +103,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
 {
   struct autorecode_pgm arc;
   struct casereader *input;
-  struct ccase c;
+  struct ccase *c;
   size_t dst_cnt;
   size_t i;
   bool ok;
@@ -189,15 +189,15 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
    }
 
   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)
@@ -300,11 +300,13 @@ recode (struct dataset *ds, const struct autorecode_pgm *arc)
 
 /* 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];
@@ -312,12 +314,12 @@ autorecode_trns_proc (void *trns_, struct ccase *c, casenumber case_idx UNUSED)
       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;
 }
index 35e619bdeeada375af47915199d0c5addcfb2708..15d0e4032a146c094e5275cd21f25cdfadc71afe 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -98,17 +98,17 @@ do_binomial (const struct dictionary *dict,
   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))
@@ -132,7 +132,7 @@ do_binomial (const struct dictionary *dict,
            msg (ME, _("Variable %s is not dichotomous"), var_get_name (var));
        }
 
-      case_destroy (&c);
+      case_unref (c);
     }
   return casereader_destroy (input);
 }
index ed143824187593f984324bc39afeaf810c0080df..19496d7ead9016de96949f5502abfdc6f7576eea 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -57,7 +57,7 @@ create_freq_hash_with_range (const struct dictionary *dict,
 {
   bool warn = true;
   float i_d;
-  struct ccase c;
+  struct ccase *c;
 
   struct hsh_table *freq_hash =
     hsh_create (4, compare_freq, hash_freq,
@@ -78,21 +78,21 @@ create_freq_hash_with_range (const struct dictionary *dict,
       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;
        }
 
@@ -107,7 +107,7 @@ create_freq_hash_with_range (const struct dictionary *dict,
       (*existing_fr)->count += fr->count;
       free (fr);
 
-      case_destroy (&c);
+      case_unref (c);
     }
   if (casereader_destroy (input))
     return freq_hash;
@@ -130,20 +130,20 @@ create_freq_hash (const struct dictionary *dict,
                  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)
index 801b128b8a4ad1c5e0398caa897a4cee0a869f08..60d2faee8b7348c2ffa26f2b911ea705b78b5866 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -177,8 +177,8 @@ static struct pool *pl_col; /* For column data. */
 
 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 *);
 
@@ -305,16 +305,16 @@ internal_cmd_crosstabs (struct lexer *lexer, struct dataset *ds)
   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);
 
@@ -518,12 +518,13 @@ static unsigned hash_table_entry (const void *, const void *);
 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)
@@ -598,7 +599,7 @@ precalc (struct casereader *input, const struct dataset *ds)
 
 /* 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
@@ -672,7 +673,7 @@ calc_general (struct ccase *c, const struct dataset *ds)
 }
 
 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;
 
index 72f7476ae4e89fbc42c6ebe340c134b9b0353b2d..68b19300f6921f80410b7cef01ebe51ab2239876 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -583,7 +583,7 @@ dump_z_table (struct dsc_proc *dsc)
    (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_;
@@ -596,7 +596,7 @@ descriptives_trns_proc (void *trns_, struct ccase * c,
       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;
@@ -605,10 +605,11 @@ descriptives_trns_proc (void *trns_, struct ccase * c,
        }
     }
 
+  *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))
@@ -695,16 +696,17 @@ calc_descriptives (struct dsc_proc *dsc, struct casereader *group,
                    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);
@@ -726,12 +728,12 @@ calc_descriptives (struct dsc_proc *dsc, struct casereader *group,
   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)
@@ -742,7 +744,7 @@ calc_descriptives (struct dsc_proc *dsc, struct casereader *group,
       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))
             {
@@ -768,18 +770,18 @@ calc_descriptives (struct dsc_proc *dsc, struct casereader *group,
   /* 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;
index 312547f3f67132380f33d9a204d7049cfb1a670f..b564ba4415991aa1593f828fcdfc197635e6437d 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -369,14 +369,14 @@ np_plot (struct np *np, const char *label)
   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);
   }
@@ -866,7 +866,7 @@ static void
 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;
@@ -878,20 +878,21 @@ examine_group (struct cmd_examine *cmd, struct casereader *reader, int level,
     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)
@@ -927,33 +928,33 @@ examine_group (struct cmd_examine *cmd, struct casereader *reader, int level,
 
 
       /* 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);
@@ -1028,7 +1029,7 @@ examine_group (struct cmd_examine *cmd, struct casereader *reader, int level,
   /* 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)
@@ -1059,18 +1060,18 @@ examine_group (struct cmd_examine *cmd, struct casereader *reader, int level,
          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);
     }
@@ -1106,17 +1107,18 @@ run_examine (struct cmd_examine *cmd, struct casereader *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);
 
index ccb84dd8a4f37abecb352a2bf04dc92f95b71602..7583374b22874c530f3047d0adafca477f391247 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -88,7 +88,7 @@ cmd_flip (struct lexer *lexer, struct dataset *ds)
   struct flip_pgm *flip;
   struct casereader *input, *reader;
   union value *output_buf;
-  struct ccase c;
+  struct ccase *c;
   size_t i;
   bool ok;
 
@@ -169,10 +169,10 @@ cmd_flip (struct lexer *lexer, struct dataset *ds)
   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;
@@ -464,26 +464,25 @@ flip_file (struct flip_pgm *flip)
   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));
@@ -492,14 +491,14 @@ flip_casereader_read (struct casereader *reader UNUSED, void *flip_,
           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.
index 94b2bcf9e6edd2303632342d6fa8e80304c62018..cd370be821c8db73f2d88da8350613a7ea8c07b0 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -376,11 +376,11 @@ internal_cmd_frequencies (struct lexer *lexer, struct dataset *ds)
   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);
@@ -535,13 +535,14 @@ calc (const struct ccase *c, const struct dataset *ds)
 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);
index d6b4952c289532b0c0974ef0183b5b93585a4af3..07ee7ab53166fcbd917a79933f18eaf9761b8ea8 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -184,20 +184,21 @@ run_glm (struct casereader *input,
   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)
     {
@@ -237,12 +238,12 @@ run_glm (struct casereader *input,
       
       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);
index c752d503bbbde6af9eeb0bd3036656e6de2c6019..04c83e1a0ed694456d3518e5c9ccad30101a2abb 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -45,7 +45,7 @@ npar_summary_calc_descriptives (struct descriptives *desc,
       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;
 
@@ -54,14 +54,14 @@ npar_summary_calc_descriptives (struct descriptives *desc,
                                                &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);
 
index b2e77f45d06a29ba3f4574406232b9f606ea28fb..be57eb24d5fbf6ac9830f5582655bd1028f89f30 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -894,15 +894,16 @@ run_oneway (struct cmd_oneway *cmd,
   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));
 
@@ -923,13 +924,13 @@ run_oneway (struct cmd_oneway *cmd,
   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));
@@ -938,7 +939,7 @@ run_oneway (struct cmd_oneway *cmd,
        {
          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;
index d3ee3707a4437112e84059270c2d16af7f11370c..3bbd39d1e0b0ea26ff7c1b78d67a2db35b5d8f4f 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -476,7 +476,7 @@ rank_sorted_file (struct casereader *input,
 {
   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;
@@ -489,8 +489,8 @@ rank_sorted_file (struct casereader *input,
   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. */
@@ -507,21 +507,22 @@ rank_sorted_file (struct casereader *input,
                        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);
 
@@ -532,11 +533,12 @@ rank_sorted_file (struct casereader *input,
 
 /* 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;
 }
index 4f6f0b862196b6a7365466147145714f3969bfa9..595e7e750c54d4d996b85b71eb141f87b4ba8d52 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -542,7 +542,7 @@ regression_trns_free (void *t_)
   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;
@@ -563,12 +563,12 @@ regression_trns_pred_proc (void *t_, struct ccase *c,
   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);
@@ -581,7 +581,7 @@ regression_trns_pred_proc (void *t_, struct ccase *c,
   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;
@@ -603,14 +603,15 @@ regression_trns_resid_proc (void *t_, struct ccase *c,
   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);
@@ -821,7 +822,7 @@ prepare_categories (struct casereader *input,
                    struct moments_var *mom)
 {
   int n_data;
-  struct ccase c;
+  struct ccase *c;
   size_t i;
 
   assert (vars != NULL);
@@ -832,7 +833,7 @@ prepare_categories (struct casereader *input,
       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
@@ -841,7 +842,7 @@ prepare_categories (struct casereader *input,
        */
       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
@@ -868,7 +869,7 @@ run_regression (struct casereader *input, struct cmd_regression *cmd,
   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;
@@ -878,13 +879,14 @@ run_regression (struct casereader *input, struct cmd_regression *cmd,
 
   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)
     {
@@ -916,7 +918,7 @@ run_regression (struct casereader *input, struct cmd_regression *cmd,
       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];
@@ -955,18 +957,18 @@ run_regression (struct casereader *input, struct cmd_regression *cmd,
             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
index 8384bb350312100214e33cfcff1b1f5057d70703..25aff211dd739b8d63f8af886a565cadafdde11d 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -304,7 +304,7 @@ run_reliability (struct casereader *input, struct dataset *ds UNUSED,
 {
   int i;
   int si;
-  struct ccase c;
+  struct ccase *c;
   casenumber n_missing ;
   casenumber n_valid = 0;
 
@@ -338,7 +338,7 @@ run_reliability (struct casereader *input, struct dataset *ds UNUSED,
                                          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 ++;
@@ -348,9 +348,9 @@ run_reliability (struct casereader *input, struct dataset *ds UNUSED,
          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);
index 6d6dfd56cc6d0f432c936d52930d2ed85420c186..bc6023c72ebfaf7e08785ecc09dfa9a6b96c7669 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -1799,17 +1799,18 @@ calculate (struct cmd_t_test *cmd,
 
   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,
@@ -1823,8 +1824,8 @@ calculate (struct cmd_t_test *cmd,
   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);
 
@@ -1832,22 +1833,22 @@ calculate (struct cmd_t_test *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,
index 2f5bbea892745a99fb33fdbede97ce6baa29319c..2a05f5d995edd99517db13c8c832918e40d3b430 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -88,7 +88,7 @@ wilcoxon_execute (const struct dataset *ds,
     {
       struct casereader *r = casereader_clone (input);
       struct casewriter *writer;
-      struct ccase c;
+      struct ccase *c;
       struct subcase ordering;
       variable_pair *vp = &t2s->pairs[i];
 
@@ -105,41 +105,37 @@ wilcoxon_execute (const struct dataset *ds,
       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);
@@ -148,7 +144,7 @@ wilcoxon_execute (const struct dataset *ds,
   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,
@@ -156,13 +152,13 @@ wilcoxon_execute (const struct dataset *ds,
                                          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 )
            {
@@ -176,8 +172,6 @@ wilcoxon_execute (const struct dataset *ds,
            }
          else
            NOT_REACHED ();
-
-         case_destroy (&c);
        }
 
       casereader_destroy (rr);
index b3b2856d4262f36c88db1d4142f64a99039892ea..ccfee80579400e3cd618012114a7551b16d60397 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -80,14 +80,15 @@ check_datasheet_casereader (struct mc *mc, struct casereader *reader,
               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);
@@ -95,16 +96,17 @@ check_datasheet_casereader (struct mc *mc, struct casereader *reader,
             }
 
           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);
     }
 }
@@ -253,17 +255,17 @@ datasheet_mc_init (struct mc *mc)
       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);
@@ -371,7 +373,7 @@ datasheet_mc_mutate (struct mc *mc, const void *ods_)
       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);
@@ -379,15 +381,15 @@ datasheet_mc_mutate (struct mc *mc, const void *ods_)
 
           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");
index bd0e492dc00a28f51ea4264a59318fc3d7933048..d5a1c096d68b3ad88c503ab961140c8037b6625e 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -51,7 +51,7 @@ void datasheet_move_columns (struct datasheet *,
 /* 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);
@@ -60,7 +60,7 @@ void datasheet_move_rows (struct datasheet *,
                           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);
index f17798f77722a35cb2597a82f5ecaea4ccfcced7..9f65491ef50afdd1485d74e7faf84d49e635704d 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -112,14 +112,17 @@ cmd_compute (struct lexer *lexer, struct dataset *ds)
 
 /* 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;
 }
@@ -127,17 +130,17 @@ compute_num (void *compute_, struct ccase *c, casenumber case_num)
 /* 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))
@@ -152,8 +155,10 @@ compute_num_vec (void *compute_, struct ccase *c, casenumber case_num)
                  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;
@@ -161,14 +166,18 @@ compute_num_vec (void *compute_, struct ccase *c, casenumber case_num)
 
 /* 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;
 }
@@ -176,18 +185,18 @@ compute_str (void *compute_, struct ccase *c, casenumber case_num)
 /* 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)
         {
@@ -205,8 +214,9 @@ compute_str_vec (void *compute_, struct ccase *c, casenumber case_num)
         }
 
       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));
     }
 
index 1c9b4d65735f9487b147da120585465b7501ea0d..6e234c4b23728fa9e1e886db9a9585e9fd5c5274 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -268,8 +268,8 @@ parse_string_criteria (struct lexer *lexer, struct pool *pool, struct criteria *
 /* 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;
@@ -302,8 +302,8 @@ count_numeric (struct criteria *crit, struct ccase *c)
 }
 
 /* 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;
@@ -325,12 +325,13 @@ count_string (struct criteria *crit, struct ccase *c)
 
 /* 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;
@@ -339,10 +340,10 @@ count_trns_proc (void *trns_, struct ccase *c,
       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;
 }
index ad3425c8a28dadd966ef5a59d26bd618c0f64e20..d1cfabf6676478deb66baca38b371431c5ddd1d6 100644 (file)
@@ -1,5 +1,5 @@
 /* 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;
index bdff1ac5246ed80e9afd428a4ec4518b077a9684..e2074823f9df4185aa9db4bcd29a6c6615e25bd3 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -647,18 +647,19 @@ find_src_string (struct recode_trns *trns, const char *value, const struct varia
 
 /* 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;
 
index 632009eddc84cabb12dc026df09388b0a9136a12..6fbc758c2e1329f41d57d626daa9eb8ca75b495a 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -116,7 +116,7 @@ cmd_sample (struct lexer *lexer, struct dataset *ds)
 
 /* 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_;
index 5576c420fd903ee483ea5f5859e4ee89f31d9727..85f616d536fb3ad39e670f517f9f892488a9a8b8 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -70,11 +70,11 @@ cmd_select_if (struct lexer *lexer, struct dataset *ds)
 
 /* 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);
 }
 
index 3f8ddb29bd0b3c76d524da12c3f273643acfe0ec..7bd582105f940c28ffeb26506d4c5fe941ff728d 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -118,7 +118,7 @@ levene(const struct dictionary *dict,
        enum mv_class exclude)
 {
   struct casereader *pass1, *pass2;
-  struct ccase c;
+  struct ccase *c;
   struct levene_info l;
 
   l.n_dep      = n_dep;
@@ -131,14 +131,14 @@ levene(const struct dictionary *dict,
   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);
 
index b84122982e04f19fedaf1c2a0e542e58214546d0..2ff57c6e5ba6fa0a88a9237f95782cb55332bbd6 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -36,7 +36,7 @@
 struct merge_input
   {
     struct casereader *reader;
-    struct ccase c;
+    struct ccase *c;
   };
 
 struct merge
@@ -111,7 +111,8 @@ read_input_case (struct merge *m, size_t idx)
 {
   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
     {
@@ -144,11 +145,11 @@ do_merge (struct merge *m)
 
       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);
     }
 
index e189b47091faee8304ee1a557042cd0f2cff873c..99584a5105b75879517e4b30982e9d78280a5dd1 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -37,7 +37,7 @@ static void
 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;
 
@@ -56,13 +56,11 @@ acc (struct statistic *s, const struct ccase *cx UNUSED,
   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;
 }
index ca4160f4fdf6f52b09d82972edf10f6d8f4f6703..1b6aa131ea745ba6c0b55b33a54f3a6d39ceddbe 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -113,44 +113,42 @@ order_stats_accumulate (struct order_stats **os, size_t nos,
                        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);
 }
index 9e860c4657a83029fc923e835f30579b39d2ea1c..67aa32d29048fffbb5e7b3c03b371b8db9c88a62 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -48,7 +48,7 @@ struct sort_writer
 
     struct casewriter *run;
     casenumber run_id;
-    struct ccase run_end;
+    struct ccase *run_end;
   };
 
 static struct casewriter_class sort_casewriter_class;
@@ -58,7 +58,7 @@ static void pqueue_destroy (struct pqueue *);
 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 *);
 
@@ -74,7 +74,7 @@ sort_create_writer (const struct subcase *ordering, size_t value_cnt)
   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);
 }
@@ -89,9 +89,9 @@ sort_casewriter_write (struct casewriter *writer UNUSED, void *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));
 }
 
@@ -104,7 +104,7 @@ sort_casewriter_destroy (struct casewriter *writer UNUSED, void *sort_)
   merge_destroy (sort->merge);
   pqueue_destroy (sort->pqueue);
   casewriter_destroy (sort->run);
-  case_destroy (&sort->run_end);
+  case_unref (sort->run_end);
   free (sort);
 }
 
@@ -134,12 +134,12 @@ sort_casewriter_convert_to_reader (struct casewriter *writer, void *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)
@@ -153,10 +153,9 @@ output_record (struct sort_writer *sort)
       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 =
@@ -204,7 +203,7 @@ struct pqueue
 struct pqueue_record
   {
     casenumber id;
-    struct ccase c;
+    struct ccase *c;
     casenumber idx;
   };
 
@@ -238,10 +237,9 @@ pqueue_destroy (struct pqueue *pq)
     {
       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);
@@ -270,15 +268,15 @@ pqueue_push (struct pqueue *pq, struct ccase *c, casenumber id)
 
   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;
 
@@ -289,7 +287,7 @@ pqueue_pop (struct pqueue *pq, struct ccase *c, casenumber *id)
 
   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,
@@ -303,8 +301,7 @@ compare_pqueue_records_minheap (const void *a_, const void *b_,
   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;
index 00e227ecc922a465b939779000a31e69b359ea5e..735d4328c930b276f060f759e7024c687605de3b 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -1607,16 +1607,9 @@ data_sheet_set_clip (PsppireSheet *sheet)
   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);
     }
@@ -1667,8 +1660,10 @@ clip_to_text (void)
   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;
@@ -1677,7 +1672,7 @@ clip_to_text (void)
       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");
        }
@@ -1685,7 +1680,7 @@ clip_to_text (void)
       if ( r < case_cnt)
        g_string_append (string, "\n");
 
-      case_destroy (&cc);
+      case_unref (cc);
     }
 
   return string;
@@ -1710,8 +1705,8 @@ clip_to_html (void)
   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;
@@ -1722,13 +1717,13 @@ clip_to_html (void)
        {
          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");
 
index 37747e07c702d0c179064348ca921384bed8a2af..71d7d5f53976c124fc779a7a56fa127b13eaa09e 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -531,7 +531,7 @@ psppire_data_store_insert_new_case (PsppireDataStore *ds, casenumber posn)
 {
   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) ;
@@ -540,9 +540,9 @@ psppire_data_store_insert_new_case (PsppireDataStore *ds, casenumber posn)
 
   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)
     {
@@ -550,12 +550,12 @@ psppire_data_store_insert_new_case (PsppireDataStore *ds, casenumber posn)
       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;
 }
@@ -837,18 +837,16 @@ get_column_justification (const PsppireSheetModel *model, gint col)
 \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);
 }
 
 
@@ -879,14 +877,13 @@ psppire_data_store_insert_case (PsppireDataStore *ds,
                                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 )
     {
index 44b11725babd667a32bb561a00bc3c6e896f78a7..5ffd85d68e458137b2b7c2cc25177fc3ce38b42b 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -122,9 +122,8 @@ size_t psppire_data_store_get_value_count (const PsppireDataStore *ds);
 
 \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);