pxd: initial work
[pspp] / src / data / dictionary.c
index 4eaaefae18ed9ae4889275bccd00b0e568c26e8d..7cf2a7917de2e74cb85e8ac7db01ccad356246c4 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2007, 2009-2015 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
@@ -41,6 +41,7 @@
 #include "libpspp/message.h"
 #include "libpspp/misc.h"
 #include "libpspp/pool.h"
+#include "libpspp/pxd.h"
 #include "libpspp/str.h"
 #include "libpspp/string-array.h"
 
@@ -87,6 +88,8 @@ struct dictionary
 static void dict_unset_split_var (struct dictionary *, struct variable *);
 static void dict_unset_mrset_var (struct dictionary *, struct variable *);
 
+static void dict_uncache (struct dictionary *);
+
 /* Returns the encoding for data in dictionary D.  The return value is a
    nonnull string that contains an IANA character set name. */
 const char *
@@ -255,6 +258,8 @@ dict_clone (const struct dictionary *s)
 void
 dict_clear (struct dictionary *d)
 {
+  dict_uncache (d);
+
   /* FIXME?  Should we really clear case_limit, label, documents?
      Others are necessarily cleared by deleting all the variables.*/
   while (d->var_cnt > 0 )
@@ -1674,3 +1679,166 @@ vardict_get_dict_index (const struct vardict_info *vardict)
 {
   return vardict - vardict->dict->var;
 }
+\f
+static struct pxd_object *
+vardict_info_save (const struct vardict_info *vardict, struct pxd *pxd)
+{
+  struct pxd_builder b;
+
+  pxd_builder_init (&b, pxd);
+  pxd_builder_put_s32 (&b, vardict->case_index);
+  pxd_builder_put_link (&b, var_save (vardict->var, pxd));
+  return pxd_builder_commit (&b);
+}
+
+struct pxd_object *
+dict_save (const struct dictionary *dict, struct pxd *pxd)
+{
+  struct pxd_array_builder ab;
+  struct pxd_object *vars;
+  struct pxd_builder b;
+  size_t i;
+
+  pxd_array_builder_init (&ab, pxd);
+  for (i = 0; i < dict->var_cnt; i++)
+    pxd_array_builder_add (&ab, vardict_info_save (&dict->var[i], pxd));
+  vars = pxd_array_builder_commit (&ab);
+
+  pxd_builder_init (&b, pxd);
+  pxd_builder_put_link (&b, vars);
+  pxd_builder_put_u32 (&b, dict->next_value_idx);
+
+  pxd_builder_put_size_t (&b, dict->split_cnt);
+  for (i = 0; i < dict->split_cnt; i++)
+    pxd_builder_put_u32 (&b, var_get_dict_index (dict->split[i]));
+
+  pxd_builder_put_s32 (&b,
+                       (dict->weight == NULL ? -1
+                        : var_get_dict_index (dict->weight)));
+  pxd_builder_put_s32 (&b,
+                       (dict->filter == NULL ? -1
+                        : var_get_dict_index (dict->filter)));
+
+  pxd_builder_put_casenumber (&b, dict->case_limit);
+  pxd_builder_put_string (&b, dict->label != NULL ? dict->label : "");
+  //XXX pxd_builder_put_string (&b, ds_cstr (&dict->documents));
+
+  pxd_builder_put_size_t (&b, dict->vector_cnt);
+  for (i = 0; i < dict->split_cnt; i++)
+    pxd_builder_put_link (&b, vector_save (dict->vector[i], pxd));
+
+  pxd_builder_put_link (&b, attrset_save (&dict->attributes, pxd));
+
+  pxd_builder_put_size_t (&b, dict->n_mrsets);
+  for (i = 0; i < dict->n_mrsets; i++)
+    pxd_builder_put_link (&b, mrset_save (dict->mrsets[i], pxd));
+
+  pxd_builder_put_string (&b, dict->encoding ? dict->encoding : "");
+
+  return pxd_builder_commit (&b);
+}
+
+static void
+vardict_info_load (struct dictionary *dict, struct pxd_object *obj,
+                   const struct pxd *pxd)
+{
+  struct pxd_parser p;
+  struct variable *var;
+  int case_index;
+
+  pxd_parser_init (&p, obj, pxd);
+  case_index = pxd_parser_get_u32 (&p);
+  var = add_var (dict, var_load (pxd_parser_get_link (&p), pxd));
+  var_get_vardict (var)->case_index = case_index;
+  pxd_parser_destroy (&p);
+}
+
+struct dictionary *
+dict_load (struct pxd_object *obj, const struct pxd *pxd)
+{
+  struct dictionary *dict;
+  struct pxd_array array;
+  struct pxd_parser p;
+  char *encoding;
+  int weight_idx;
+  int filter_idx;
+  size_t i;
+
+  pxd_parser_init (&p, obj, pxd);
+
+  encoding = pxd_parser_get_string (&p);
+  dict = dict_create (encoding);
+  free (encoding);
+
+  pxd_array_init (&array, pxd_parser_get_link (&p), pxd);
+  for (i = 0; i < pxd_array_size (&array); i++)
+    vardict_info_load (dict, pxd_array_get (&array, i), pxd);
+  pxd_array_destroy (&array);
+
+  dict->next_value_idx = pxd_parser_get_u32 (&p);
+
+  dict->split_cnt = pxd_parser_get_size_t (&p);
+  if (dict->split_cnt > 0)
+    {
+      dict->split = xnmalloc (dict->split_cnt, sizeof *dict->split);
+      for (i = 0; i < dict->split_cnt; i++)
+        dict->split[i] = dict_get_var (dict, i);
+    }
+
+  weight_idx = pxd_parser_get_s32 (&p);
+  if (weight_idx >= 0)
+    dict_set_weight (dict, dict_get_var (dict, weight_idx));
+
+  filter_idx = pxd_parser_get_s32 (&p);
+  if (filter_idx >= 0)
+    dict_set_filter (dict, dict_get_var (dict, filter_idx));
+
+  dict->case_limit = pxd_parser_get_casenumber (&p);
+
+  dict->label = pxd_parser_get_string (&p);
+  if (dict->label[0] == '\0')
+    dict_set_label (dict, NULL);
+
+#if 0                           /* XXX */
+  documents = pxd_parser_get_string (&p);
+  if (documents[0] != '\0')
+    ds_assign_cstr (&dict->documents, documents);
+  free (documents);
+#endif
+
+  dict->vector_cnt = pxd_parser_get_size_t (&p);
+  if (dict->vector_cnt > 0)
+    {
+      dict->vector = xnmalloc (dict->vector_cnt, sizeof *dict->vector);
+      for (i = 0; i < dict->vector_cnt; i++)
+        dict->vector[i] = vector_load (pxd_parser_get_link (&p), pxd, dict);
+    }
+
+  attrset_destroy (&dict->attributes);
+  attrset_load (&dict->attributes, pxd_parser_get_link (&p), pxd);
+
+  dict->n_mrsets = pxd_parser_get_size_t (&p);
+  if (dict->n_mrsets > 0)
+    {
+      dict->mrsets = xnmalloc (dict->n_mrsets, sizeof *dict->mrsets);
+      for (i = 0; i < dict->n_mrsets; i++)
+        dict->mrsets[i] = mrset_load (pxd_parser_get_link (&p), pxd, dict);
+    }
+
+  dict->encoding = pxd_parser_get_string (&p);
+  if (dict->encoding[0] == '\0')
+    {
+      free (dict->encoding);
+      dict->encoding = NULL;
+    }
+
+  pxd_parser_destroy (&p);
+
+  return dict;
+}
+
+static void
+dict_uncache (struct dictionary *dict UNUSED)
+{
+}
+