pxd: initial work
[pspp] / src / data / missing-values.c
index 0fc9d01af01ae5a7842aebf3a8285217485de3ca..aa029a4f4d443e7f5dbd7a4ae2b8e99fedff2471 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2005, 2009, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2009, 2011-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
@@ -23,6 +23,8 @@
 
 #include "data/variable.h"
 #include "libpspp/assertion.h"
+#include "libpspp/cast.h"
+#include "libpspp/pxd.h"
 #include "libpspp/str.h"
 
 /* Types of user-missing values.
@@ -158,19 +160,23 @@ mv_add_value (struct missing_values *mv, const union value *v)
   NOT_REACHED ();
 }
 
-/* Attempts to add S to the set of string missing values MV.  S
-   must contain exactly as many characters as MV's width.
-   Returns true if successful, false if MV has no more room for
+/* Attempts to add S, which is LEN bytes long, to the set of string missing
+   values MV.  Returns true if successful, false if MV has no more room for
    missing values or if S is not an acceptable missing value. */
 bool
-mv_add_str (struct missing_values *mv, const uint8_t s[])
+mv_add_str (struct missing_values *mv, const uint8_t s[], size_t len)
 {
   union value v;
   bool ok;
 
   assert (mv->width > 0);
+  while (len > mv->width)
+    if (s[--len] != ' ')
+      return false;
+
   value_init (&v, mv->width);
-  memcpy (value_str_rw (&v, mv->width), s, mv->width);
+  buf_copy_rpad (CHAR_CAST (char *, value_str_rw (&v, mv->width)), mv->width,
+                 CHAR_CAST (char *, s), len, ' ');
   ok = mv_add_value (mv, &v);
   value_destroy (&v, mv->width);
 
@@ -465,3 +471,40 @@ mv_is_str_missing (const struct missing_values *mv, const uint8_t s[],
   assert (mv->width > 0);
   return class & MV_USER && is_str_user_missing (mv, s);
 }
+
+struct pxd_object *
+mv_save (const struct missing_values *mv, struct pxd *pxd)
+{
+  struct pxd_builder b;
+  int i;
+
+  pxd_builder_init (&b, pxd);
+
+  pxd_builder_put_u16 (&b, mv->width);
+  pxd_builder_put_u16 (&b, mv->type);
+  for (i = 0; i < 3; i++)
+    if (using_element (mv->type, i))
+      pxd_builder_put_value (&b, &mv->values[i], mv->width);
+
+  return pxd_builder_commit (&b);
+}
+
+void
+mv_load (struct missing_values *mv, struct pxd_object *object,
+         const struct pxd *pxd)
+{
+  struct pxd_parser p;
+  int i;
+
+  pxd_parser_init (&p, object, pxd);
+
+  mv->width = pxd_parser_get_u16 (&p);
+  mv->type = pxd_parser_get_u16 (&p);
+  for (i = 0; i < 3; i++)
+    if (using_element (mv->type, i))
+      pxd_parser_get_value (&p, &mv->values[i], mv->width);
+    else
+      value_init (&mv->values[i], mv->width);
+
+  pxd_parser_destroy (&p);
+}