X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fattributes.c;fp=src%2Fdata%2Fattributes.c;h=b04ebf0693ebe354be103a48c00b4f2ee0c37cc2;hb=52c54183e360053b1845e46cb96cd44a0cf96040;hp=c4ae97c285928ed6e701cc6594fe0fefed5824c7;hpb=2ca3267c1110bbff675c560b19d02defb96ee2f9;p=pspp diff --git a/src/data/attributes.c b/src/data/attributes.c index c4ae97c285..b04ebf0693 100644 --- a/src/data/attributes.c +++ b/src/data/attributes.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2008, 2009, 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010, 2011, 2012, 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 @@ -22,8 +22,10 @@ #include #include "libpspp/array.h" +#include "libpspp/compiler.h" #include "libpspp/hash-functions.h" #include "libpspp/i18n.h" +#include "libpspp/pxd.h" #include "gl/xalloc.h" @@ -36,13 +38,17 @@ set. */ struct attribute { + struct attrset *set; /* Containing set, if any. */ struct hmap_node node; /* Used by attrset. */ + char *name; /* Name. */ char **values; /* Each value. */ size_t n_values; /* Number of values. */ size_t allocated_values; /* Amount of allocated space for values. */ }; +static void attrset_uncache__ (struct attrset *); + /* Creates and returns a new attribute with the given NAME. The attribute initially has no values. (Attributes with no values cannot be saved to system files, so at least one value should @@ -52,6 +58,7 @@ struct attribute * attribute_create (const char *name) { struct attribute *attr = xmalloc (sizeof *attr); + attr->set = NULL; attr->name = xstrdup (name); attr->values = NULL; attr->n_values = 0; @@ -84,6 +91,8 @@ attribute_destroy (struct attribute *attr) { size_t i; + assert (attr->set == NULL); + for (i = 0; i < attr->n_values; i++) free (attr->values[i]); free (attr->values); @@ -122,6 +131,8 @@ attribute_get_n_values (const struct attribute *attrs) void attribute_add_value (struct attribute *attr, const char *value) { + attrset_uncache__ (attr->set); + if (attr->n_values >= attr->allocated_values) attr->values = x2nrealloc (attr->values, &attr->allocated_values, sizeof *attr->values); @@ -138,6 +149,8 @@ attribute_add_value (struct attribute *attr, const char *value) void attribute_set_value (struct attribute *attr, size_t index, const char *value) { + attrset_uncache__ (attr->set); + if (index < attr->n_values) { /* Replace existing value. */ @@ -162,6 +175,8 @@ attribute_set_value (struct attribute *attr, size_t index, const char *value) void attribute_del_value (struct attribute *attr, size_t index) { + attrset_uncache__ (attr->set); + if (index < attr->n_values) { free (attr->values[index]); @@ -170,6 +185,49 @@ attribute_del_value (struct attribute *attr, size_t index) attr->n_values--; } } + +struct pxd_object * +attribute_save (const struct attribute *attr, struct pxd *pxd) +{ + struct pxd_builder b; + size_t i; + + pxd_builder_init (&b, pxd); + + pxd_builder_put_string (&b, attr->name); + pxd_builder_put_size_t (&b, attr->n_values); + for (i = 0; i < attr->n_values; i++) + pxd_builder_put_string (&b, attr->values[i]); + + return pxd_builder_commit (&b); +} + +struct attribute * +attribute_load (struct pxd_object *object, const struct pxd *pxd) +{ + struct attribute *attr; + struct pxd_parser p; + size_t n, i; + char *name; + + pxd_parser_init (&p, object, pxd); + + name = pxd_parser_get_string (&p); + attr = attribute_create (name); + free (name); + + n = pxd_parser_get_size_t (&p); + for (i = 0; i < n; i++) + { + char *value = pxd_parser_get_string (&p); + attribute_add_value (attr, value); + free (value); + } + + pxd_parser_destroy (&p); + + return attr; +} /* Initializes SET as a new, initially empty attibute set. */ void @@ -203,8 +261,13 @@ attrset_destroy (struct attrset *set) { struct attribute *attr, *next; + attrset_uncache__ (set); + HMAP_FOR_EACH_SAFE (attr, next, struct attribute, node, &set->map) - attribute_destroy (attr); + { + attr->set = NULL; + attribute_destroy (attr); + } hmap_destroy (&set->map); } } @@ -237,7 +300,13 @@ void attrset_add (struct attrset *set, struct attribute *attr) { const char *name = attribute_get_name (attr); + assert (attrset_lookup (set, name) == NULL); + assert (attr->set == NULL); + + attrset_uncache__ (set); + + attr->set = set; hmap_insert (&set->map, &attr->node, utf8_hash_case_string (name, 0)); } @@ -249,7 +318,9 @@ attrset_delete (struct attrset *set, const char *name) struct attribute *attr = attrset_lookup (set, name); if (attr != NULL) { + attrset_uncache__ (set); hmap_delete (&set->map, &attr->node); + attr->set = NULL; attribute_destroy (attr); } } @@ -258,8 +329,45 @@ attrset_delete (struct attrset *set, const char *name) void attrset_clear (struct attrset *set) { - attrset_destroy (set); + if (!hmap_is_empty (&set->map)) + { + attrset_destroy (set); + attrset_init (set); + } +} + +struct pxd_object * +attrset_save (const struct attrset *set, struct pxd *pxd) +{ + struct attribute *attr; + struct pxd_builder b; + + pxd_builder_init (&b, pxd); + + HMAP_FOR_EACH (attr, struct attribute, node, &set->map) + pxd_builder_put_link (&b, attribute_save (attr, pxd)); + + return pxd_builder_commit (&b); +} + +void +attrset_load (struct attrset *set, + struct pxd_object *object, const struct pxd *pxd) +{ + struct pxd_parser p; + unsigned int i; + + pxd_parser_init (&p, object, pxd); + attrset_init (set); + for (i = 0; i < pxd_object_get_n_links (object); i++) + { + struct pxd_object *attr_obj = pxd_object_get_link (object, i, pxd); + struct attribute *attr = attribute_load (attr_obj, pxd); + attrset_add (set, attr); + } + + pxd_parser_destroy (&p); } static struct attribute *iterator_data (struct attrset_iterator *iterator) @@ -335,3 +443,10 @@ attrset_sorted (const struct attrset *set) else return NULL; } + +static void +attrset_uncache__ (struct attrset *set UNUSED) +{ + /* XXX */ +} +