/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013,
+ 2014, 2016, 2020 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
/* A variable. */
struct variable
{
+ int ref_cnt;
/* Dictionary information. */
char *name; /* Variable name. Mixed case. */
int width; /* 0 for numeric, otherwise string width. */
/* Used only for system and portable file input and output.
See short-names.h. */
char **short_names;
- size_t short_name_cnt;
+ size_t n_short_names;
/* Custom attributes. */
struct attrset attributes;
struct variable *
var_create (const char *name, int width)
{
- struct variable *v;
enum val_type type;
assert (width >= 0 && width <= MAX_STRING);
- v = xzalloc (sizeof *v);
+ struct variable *v = XZALLOC (struct variable);
var_set_name_quiet (v, name);
v->width = width;
mv_init (&v->miss, width);
attrset_init (&v->attributes);
ds_init_empty (&v->name_and_label);
+ v->ref_cnt = 1;
+
return v;
}
/* Destroys variable V.
V must not belong to a dictionary. If it does, use
dict_delete_var instead. */
+static void
+var_destroy__ (struct variable *v)
+{
+ assert (!var_has_vardict (v));
+ mv_destroy (&v->miss);
+ var_clear_short_names (v);
+ val_labs_destroy (v->val_labs);
+ var_set_label_quiet (v, NULL);
+ attrset_destroy (var_get_attributes (v));
+ free (v->name);
+ ds_destroy (&v->name_and_label);
+ free (v);
+}
+
+struct variable *
+var_ref (struct variable *v)
+{
+ v->ref_cnt++;
+ return v;
+}
+
void
-var_destroy (struct variable *v)
+var_unref (struct variable *v)
{
- if (v != NULL)
- {
- assert (!var_has_vardict (v));
- mv_destroy (&v->miss);
- var_clear_short_names (v);
- val_labs_destroy (v->val_labs);
- var_set_label_quiet (v, NULL);
- attrset_destroy (var_get_attributes (v));
- free (v->name);
- ds_destroy (&v->name_and_label);
- free (v);
- }
+ if (--v->ref_cnt == 0)
+ var_destroy__ (v);
}
+
+
\f
/* Variable names. */
ov = var_clone (v);
- if (var_has_missing_values (v))
+ if (mv_is_resizable (&v->miss, new_width))
+ mv_resize (&v->miss, new_width);
+ else
{
- if (mv_is_resizable (&v->miss, new_width))
- mv_resize (&v->miss, new_width);
- else
- {
- mv_destroy (&v->miss);
- mv_init (&v->miss, new_width);
- }
- traits |= VAR_TRAIT_MISSING_VALUES;
+ mv_destroy (&v->miss);
+ mv_init (&v->miss, new_width);
}
+ if (new_width != var_get_width (v))
+ traits |= VAR_TRAIT_MISSING_VALUES;
if (v->val_labs != NULL)
{
return !mv_is_empty (&v->miss);
}
-/* Returns true if VALUE is in the given CLASS of missing values
- in V, false otherwise. */
-bool
-var_is_value_missing (const struct variable *v, const union value *value,
- enum mv_class class)
+/* Returns MV_SYSTEM if VALUE is system-missing, MV_USER if VALUE is
+ user-missing for V, and otherwise 0. */
+enum mv_class
+var_is_value_missing (const struct variable *v, const union value *value)
{
- return mv_is_value_missing (&v->miss, value, class);
+ return mv_is_value_missing (&v->miss, value);
}
-/* Returns true if D is in the given CLASS of missing values in
- V, false otherwise.
- V must be a numeric variable. */
-bool
-var_is_num_missing (const struct variable *v, double d, enum mv_class class)
+/* Returns MV_SYSTEM if VALUE is system-missing, MV_USER if VALUE is
+ user-missing for V, and otherwise 0. V must be a numeric variable. */
+enum mv_class
+var_is_num_missing (const struct variable *v, double d)
{
- return mv_is_num_missing (&v->miss, d, class);
+ return mv_is_num_missing (&v->miss, d);
}
-/* Returns true if S[] is a missing value for V, false otherwise.
- S[] must contain exactly as many characters as V's width.
- V must be a string variable. */
-bool
-var_is_str_missing (const struct variable *v, const uint8_t s[],
- enum mv_class class)
+/* Returns MV_USER if VALUE is user-missing for V and otherwise 0. V must be
+ a string variable. */
+enum mv_class
+var_is_str_missing (const struct variable *v, const uint8_t s[])
{
- return mv_is_str_missing (&v->miss, s, class);
+ return mv_is_str_missing (&v->miss, s);
}
\f
/* Returns variable V's value labels,
append_value (const struct variable *v, const union value *value,
struct string *str)
{
- char *s = data_out (value, var_get_encoding (v), &v->print);
- ds_put_cstr (str, s);
+ char *s = data_out (value, var_get_encoding (v), &v->print,
+ settings_get_fmt_settings ());
+ struct substring ss = ss_cstr (s);
+ ss_rtrim (&ss, ss_cstr (" "));
+ ds_put_substring (str, ss);
free (s);
}
-/* Append STR with a string representing VALUE for variable V.
- That is, if VALUE has a label, append that label,
- otherwise format VALUE and append the formatted string.
- STR must be a pointer to an initialised struct string.
-*/
void
-var_append_value_name (const struct variable *v, const union value *value,
- struct string *str)
+var_append_value_name__ (const struct variable *v, const union value *value,
+ enum settings_value_show show, struct string *str)
{
- enum settings_value_style style = settings_get_value_style ();
- const char *name = var_lookup_value_label (v, value);
+ const char *label = var_lookup_value_label (v, value);
- switch (style)
+ switch (show)
{
- case SETTINGS_VAL_STYLE_VALUES:
+ case SETTINGS_VALUE_SHOW_VALUE:
append_value (v, value, str);
break;
- case SETTINGS_VAL_STYLE_LABELS:
- if (name == NULL)
- append_value (v, value, str);
+ default:
+ case SETTINGS_VALUE_SHOW_LABEL:
+ if (label)
+ ds_put_cstr (str, label);
else
- ds_put_cstr (str, name);
+ append_value (v, value, str);
break;
- case SETTINGS_VAL_STYLE_BOTH:
- default:
+ case SETTINGS_VALUE_SHOW_BOTH:
append_value (v, value, str);
- if (name != NULL)
- {
- ds_put_cstr (str, " (");
- ds_put_cstr (str, name);
- ds_put_cstr (str, ")");
- }
+ if (label != NULL)
+ ds_put_format (str, " %s", label);
break;
- };
+ }
+}
+
+/* Append STR with a string representing VALUE for variable V.
+ That is, if VALUE has a label, append that label,
+ otherwise format VALUE and append the formatted string.
+ STR must be a pointer to an initialised struct string.
+*/
+void
+var_append_value_name (const struct variable *v, const union value *value,
+ struct string *str)
+{
+ var_append_value_name__ (v, value, settings_get_show_values (), str);
}
\f
/* Print and write formats. */
const char *
var_to_string (const struct variable *v)
{
- enum settings_var_style style = settings_get_var_style ();
-
- switch (style)
- {
- case SETTINGS_VAR_STYLE_NAMES:
+ switch (settings_get_show_variables ())
+ {
+ case SETTINGS_VALUE_SHOW_VALUE:
return v->name;
- break;
- case SETTINGS_VAR_STYLE_LABELS:
+
+ case SETTINGS_VALUE_SHOW_LABEL:
+ default:
return v->label != NULL ? v->label : v->name;
- break;
- case SETTINGS_VAR_STYLE_BOTH:
+
+ case SETTINGS_VALUE_SHOW_BOTH:
update_vl_string (v);
return ds_cstr (&v->name_and_label);
- break;
- default:
- NOT_REACHED ();
- break;
- };
+ }
}
/* Returns V's variable label, or a null pointer if it has none. */
all if it hasn't been saved to or read from a system or
portable file. */
size_t
-var_get_short_name_cnt (const struct variable *var)
+var_get_n_short_names (const struct variable *var)
{
- return var->short_name_cnt;
+ return var->n_short_names;
}
/* Returns VAR's short name with the given IDX, if it has one
const char *
var_get_short_name (const struct variable *var, size_t idx)
{
- return idx < var->short_name_cnt ? var->short_names[idx] : NULL;
+ return idx < var->n_short_names ? var->short_names[idx] : NULL;
}
/* Sets VAR's short name with the given IDX to the UTF-8 string SHORT_NAME.
struct variable *ov = var_clone (var);
/* Clear old short name numbered IDX, if any. */
- if (idx < var->short_name_cnt)
+ if (idx < var->n_short_names)
{
free (var->short_names[idx]);
var->short_names[idx] = NULL;
/* Install new short name for IDX. */
if (short_name != NULL)
{
- if (idx >= var->short_name_cnt)
+ if (idx >= var->n_short_names)
{
- size_t old_cnt = var->short_name_cnt;
+ size_t n_old = var->n_short_names;
size_t i;
- var->short_name_cnt = MAX (idx * 2, 1);
- var->short_names = xnrealloc (var->short_names, var->short_name_cnt,
+ var->n_short_names = MAX (idx * 2, 1);
+ var->short_names = xnrealloc (var->short_names, var->n_short_names,
sizeof *var->short_names);
- for (i = old_cnt; i < var->short_name_cnt; i++)
+ for (i = n_old; i < var->n_short_names; i++)
var->short_names[i] = NULL;
}
var->short_names[idx] = utf8_to_upper (short_name);
{
size_t i;
- for (i = 0; i < v->short_name_cnt; i++)
+ for (i = 0; i < v->n_short_names; i++)
free (v->short_names[i]);
free (v->short_names);
v->short_names = NULL;
- v->short_name_cnt = 0;
+ v->n_short_names = 0;
}
\f
/* Relationship with dictionary. */
double
var_force_valid_weight (const struct variable *wv, double w, bool *warn_on_invalid)
{
- if (w < 0.0 || (wv && var_is_num_missing (wv, w, MV_ANY)))
+ if (w < 0.0 || (wv && var_is_num_missing (wv, w)))
w = 0.0;
if (w == 0.0 && warn_on_invalid != NULL && *warn_on_invalid)