X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fshort-names.c;h=aa157bae1b13c105f4685fb120e7c92980f13938;hb=3b6384c0f3f35fb0b280cb20ddaa01b50912f4b8;hp=3ed99c04c2417792696f2eafe72351fb571f47f7;hpb=6999c6d125665923b52ae15cbad83d06c92a8875;p=pspp diff --git a/src/data/short-names.c b/src/data/short-names.c index 3ed99c04c2..aa157bae1b 100644 --- a/src/data/short-names.c +++ b/src/data/short-names.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009, 2010, 2011 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 @@ -16,90 +16,35 @@ #include -#include +#include "data/short-names.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "data/dictionary.h" +#include "data/sys-file-private.h" +#include "data/variable.h" +#include "libpspp/assertion.h" +#include "libpspp/compiler.h" +#include "libpspp/i18n.h" +#include "libpspp/message.h" +#include "libpspp/str.h" +#include "libpspp/stringi-set.h" #include "gettext.h" #define _(msgid) gettext (msgid) -/* 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, size_t i, - 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 (suffix_number >= 0); - - /* Set base name. */ - var_set_short_name (v, i, 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, i, short_name); -} - static void -claim_short_name (struct variable *v, size_t i, struct hsh_table *short_names) +claim_short_name (struct variable *v, size_t i, + struct stringi_set *short_names) { const char *short_name = var_get_short_name (v, i); - if (short_name != NULL - && hsh_insert (short_names, (char *) short_name) != NULL) + if (short_name != NULL && !stringi_set_insert (short_names, short_name)) var_set_short_name (v, i, NULL); } /* Form initial short_name from the variable name, then try _A, _B, ... _AA, _AB, etc., if needed. */ static void -assign_short_name (struct variable *v, size_t i, struct hsh_table *short_names) +assign_short_name (struct variable *v, size_t i, + struct stringi_set *short_names) { int trial; @@ -108,13 +53,28 @@ assign_short_name (struct variable *v, size_t i, struct hsh_table *short_names) for (trial = 0; ; trial++) { + char suffix[SHORT_NAME_LEN + 1]; + char *short_name; + + /* Compose suffix. */ if (trial == 0) - var_set_short_name (v, i, var_get_name (v)); + suffix[0] = '\0'; else - set_var_short_name_suffix (v, i, var_get_name (v), trial - 1); + { + suffix[0] = '_'; + str_format_26adic (trial, &suffix[1], sizeof suffix - 1); + } - if (hsh_insert (short_names, (char *) var_get_short_name (v, i)) == NULL) - break; + /* Set name. */ + short_name = utf8_encoding_concat (var_get_name (v), suffix, + var_get_encoding (v), SHORT_NAME_LEN); + if (stringi_set_insert (short_names, short_name)) + { + var_set_short_name (v, i, short_name); + free (short_name); + return; + } + free (short_name); } } @@ -130,15 +90,10 @@ void short_names_assign (struct dictionary *d) { size_t var_cnt = dict_get_var_cnt (d); - struct hsh_table *short_names; + struct stringi_set short_names; size_t i, j; - /* Create hash used for detecting conflicts. The entries in - the hash table point to strings owned by dictionary - variables, not by us, so we don't need to provide a free - function. */ - short_names = hsh_create (var_cnt, compare_strings, hash_string, - NULL, NULL); + stringi_set_init (&short_names); /* Clear short names that conflict with a variable name. */ for (i = 0; i < var_cnt; i++) @@ -162,8 +117,10 @@ short_names_assign (struct dictionary *d) for (i = 0; i < var_cnt; i++) { struct variable *v = dict_get_var (d, i); - if (strlen (var_get_name (v)) <= SHORT_NAME_LEN) - var_set_short_name (v, 0, var_get_name (v)); + const char *name = var_get_name (v); + int len = recode_string_len (var_get_encoding (v), "UTF-8", name, -1); + if (len <= SHORT_NAME_LEN) + var_set_short_name (v, 0, name); } /* Each variable with an assigned short name for its first @@ -174,14 +131,14 @@ short_names_assign (struct dictionary *d) for (i = 0; i < var_cnt; i++) { struct variable *v = dict_get_var (d, i); - claim_short_name (v, 0, short_names); + claim_short_name (v, 0, &short_names); } for (i = 0; i < var_cnt; i++) { struct variable *v = dict_get_var (d, i); int segment_cnt = sfm_width_to_segments (var_get_width (v)); for (j = 1; j < segment_cnt; j++) - claim_short_name (v, i, short_names); + claim_short_name (v, j, &short_names); } /* Assign short names to first segment of remaining variables, @@ -189,16 +146,15 @@ short_names_assign (struct dictionary *d) for (i = 0; i < var_cnt; i++) { struct variable *v = dict_get_var (d, i); - assign_short_name (v, 0, short_names); + assign_short_name (v, 0, &short_names); } for (i = 0; i < var_cnt; i++) { struct variable *v = dict_get_var (d, i); int segment_cnt = sfm_width_to_segments (var_get_width (v)); for (j = 1; j < segment_cnt; j++) - assign_short_name (v, j, short_names); + assign_short_name (v, j, &short_names); } - /* Get rid of hash table. */ - hsh_destroy (short_names); + stringi_set_destroy (&short_names); }