/* 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
#include <config.h>
-#include <data/short-names.h>
+#include "data/short-names.h"
-#include <data/dictionary.h>
-#include <data/sys-file-private.h>
-#include <data/variable.h>
-#include <libpspp/assertion.h>
-#include <libpspp/compiler.h>
-#include <libpspp/hash.h>
-#include <libpspp/message.h>
-#include <libpspp/str.h>
+#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;
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);
}
}
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++)
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
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,
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);
}