X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fvariable.c;h=f22bc522e4bee26924071062256fbf814e4c9eae;hb=52c54183e360053b1845e46cb96cd44a0cf96040;hp=971154368cb7ae5ede7b21d4f88374e6f1e4b752;hpb=2ca3267c1110bbff675c560b19d02defb96ee2f9;p=pspp diff --git a/src/data/variable.c b/src/data/variable.c index 971154368c..f22bc522e4 100644 --- a/src/data/variable.c +++ b/src/data/variable.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 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 @@ -33,8 +33,10 @@ #include "libpspp/compiler.h" #include "libpspp/hash-functions.h" #include "libpspp/i18n.h" +#include "libpspp/intern.h" #include "libpspp/message.h" #include "libpspp/misc.h" +#include "libpspp/pxd.h" #include "libpspp/str.h" #include "gl/minmax.h" @@ -76,6 +78,8 @@ struct variable /* Custom attributes. */ struct attrset attributes; }; + +static void var_uncache (struct variable *); static void var_set_print_format_quiet (struct variable *v, const struct fmt_spec *print); @@ -121,6 +125,7 @@ var_destroy (struct variable *v) if (v != NULL) { assert (!var_has_vardict (v)); + var_uncache (v); mv_destroy (&v->miss); var_clear_short_names (v); val_labs_destroy (v->val_labs); @@ -156,6 +161,7 @@ var_set_name_quiet (struct variable *v, const char *name) v->name = xstrdup (name); ds_destroy (&v->name_and_label); ds_init_empty (&v->name_and_label); + var_uncache (v); } /* Sets V's name to NAME, a UTF-8 encoded string. @@ -305,6 +311,8 @@ var_set_width_and_formats (struct variable *v, int new_width, if (traits != 0) dict_var_changed (v, traits, ov); + + var_uncache (v); } /* Changes the width of V to NEW_WIDTH. @@ -440,8 +448,14 @@ var_has_value_labels (const struct variable *v) static void var_set_value_labels_quiet (struct variable *v, const struct val_labs *vls) { - val_labs_destroy (v->val_labs); - v->val_labs = NULL; + bool changed = false; + + if (v->val_labs != NULL) + { + val_labs_destroy (v->val_labs); + v->val_labs = NULL; + changed = true; + } if (vls != NULL) { @@ -449,6 +463,9 @@ var_set_value_labels_quiet (struct variable *v, const struct val_labs *vls) v->val_labs = val_labs_clone (vls); val_labs_set_width (v->val_labs, v->width); } + + if (changed) + var_uncache (v); } @@ -483,8 +500,14 @@ bool var_add_value_label (struct variable *v, const union value *value, const char *label) { + bool changed; + alloc_value_labels (v); - return val_labs_add (v->val_labs, value, label); + + changed = val_labs_add (v->val_labs, value, label); + if (changed) + var_uncache (v); + return changed; } /* Adds or replaces a value label with the given VALUE and UTF-8 encoded LABEL @@ -497,6 +520,7 @@ var_replace_value_label (struct variable *v, { alloc_value_labels (v); val_labs_replace (v->val_labs, value, label); + var_uncache (v); } /* Removes V's value labels, if any. */ @@ -585,6 +609,7 @@ var_set_print_format_quiet (struct variable *v, const struct fmt_spec *print) { assert (fmt_check_width_compat (print, v->width)); v->print = *print; + var_uncache (v); } } @@ -598,6 +623,7 @@ var_set_print_format (struct variable *v, const struct fmt_spec *print) struct variable *ov = var_clone (v); var_set_print_format_quiet (v, print); dict_var_changed (v, VAR_TRAIT_PRINT_FORMAT, ov); + var_uncache (v); } /* Returns V's write format specification. */ @@ -618,6 +644,7 @@ var_set_write_format_quiet (struct variable *v, const struct fmt_spec *write) { assert (fmt_check_width_compat (write, v->width)); v->write = *write; + var_uncache (v); } } @@ -727,10 +754,9 @@ var_set_label_quiet (struct variable *v, const char *label) ds_destroy (&v->name_and_label); ds_init_empty (&v->name_and_label); + var_uncache (v); } - - /* Sets V's variable label to UTF-8 encoded string LABEL, stripping off leading and trailing white space. If LABEL is a null pointer or if LABEL is an empty string (after stripping white space), then V's variable label (if any) @@ -823,7 +849,6 @@ var_set_measure_quiet (struct variable *v, enum measure measure) v->measure = measure; } - /* Sets V's measurement level to MEASURE. */ void var_set_measure (struct variable *v, enum measure measure) @@ -1173,13 +1198,17 @@ var_set_short_name (struct variable *var, size_t idx, const char *short_name) void var_clear_short_names (struct variable *v) { - size_t i; - - for (i = 0; i < v->short_name_cnt; i++) - free (v->short_names[i]); - free (v->short_names); - v->short_names = NULL; - v->short_name_cnt = 0; + if (v->short_name_cnt > 0) + { + size_t i; + + for (i = 0; i < v->short_name_cnt; i++) + free (v->short_names[i]); + free (v->short_names); + v->short_names = NULL; + v->short_name_cnt = 0; + var_uncache (v); + } } /* Relationship with dictionary. */ @@ -1221,6 +1250,7 @@ var_set_attributes_quiet (struct variable *v, const struct attrset *attrs) { attrset_destroy (&v->attributes); attrset_clone (&v->attributes, attrs); + var_uncache (v); } /* Replaces variable V's attributes set by a copy of ATTRS. */ @@ -1312,3 +1342,125 @@ var_clear_vardict (struct variable *v) { v->vardict = NULL; } + +struct pxd_object * +var_save (const struct variable *var, struct pxd *pxd) +{ + struct pxd_builder b; + size_t i; + + pxd_builder_init (&b, pxd); + + pxd_builder_put_string (&b, var->name); + pxd_builder_put_u16 (&b, var->width); + pxd_builder_put_link (&b, mv_save (&var->miss, pxd)); + pxd_builder_put_u32 (&b, fmt_to_uint (&var->print)); + pxd_builder_put_u32 (&b, fmt_to_uint (&var->write)); + + if (var_has_value_labels (var)) + { + pxd_builder_put_bool (&b, true); + pxd_builder_put_link (&b, val_labs_save (var->val_labs, pxd)); + } + else + pxd_builder_put_bool (&b, false); + + pxd_builder_put_string (&b, var->label != NULL ? var->label : ""); + + pxd_builder_put_u8 (&b, var->measure); + pxd_builder_put_u32 (&b, var->display_width); + pxd_builder_put_u8 (&b, var->alignment); + + pxd_builder_put_bool (&b, var->leave); + + pxd_builder_put_size_t (&b, var->short_name_cnt); + for (i = 0; i < var->short_name_cnt; i++) + pxd_builder_put_string (&b, var->short_names[i]); + + pxd_builder_put_link (&b, attrset_save (&var->attributes, pxd)); + + return pxd_builder_commit (&b); +} + +struct variable * +var_load (struct pxd_object *object, const struct pxd *pxd) +{ + struct fmt_spec print, write; + struct missing_values mv; + struct variable *var; + struct pxd_parser p; + char *label; + char *name; + int width; + size_t i; + +#if 0 + cached_var = pxd_cache_search (&var_cache, pxd_object_id (object)); + if (cached_var != NULL) + { + size_t n; + + var = var_clone (cached_var); + + /* var_clone() doesn't copy short names, so we need to. */ + n = cached_var->short_name_cnt; + if (n > 0) + { + size_t i; + + var->short_name_cnt = n; + var->short_names = xmalloc (n * sizeof *var->short_names); + for (i = 0; i < n; i++) + var->short_names[i] = xstrdup (cached_var->short_names[i]); + } + + return var; + } +#endif + + pxd_parser_init (&p, object, pxd); + + name = pxd_parser_get_string (&p); + width = pxd_parser_get_u16 (&p); + var = var_create (name, width); + + mv_load (&mv, pxd_parser_get_link (&p), pxd); + var_set_missing_values (var, &mv); + mv_destroy (&mv); + + fmt_from_uint (&print, pxd_parser_get_u32 (&p)); + var_set_print_format (var, &print); + + fmt_from_uint (&write, pxd_parser_get_u32 (&p)); + var_set_write_format (var, &write); + + if (pxd_parser_get_bool (&p)) + var->val_labs = val_labs_load (pxd_parser_get_link (&p), pxd); + + label = pxd_parser_get_string (&p); + if (label[0]) + var_set_label (var, label); + free (label); + + var->measure = pxd_parser_get_u8 (&p); + var->display_width = pxd_parser_get_u32 (&p); + var->alignment = pxd_parser_get_u8 (&p); + + var->leave = pxd_parser_get_bool (&p); + + var->short_name_cnt = pxd_parser_get_size_t (&p); + var->short_names = xmalloc (var->short_name_cnt * sizeof *var->short_names); + for (i = 0; i < var->short_name_cnt; i++) + var->short_names[i] = pxd_parser_get_string (&p); + + attrset_load (&var->attributes, pxd_parser_get_link (&p), pxd); + + pxd_parser_destroy (&p); + + return var; +} + +static void +var_uncache (struct variable *var UNUSED) +{ +}