X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fdictionary.c;h=cee678e407878651360979f77b290e614968204d;hb=a81a87da6616bf36a019a501c468cd61422a12b1;hp=d77d9fdd1ed2b78620a87a6103f6f4304f0c4095;hpb=8021cf8974a46fe82af7b8952e448c0ea6858a48;p=pspp-builds.git diff --git a/src/data/dictionary.c b/src/data/dictionary.c index d77d9fdd..cee678e4 100644 --- a/src/data/dictionary.c +++ b/src/data/dictionary.c @@ -1,20 +1,18 @@ -/* PSPP - computes sample statistics. +/* PSPP - a program for statistical analysis. Copyright (C) 1997-9, 2000, 2006, 2007 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 the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with this program. If not, see . */ #include @@ -116,7 +114,10 @@ dict_clone (const struct dictionary *s) { struct variable *sv = s->var[i]; struct variable *dv = dict_clone_var_assert (d, sv, var_get_name (sv)); - var_set_short_name (dv, var_get_short_name (sv)); + size_t i; + + for (i = 0; i < var_get_short_name_cnt (sv); i++) + var_set_short_name (dv, i, var_get_short_name (sv, i)); } d->next_value_idx = s->next_value_idx; @@ -158,14 +159,22 @@ dict_clear (struct dictionary *d) while (d->var_cnt > 0 ) { - var_clear_vardict (d->var[d->var_cnt - 1]); - var_destroy (d->var[d->var_cnt -1]); + struct variable *v = d->var[d->var_cnt - 1]; + int dict_index = var_get_dict_index (v); + int case_index = var_get_case_index (v); + int val_cnt = var_get_value_cnt (v); + + var_clear_vardict (v); + var_destroy (v); d->var_cnt--; if (d->callbacks && d->callbacks->var_deleted ) - d->callbacks->var_deleted (d, d->var_cnt, d->cb_data); + d->callbacks->var_deleted (d, + dict_index, case_index, val_cnt, + d->cb_data); } + free (d->var); d->var = NULL; d->var_cnt = d->var_cap = 0; @@ -420,7 +429,7 @@ set_var_dict_index (struct variable *v, int dict_index) d->callbacks->var_changed (d, dict_index, d->cb_data); } -/* Sets the case_index in V's vardict to DICT_INDEX. */ +/* Sets the case_index in V's vardict to CASE_INDEX. */ static void set_var_case_index (struct variable *v, int case_index) { @@ -457,6 +466,8 @@ void dict_delete_var (struct dictionary *d, struct variable *v) { int dict_index = var_get_dict_index (v); + const int case_index = var_get_case_index (v); + const int val_cnt = var_get_value_cnt (v); assert (dict_contains_var (d, v)); @@ -489,7 +500,7 @@ dict_delete_var (struct dictionary *d, struct variable *v) var_destroy (v); if (d->callbacks && d->callbacks->var_deleted ) - d->callbacks->var_deleted (d, dict_index, d->cb_data); + d->callbacks->var_deleted (d, dict_index, case_index, val_cnt, d->cb_data); } /* Deletes the COUNT variables listed in VARS from D. This is @@ -616,7 +627,7 @@ dict_rename_var (struct dictionary *d, struct variable *v, hsh_force_insert (d->name_tab, v); if (get_algorithm () == ENHANCED) - var_clear_short_name (v); + var_clear_short_names (v); if ( d->callbacks && d->callbacks->var_changed ) d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data); @@ -682,7 +693,7 @@ dict_rename_vars (struct dictionary *d, /* Clear short names. */ if (get_algorithm () == ENHANCED) for (i = 0; i < count; i++) - var_clear_short_name (vars[i]); + var_clear_short_names (vars[i]); pool_destroy (pool); return true; @@ -718,7 +729,7 @@ dict_get_case_weight (const struct dictionary *d, const struct ccase *c, double w = case_num (c, d->weight); if (w < 0.0 || var_is_num_missing (d->weight, w, MV_ANY)) w = 0.0; - if ( w == 0.0 && *warn_on_invalid ) { + if ( w == 0.0 && warn_on_invalid != NULL && *warn_on_invalid ) { *warn_on_invalid = false; msg (SW, _("At least one case in the data file had a weight value " "that was user-missing, system-missing, zero, or " @@ -836,6 +847,33 @@ dict_compact_values (struct dictionary *d) } } + +/* + Reassigns case indices for D, increasing each index above START by + the value PADDING. +*/ +static void +dict_pad_values (struct dictionary *d, int start, int padding) +{ + size_t i; + + if ( padding <= 0 ) + return; + + for (i = 0; i < d->var_cnt; ++i) + { + struct variable *v = d->var[i]; + + int index = var_get_case_index (v); + + if ( index >= start) + set_var_case_index (v, index + padding); + } + + d->next_value_idx += padding; +} + + /* Returns the number of values that would be used by a case if dict_compact_values() were called. */ size_t @@ -1113,7 +1151,7 @@ void dict_set_documents (struct dictionary *d, const char *documents) { size_t remainder; - + ds_assign_cstr (&d->documents, documents != NULL ? documents : ""); /* In case the caller didn't get it quite right, pad out the @@ -1125,7 +1163,7 @@ dict_set_documents (struct dictionary *d, const char *documents) /* Drops the documents from dictionary D. */ void -dict_clear_documents (struct dictionary *d) +dict_clear_documents (struct dictionary *d) { ds_clear (&d->documents); } @@ -1136,10 +1174,10 @@ dict_clear_documents (struct dictionary *d) void dict_add_document_line (struct dictionary *d, const char *line) { - if (strlen (line) > DOC_LINE_LENGTH) + if (strlen (line) > DOC_LINE_LENGTH) { /* Note to translators: "bytes" is correct, not characters */ - msg (SW, _("Truncating document line to %d bytes."), DOC_LINE_LENGTH); + msg (SW, _("Truncating document line to %d bytes."), DOC_LINE_LENGTH); } buf_copy_str_rpad (ds_put_uninit (&d->documents, DOC_LINE_LENGTH), DOC_LINE_LENGTH, line); @@ -1147,7 +1185,7 @@ dict_add_document_line (struct dictionary *d, const char *line) /* Returns the number of document lines in dictionary D. */ size_t -dict_get_document_line_cnt (const struct dictionary *d) +dict_get_document_line_cnt (const struct dictionary *d) { return ds_length (&d->documents) / DOC_LINE_LENGTH; } @@ -1156,7 +1194,7 @@ dict_get_document_line_cnt (const struct dictionary *d) LINE, trimming off any trailing white space. */ void dict_get_document_line (const struct dictionary *d, - size_t idx, struct string *line) + size_t idx, struct string *line) { assert (idx < dict_get_document_line_cnt (d)); ds_assign_substring (line, ds_substr (&d->documents, idx * DOC_LINE_LENGTH, @@ -1247,137 +1285,28 @@ dict_clear_vectors (struct dictionary *d) d->vector_cnt = 0; } -/* Compares two strings. */ -static int -compare_strings (const void *a, const void *b, const void *aux UNUSED) -{ - return strcmp (a, b); -} - -/* Hashes a string. */ -static unsigned -hash_string (const void *s, const void *aux UNUSED) -{ - return hsh_hash_string (s); -} - - -/* Sets V's short name to BASE, followed by a suffix of the form - _A, _B, _C, ..., _AA, _AB, etc. according to the value of - SUFFIX_NUMBER. Truncates BASE as necessary to fit. */ -static void -set_var_short_name_suffix (struct variable *v, const char *base, - int suffix_number) -{ - char suffix[SHORT_NAME_LEN + 1]; - char short_name[SHORT_NAME_LEN + 1]; - char *start, *end; - int len, ofs; - - assert (v != NULL); - assert (suffix_number >= 0); - - /* Set base name. */ - var_set_short_name (v, base); - - /* Compose suffix. */ - start = end = suffix + sizeof suffix - 1; - *end = '\0'; - do - { - *--start = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[suffix_number % 26]; - if (start <= suffix + 1) - msg (SE, _("Variable suffix too large.")); - suffix_number /= 26; - } - while (suffix_number > 0); - *--start = '_'; - - /* Append suffix to V's short name. */ - str_copy_trunc (short_name, sizeof short_name, base); - len = end - start; - if (len + strlen (short_name) > SHORT_NAME_LEN) - ofs = SHORT_NAME_LEN - len; - else - ofs = strlen (short_name); - strcpy (short_name + ofs, start); - - /* Set name. */ - var_set_short_name (v, short_name); -} - -/* Assigns a valid, unique short_name[] to each variable in D. - Each variable whose actual name is short has highest priority - for that short name. Otherwise, variables with an existing - short_name[] have the next highest priority for a given short - name; if it is already taken, then the variable is treated as - if short_name[] had been empty. Otherwise, long names are - truncated to form short names. If that causes conflicts, - variables are renamed as PREFIX_A, PREFIX_B, and so on. */ +/* Called from variable.c to notify the dictionary that some property of + the variable has changed */ void -dict_assign_short_names (struct dictionary *d) +dict_var_changed (const struct variable *v) { - struct hsh_table *short_names; - size_t i; - - /* Give variables whose names are short the corresponding short - names, and clear short_names[] that conflict with a variable - name. */ - for (i = 0; i < d->var_cnt; i++) + if ( var_has_vardict (v)) { - struct variable *v = d->var[i]; - const char *short_name = var_get_short_name (v); - if (strlen (var_get_name (v)) <= SHORT_NAME_LEN) - var_set_short_name (v, var_get_name (v)); - else if (short_name != NULL && dict_lookup_var (d, short_name) != NULL) - var_clear_short_name (v); - } + const struct vardict_info *vdi = var_get_vardict (v); + struct dictionary *d; - /* Each variable with an assigned short_name[] now gets it - unless there is a conflict. */ - short_names = hsh_create (d->var_cnt, compare_strings, hash_string, - NULL, NULL); - for (i = 0; i < d->var_cnt; i++) - { - struct variable *v = d->var[i]; - const char *name = var_get_short_name (v); - if (name != NULL && hsh_insert (short_names, (char *) name) != NULL) - var_clear_short_name (v); - } + d = vdi->dict; - /* Now assign short names to remaining variables. */ - for (i = 0; i < d->var_cnt; i++) - { - struct variable *v = d->var[i]; - const char *name = var_get_short_name (v); - if (name == NULL) - { - /* Form initial short_name from the variable name, then - try _A, _B, ... _AA, _AB, etc., if needed.*/ - int trial = 0; - do - { - if (trial == 0) - var_set_short_name (v, var_get_name (v)); - else - set_var_short_name_suffix (v, var_get_name (v), trial - 1); - - trial++; - } - while (hsh_insert (short_names, (char *) var_get_short_name (v)) - != NULL); - } + if ( d->callbacks && d->callbacks->var_changed ) + d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data); } - - /* Get rid of hash table. */ - hsh_destroy (short_names); } -/* Called from variable.c to notify the dictionary that some property of - the variable has changed */ +/* Called from variable.c to notify the dictionary that the variable's width + has changed */ void -dict_var_changed (const struct variable *v) +dict_var_resized (const struct variable *v, int delta) { if ( var_has_vardict (v)) { @@ -1386,7 +1315,9 @@ dict_var_changed (const struct variable *v) d = vdi->dict; - if ( d->callbacks && d->callbacks->var_changed ) - d->callbacks->var_changed (d, var_get_dict_index (v), d->cb_data); + dict_pad_values (d, var_get_case_index(v) + 1, delta); + + if ( d->callbacks && d->callbacks->var_resized ) + d->callbacks->var_resized (d, var_get_dict_index (v), delta, d->cb_data); } }