#include "libpspp/hmap.h"
#include "libpspp/intern.h"
#include "libpspp/message.h"
+#include "libpspp/pxd.h"
#include "libpspp/str.h"
#include "gl/xalloc.h"
+static void val_labs_uncache__ (struct val_labs *);
+static void val_lab_uncache__ (struct val_lab *);
+
/* Creates and returns a new, empty set of value labels with the
given WIDTH. */
struct val_labs *
HMAP_FOR_EACH (label, struct val_lab, node, &vls->labels)
value_resize (&label->value, vls->width, new_width);
}
- vls->width = new_width;
+ if (vls->width != new_width)
+ {
+ vls->width = new_width;
+ val_labs_uncache__ (vls);
+ }
}
/* Destroys VLS. */
{
if (vls != NULL)
{
+ val_labs_uncache__ (vls);
val_labs_clear (vls);
hmap_destroy (&vls->labels);
free (vls);
}
}
+static void
+val_lab_clear (struct val_lab *lab, int width)
+{
+ val_lab_uncache__ (lab);
+ value_destroy (&lab->value, width);
+ intern_unref (lab->label);
+}
+
/* Removes all the value labels from VLS. */
void
val_labs_clear (struct val_labs *vls)
HMAP_FOR_EACH_SAFE (label, next, struct val_lab, node, &vls->labels)
{
+ val_lab_clear (label, vls->width);
hmap_delete (&vls->labels, &label->node);
- value_destroy (&label->value, vls->width);
- intern_unref (label->label);
- intern_unref (label->escaped_label);
free (label);
}
}
}
}
+static void
+val_labs_uncache__ (struct val_labs *vls UNUSED)
+{
+}
+
+static void
+val_lab_uncache__ (struct val_lab *vl UNUSED)
+{
+}
+
+static struct pxd_object *
+val_lab_save (const struct val_lab *vl, int width, struct pxd *pxd)
+{
+ struct pxd_builder b;
+
+ pxd_builder_init (&b, pxd);
+
+ pxd_builder_put_value (&b, &vl->value, width);
+ pxd_builder_put_interned_string (&b, vl->label);
+
+ return pxd_builder_commit (&b);
+}
+
+struct pxd_object *
+val_labs_save (const struct val_labs *vls, struct pxd *pxd)
+{
+ struct val_lab *label;
+ struct pxd_builder b;
+
+ pxd_builder_init (&b, pxd);
+
+ pxd_builder_put_u32 (&b, vls->width);
+ HMAP_FOR_EACH (label, struct val_lab, node, &vls->labels)
+ pxd_builder_put_link (&b, val_lab_save (label, vls->width, pxd));
+
+ return pxd_builder_commit (&b);
+}
+
+static struct val_lab *
+val_lab_load (struct pxd_object *object, const struct pxd *pxd, int width)
+{
+ struct pxd_parser p;
+ struct val_lab *vl;
+
+ pxd_parser_init (&p, object, pxd);
+
+ vl = xmalloc (sizeof *vl);
+ pxd_parser_get_value (&p, &vl->value, width);
+ vl->label = pxd_parser_get_interned_string (&p);
+
+ pxd_parser_destroy (&p);
+
+ return vl;
+}
+
+struct val_labs *
+val_labs_load (struct pxd_object *object, const struct pxd *pxd)
+{
+ struct val_labs *vls;
+ struct pxd_parser p;
+ unsigned int i;
+ int width;
+
+ pxd_parser_init (&p, object, pxd);
+ width = pxd_parser_get_u32 (&p);
+
+ vls = val_labs_create (width);
+ for (i = 0; i < pxd_object_get_n_links (object); i++)
+ {
+ struct pxd_object *lab_obj = pxd_object_get_link (object, i, pxd);
+ struct val_lab *lab = val_lab_load (lab_obj, pxd, width);
+ hmap_insert (&vls->labels, &lab->node,
+ value_hash (&lab->value, width, 0));
+ }
+
+ pxd_parser_destroy (&p);
+
+ return vls;
+}
+\f
static void
do_add_val_lab (struct val_labs *vls, const union value *value,
const char *escaped_label)
struct val_lab *vl = val_labs_lookup (vls, value);
if (vl != NULL)
{
+ val_lab_uncache__ (vl);
intern_unref (vl->label);
intern_unref (vl->escaped_label);
set_label (vl, label);
void
val_labs_remove (struct val_labs *vls, struct val_lab *label)
{
+ val_lab_clear (label, vls->width);
hmap_delete (&vls->labels, &label->node);
- value_destroy (&label->value, vls->width);
- intern_unref (label->label);
- intern_unref (label->escaped_label);
free (label);
}