Committed patch #5636
[pspp-builds.git] / src / data / value-labels.c
index 92a2db48ea87e82340dfec28fb3d3d2ab486d7a6..f54a4870fc05bf3b02ac9a2e6405cde5dbfefe62 100644 (file)
@@ -1,6 +1,5 @@
 /* PSPP - computes sample statistics.
    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
-   Written by Ben Pfaff <blp@gnu.org>.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -23,6 +22,9 @@
 
 #include <stdlib.h>
 
+#include <data/data-out.h>
+#include <data/format.h>
+#include <data/value.h>
 #include <data/variable.h>
 #include <libpspp/alloc.h>
 #include <libpspp/compiler.h>
@@ -71,7 +73,8 @@ val_labs_copy (const struct val_labs *vls)
   struct val_labs_iterator *i;
   struct val_lab *vl;
 
-  assert (vls != NULL);
+  if (vls == NULL)
+    return NULL;
 
   copy = val_labs_create (vls->width);
   for (vl = val_labs_first (vls, &i); vl != NULL;
@@ -87,7 +90,8 @@ val_labs_copy (const struct val_labs *vls)
 bool
 val_labs_can_set_width (const struct val_labs *vls, int new_width) 
 {
-  assert ((vls->width == 0) == (new_width == 0));
+  if ( var_type_from_width (new_width) != var_type_from_width (vls->width ))
+    return false;
 
   if (vls->width == 0)
     return new_width == 0;
@@ -154,12 +158,7 @@ val_labs_clear (struct val_labs *vls)
 size_t
 val_labs_count (const struct val_labs *vls) 
 {
-  assert (vls != NULL);
-
-  if (vls->labels == NULL)
-    return 0;
-  else
-    return hsh_count (vls->labels);
+  return vls == NULL || vls->labels == NULL ? 0 : hsh_count (vls->labels);
 }
 \f
 /* One value label in internal format. */
@@ -189,10 +188,10 @@ create_int_val_lab (struct val_labs *vls, union value value, const char *label)
 }
 
 /* If VLS does not already contain a value label for VALUE, adds
-   LABEL for it and returns nonzero.  Otherwise, returns zero.
+   LABEL for it and returns true.  Otherwise, returns false.
    Behavior is undefined if VLS's width is greater than
    MAX_SHORT_STRING. */
-int
+bool
 val_labs_add (struct val_labs *vls, union value value, const char *label) 
 {
   struct int_val_lab *ivl;
@@ -211,48 +210,35 @@ val_labs_add (struct val_labs *vls, union value value, const char *label)
   if (*vlpp == NULL) 
     {
       *vlpp = ivl;
-      return 1; 
-    }
-  else 
-    {
-      free_int_val_lab (ivl, vls);
-      return 0;
+      return true; 
     }
+  free_int_val_lab (ivl, vls);
+  return false;
 }
 
-/* Sets LABEL as the value label for VALUE in VLS.  Returns zero
-   if there wasn't already a value label for VALUE, or nonzero if
+/* Sets LABEL as the value label for VALUE in VLS.  Returns false
+   if there wasn't already a value label for VALUE, or true if
    there was.  Behavior is undefined if VLS's width is greater
    than MAX_SHORT_STRING. */
-int
+void
 val_labs_replace (struct val_labs *vls, union value value, const char *label) 
 {
-  struct int_val_lab *ivl;
-
-  assert (vls != NULL);
   assert (vls->width <= MAX_SHORT_STRING);
-  assert (label != NULL);
-
-  if (vls->labels == NULL)
+  if (vls->labels != NULL)
     {
-      val_labs_add (vls, value, label);
-      return 0;
+      struct int_val_lab *new = create_int_val_lab (vls, value, label);
+      struct int_val_lab *old = hsh_replace (vls->labels, new);
+      if (old != NULL) 
+        free_int_val_lab (old, vls); 
     }
-
-  ivl = hsh_replace (vls->labels, create_int_val_lab (vls, value, label));
-  if (ivl == NULL) 
-    return 0;
   else 
-    {
-      free_int_val_lab (ivl, vls);
-      return 1;
-    }
+    val_labs_add (vls, value, label);  
 }
 
-/* Removes any value label for VALUE within VLS.  Returns nonzero
+/* Removes any value label for VALUE within VLS.  Returns true
    if a value label was removed. Behavior is undefined if VLS's
    width is greater than MAX_SHORT_STRING. */
-int 
+bool
 val_labs_remove (struct val_labs *vls, union value value) 
 {
   assert (vls != NULL);
@@ -266,7 +252,7 @@ val_labs_remove (struct val_labs *vls, union value value)
       return deleted;
     }
   else
