sys-file-reader: Avoid assert-fail for duplicate attribute names.
[pspp] / src / data / attributes.c
index d262e2ebc3a8438ab56404928361bd19b54eeb5b..d7b45ff59571dd65567349d937f35ee4e038fa1d 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2008, 2009, 2011, 2012 Free Software Foundation, Inc.
+   Copyright (C) 2008, 2009, 2011, 2012, 2016 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
@@ -22,7 +22,9 @@
 #include <string.h>
 
 #include "libpspp/array.h"
+#include "libpspp/compiler.h"
 #include "libpspp/hash-functions.h"
+#include "libpspp/i18n.h"
 
 #include "gl/xalloc.h"
 
@@ -219,14 +221,28 @@ attrset_count (const struct attrset *set)
    case-insensitively, or a null pointer if SET does not contain
    an attribute with that name. */
 struct attribute *
-attrset_lookup (struct attrset *set, const char *name)
+attrset_lookup (const struct attrset *set, const char *name)
 {
-  struct attribute *attr;
+  const struct attribute *attr;
   HMAP_FOR_EACH_WITH_HASH (attr, struct attribute, node,
-                           hash_case_string (name, 0), &set->map)
-    if (!strcasecmp (attribute_get_name (attr), name))
+                           utf8_hash_case_string (name, 0), &set->map)
+    if (!utf8_strcasecmp (attribute_get_name (attr), name))
       break;
-  return attr;
+  return CONST_CAST (struct attribute *, attr);
+}
+
+/* Adds ATTR to SET.  Succeeds and returns true if SET does not already contain
+   an attribute with the same name (matched case insensitively); otherwise
+   fails and returns false.  On success only, ownership of ATTR is transferred
+   to SET. */
+bool
+attrset_try_add (struct attrset *set, struct attribute *attr)
+{
+  const char *name = attribute_get_name (attr);
+  if (attrset_lookup (set, name))
+    return false;
+  hmap_insert (&set->map, &attr->node, utf8_hash_case_string (name, 0));
+  return true;
 }
 
 /* Adds ATTR to SET, which must not already contain an attribute
@@ -235,9 +251,8 @@ attrset_lookup (struct attrset *set, const char *name)
 void
 attrset_add (struct attrset *set, struct attribute *attr)
 {
-  const char *name = attribute_get_name (attr);
-  assert (attrset_lookup (set, name) == NULL);
-  hmap_insert (&set->map, &attr->node, hash_case_string (name, 0));
+  bool ok UNUSED = attrset_try_add (set, attr);
+  assert (ok);
 }
 
 /* Deletes any attribute from SET that matches NAME