X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fdictionary.c;h=64c4f8ac10977547da5f50b3669ffe9e7940884a;hb=f5c108becd49d78f4898cab11352291f5689d24e;hp=d38ed5fc1326d15f8d75e565c3bc77c9034f0fbe;hpb=4517b68e7248f22e7b7ed81f0d73179351a53047;p=pspp-builds.git diff --git a/src/data/dictionary.c b/src/data/dictionary.c index d38ed5fc..64c4f8ac 100644 --- a/src/data/dictionary.c +++ b/src/data/dictionary.c @@ -24,7 +24,6 @@ #include #include "case.h" -#include "cat-routines.h" #include "category.h" #include "settings.h" #include "value-labels.h" @@ -52,13 +51,13 @@ struct dictionary size_t var_cnt, var_cap; /* Number of variables, capacity. */ struct hsh_table *name_tab; /* Variable index by name. */ int next_value_idx; /* Index of next `union value' to allocate. */ - struct variable **split; /* SPLIT FILE vars. */ + const struct variable **split; /* SPLIT FILE vars. */ size_t split_cnt; /* SPLIT FILE count. */ struct variable *weight; /* WEIGHT variable. */ struct variable *filter; /* FILTER variable. */ size_t case_limit; /* Current case limit (N command). */ char *label; /* File label. */ - char *documents; /* Documents, as a string. */ + struct string documents; /* Documents, as a string. */ struct vector **vector; /* Vectors of variables. */ size_t vector_cnt; /* Number of vectors. */ const struct dict_callbacks *callbacks; /* Callbacks on dictionary @@ -178,8 +177,7 @@ dict_clear (struct dictionary *d) d->case_limit = 0; free (d->label); d->label = NULL; - free (d->documents); - d->documents = NULL; + ds_destroy (&d->documents); dict_clear_vectors (d); } @@ -233,13 +231,20 @@ dict_get_var (const struct dictionary *d, size_t idx) return d->var[idx]; } +inline void +dict_get_vars (const struct dictionary *d, const struct variable ***vars, + size_t *cnt, unsigned exclude_classes) +{ + dict_get_vars_mutable (d, (struct variable ***) vars, cnt, exclude_classes); +} + /* Sets *VARS to an array of pointers to variables in D and *CNT to the number of variables in *D. All variables are returned if EXCLUDE_CLASSES is 0, or it may contain one or more of (1u << DC_ORDINARY), (1u << DC_SYSTEM), or (1u << DC_SCRATCH) to exclude the corresponding type of variable. */ void -dict_get_vars (const struct dictionary *d, struct variable ***vars, +dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars, size_t *cnt, unsigned exclude_classes) { size_t count; @@ -352,9 +357,16 @@ dict_clone_var_assert (struct dictionary *d, const struct variable *old_var, struct variable * dict_lookup_var (const struct dictionary *d, const char *name) { - struct variable *target = var_create (name, 0); - struct variable *result = hsh_find (d->name_tab, target); + struct variable *target ; + struct variable *result ; + + if ( ! var_is_valid_name (name, false)) + return NULL; + + target = var_create (name, 0); + result = hsh_find (d->name_tab, target); var_destroy (target); + return result; } @@ -431,11 +443,12 @@ reindex_vars (struct dictionary *d, size_t from, size_t to) /* Deletes variable V from dictionary D and frees V. This is a very bad idea if there might be any pointers to V - from outside D. In general, no variable in should be deleted when - any transformations are active on the dictionary's dataset, because - those transformations might reference the deleted variable. - The safest time to delete a variable is just after a procedure - has been executed, as done by MODIFY VARS. + from outside D. In general, no variable in the active file's + dictionary should be deleted when any transformations are + active on the dictionary's dataset, because those + transformations might reference the deleted variable. The + safest time to delete a variable is just after a procedure has + been executed, as done by MODIFY VARS. Pointers to V within D are not a problem, because dict_delete_var() knows to remove V from split variables, @@ -705,7 +718,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 " @@ -1002,7 +1015,7 @@ dict_compactor_destroy (struct dict_compactor *compactor) dict_get_split_cnt() to determine how many SPLIT FILE vars there are. Returns a null pointer if and only if there are no SPLIT FILE vars. */ -struct variable *const * +const struct variable *const * dict_get_split_vars (const struct dictionary *d) { assert (d != NULL); @@ -1044,7 +1057,7 @@ dict_set_split_vars (struct dictionary *d, assert (cnt == 0 || split != NULL); d->split_cnt = cnt; - d->split = xnrealloc (d->split, cnt, sizeof *d->split); + d->split = cnt > 0 ? xnrealloc (d->split, cnt, sizeof *d->split) : NULL; memcpy (d->split, split, cnt * sizeof *d->split); if ( d->callbacks && d->callbacks->split_changed ) @@ -1082,27 +1095,73 @@ dict_set_label (struct dictionary *d, const char *label) } /* Returns the documents for D, or a null pointer if D has no - documents (see cmd_document()).. */ + documents. If the return value is nonnull, then the string + will be an exact multiple of DOC_LINE_LENGTH bytes in length, + with each segment corresponding to one line. */ const char * dict_get_documents (const struct dictionary *d) { - assert (d != NULL); - - return d->documents; + return ds_is_empty (&d->documents) ? NULL : ds_cstr (&d->documents); } /* Sets the documents for D to DOCUMENTS, or removes D's - documents if DOCUMENT is a null pointer. */ + documents if DOCUMENT is a null pointer. If DOCUMENTS is + nonnull, then it should be an exact multiple of + DOC_LINE_LENGTH bytes in length, with each segment + corresponding to one line. */ void dict_set_documents (struct dictionary *d, const char *documents) { - assert (d != NULL); + size_t remainder; - free (d->documents); - if (documents == NULL) - d->documents = NULL; - else - d->documents = xstrdup (documents); + ds_assign_cstr (&d->documents, documents != NULL ? documents : ""); + + /* In case the caller didn't get it quite right, pad out the + final line with spaces. */ + remainder = ds_length (&d->documents) % DOC_LINE_LENGTH; + if (remainder != 0) + ds_put_char_multiple (&d->documents, ' ', DOC_LINE_LENGTH - remainder); +} + +/* Drops the documents from dictionary D. */ +void +dict_clear_documents (struct dictionary *d) +{ + ds_clear (&d->documents); +} + +/* Appends LINE to the documents in D. LINE will be truncated or + padded on the right with spaces to make it exactly + DOC_LINE_LENGTH bytes long. */ +void +dict_add_document_line (struct dictionary *d, const char *line) +{ + 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); + } + buf_copy_str_rpad (ds_put_uninit (&d->documents, DOC_LINE_LENGTH), + DOC_LINE_LENGTH, line); +} + +/* Returns the number of document lines in dictionary D. */ +size_t +dict_get_document_line_cnt (const struct dictionary *d) +{ + return ds_length (&d->documents) / DOC_LINE_LENGTH; +} + +/* Copies document line number IDX from dictionary D into + LINE, trimming off any trailing white space. */ +void +dict_get_document_line (const struct dictionary *d, + 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, + DOC_LINE_LENGTH)); + ds_rtrim (line, ss_cstr (CC_SPACES)); } /* Creates in D a vector named NAME that contains the CNT @@ -1130,6 +1189,18 @@ dict_create_vector (struct dictionary *d, return false; } +/* Creates in D a vector named NAME that contains the CNT + variables in VAR. A vector named NAME must not already exist + in D. */ +void +dict_create_vector_assert (struct dictionary *d, + const char *name, + struct variable **var, size_t cnt) +{ + assert (dict_lookup_vector (d, name) == NULL); + dict_create_vector (d, name, var, cnt); +} + /* Returns the vector in D with index IDX, which must be less than dict_get_vector_cnt (D). */ const struct vector *