casereader: Implement save, load.
[pspp] / src / data / case.c
index dc4029268ebf981bc10d96ecccf7c88eb53dd71a..d36f66a6ae46385a44ab5a2a9024678a0bf6f674 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2004, 2007, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2007, 2009, 2010, 2011, 2013 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
 #include <config.h>
 
-#include <data/case.h>
+#include "data/case.h"
 
 #include <limits.h>
 #include <stddef.h>
 #include <stdlib.h>
 
-#include <data/value.h>
-#include <data/variable.h>
-#include <libpspp/assertion.h>
-#include <libpspp/str.h>
+#include "data/value.h"
+#include "data/variable.h"
+#include "libpspp/assertion.h"
+#include "libpspp/str.h"
 
-#include "minmax.h"
-#include "xalloc.h"
+#include "gl/minmax.h"
+#include "gl/xalloc.h"
+
+/* Set this flag to 1 to copy cases instead of ref counting them.
+   This is sometimes helpful in debugging situations. */
+#define DEBUG_CASEREFS 0
+
+#if DEBUG_CASEREFS
+#warning "Caseref debug enabled.  CASES ARE NOT BEING SHARED!!"
+#endif
 
 static size_t case_size (const struct caseproto *);
 static bool variable_matches_case (const struct ccase *,
@@ -80,6 +88,19 @@ case_clone (const struct ccase *c)
   return case_unshare (case_ref (c));
 }
 
+/* Increments case C's reference count and returns C.  Afterward,
+   case C is shared among its reference count holders. */
+struct ccase *
+case_ref (const struct ccase *c_)
+{
+  struct ccase *c = CONST_CAST (struct ccase *, c_);
+  c->ref_cnt++;
+#if DEBUG_CASEREFS
+  c = case_unshare__ (c);
+#endif
+  return c;
+}
+
 /* Returns an estimate of the number of bytes of memory that
    would be consumed in creating a case based on PROTO.  The
    estimate includes typical overhead from malloc() in addition
@@ -414,6 +435,49 @@ case_data_all_rw (struct ccase *c)
   return c->values;
 }
 
+struct pxd_object *
+case_save (const struct ccase *c, struct pxd *pxd)
+{
+  struct pxd_builder b;
+  size_t i;
+
+  pxd_builder_init (&b, pxd);
+
+  pxd_builder_put_link (&b, caseproto_save (c->proto, pxd));
+  for (i = 0; i < caseproto_get_n_widths (c->proto); i++)
+    {
+      int width = caseproto_get_width (c->proto, i);
+      if (width >= 0)
+        pxd_builder_put_value (&b, case_data_idx (c, i), width);
+    }
+
+  return pxd_builder_commit (&b);
+}
+
+struct ccase *
+case_load (struct pxd_object *object, const struct pxd *pxd)
+{
+  struct caseproto *proto;
+  struct pxd_parser p;
+  struct ccase *c;
+  size_t i;
+
+  pxd_parser_init (&p, object, pxd);
+
+  proto = caseproto_load (pxd_parser_get_link (&p), pxd);
+  c = case_create (proto);
+
+  for (i = 0; i < caseproto_get_n_widths (proto); i++)
+    pxd_parser_get_value (&p, case_data_rw_idx (c, i),
+                          caseproto_get_width (proto, i));
+
+  caseproto_unref (proto);
+
+  pxd_parser_destroy (&p);
+
+  return c;
+}
+
 /* Internal helper function for case_unshare. */
 struct ccase *
 case_unshare__ (struct ccase *old)