-    return 0;
+    return false;
 }
 
 /* Searches VLS for a value label for VALUE.  If successful,
@@ -276,12 +262,9 @@ val_labs_remove (struct val_labs *vls, union value value)
 char *
 val_labs_find (const struct val_labs *vls, union value value) 
 {
-  assert (vls != NULL);
-
-  if (vls->width > MAX_SHORT_STRING)
-    return NULL;
-
-  if (vls->labels != NULL) 
+  if (vls != NULL
+      && vls->width <= MAX_SHORT_STRING
+      && vls->labels != NULL)
     {
       struct int_val_lab ivl, *vlp;
 
@@ -398,7 +381,7 @@ val_labs_done (struct val_labs_iterator **ip)
 \f
 /* Compares two value labels and returns a strcmp()-type result. */
 int
-compare_int_val_lab (const void *a_, const void *b_, void *vls_)
+compare_int_val_lab (const void *a_, const void *b_, const void *vls_)
 {
   const struct int_val_lab *a = a_;
   const struct int_val_lab *b = b_;
@@ -412,7 +395,7 @@ compare_int_val_lab (const void *a_, const void *b_, void *vls_)
 
 /* Hash a value label. */
 unsigned
-hash_int_val_lab (const void *vl_, void *vls_)
+hash_int_val_lab (const void *vl_, const void *vls_)
 {
   const struct int_val_lab *vl = vl_;
   const struct val_labs *vls = vls_;
@@ -420,12 +403,12 @@ hash_int_val_lab (const void *vl_, void *vls_)
   if (vls->width == 0)
     return hsh_hash_double (vl->value.f);
   else
-    return hsh_hash_bytes (vl->value.s, sizeof vl->value.s);
+    return hsh_hash_bytes (vl->value.s, vls->width);
 }
 
 /* Free a value label. */
 void
-free_int_val_lab (void *vl_, void *vls_ UNUSED) 
+free_int_val_lab (void *vl_, const void *vls_ UNUSED) 
 {
   struct int_val_lab *vl = vl_;
 
@@ -449,6 +432,12 @@ static hsh_free_func free_atom;
 /* Hash table of atoms. */
 static struct hsh_table *atoms;
 
+static void
+destroy_atoms (void)
+{
+  hsh_destroy (atoms);
+}
+
 /* Creates and returns an atom for STRING. */
 static struct atom *
 atom_create (const char *string) 
@@ -459,7 +448,10 @@ atom_create (const char *string)
   assert (string != NULL);
           
   if (atoms == NULL) 
-    atoms = hsh_create (8, compare_atoms, hash_atom, free_atom, NULL);
+    {
+      atoms = hsh_create (8, compare_atoms, hash_atom, free_atom, NULL);
+      atexit (destroy_atoms);
+    }
 
   a.string = (char *) string;
   app = hsh_probe (atoms, &a);
@@ -503,7 +495,7 @@ atom_to_string (const struct atom *atom)
 
 /* A hsh_compare_func that compares A and B. */
 static int
-compare_atoms (const void *a_, const void *b_, void *aux UNUSED) 
+compare_atoms (const void *a_, const void *b_, const void *aux UNUSED) 
 {
   const struct atom *a = a_;
   const struct atom *b = b_;
@@ -513,7 +505,7 @@ compare_atoms (const void *a_, const void *b_, void *aux UNUSED)
 
 /* A hsh_hash_func that hashes ATOM. */
 static unsigned
-hash_atom (const void *atom_, void *aux UNUSED) 
+hash_atom (const void *atom_, const void *aux UNUSED) 
 {
   const struct atom *atom = atom_;
 
@@ -522,36 +514,10 @@ hash_atom (const void *atom_, void *aux UNUSED)
 
 /* A hsh_free_func that destroys ATOM. */
 static void
-free_atom (void *atom_, void *aux UNUSED) 
+free_atom (void *atom_, const void *aux UNUSED) 
 {
   struct atom *atom = atom_;
 
   free (atom->string);
   free (atom);
 }
-
-
-/* Get a string representing the value.
-   That is, if it has a label, then return that label,
-   otherwise, if the value is alpha, then return the string for it,
-   else format it and return the formatted string
-*/
-const char *
-value_to_string (const union value *val, const struct variable *var)
-{
-  char *s;
-  
-  assert (val != NULL);
-  assert (var != NULL);
-
-  s = val_labs_find (var->val_labs, *val);
-  if (s == NULL) 
-    {
-      static char buf[MAX_STRING + 1];
-      data_out (buf, &var->print, val);
-      buf[var->print.w] = '\0';
-      s = buf;
-    }
-  
-  return s;
-}