faa36478617263d289e1edd79d8d941c36c4dd8c
kent
  Wed Jun 8 14:30:46 2016 -0700
Adding ensureNamesCaseUnique library function to check for symbol conflicts in a case-insensitive way giving a symbol list.  This is used to precheck when defining a SQL table from a tagStorm, since tagStorm is case sensitive but SQL is not.

diff --git src/lib/obscure.c src/lib/obscure.c
index 4b1d190..720512c 100644
--- src/lib/obscure.c
+++ src/lib/obscure.c
@@ -832,15 +832,43 @@
 boolean endsWithWordComma(char *string, char *word)
 /* Return TRUE if string ends with word possibly followed by a comma, and the beginning
  * of word within string is the beginning of string or follows a comma. */
 {
 int stringLen = strlen(string);
 int wordLen = strlen(word);
 int commaSize = (stringLen > wordLen && string[stringLen-1] == ',') ? 1 : 0;
 if (stringLen < wordLen + commaSize)
     return FALSE;
 int wordOffset = stringLen - commaSize - wordLen;
 if (sameStringN(string + wordOffset, word, wordLen) &&
     (wordOffset == 0 || string[wordOffset-1] == ','))
     return TRUE;
 return FALSE;
 }
+
+void ensureNamesCaseUnique(struct slName *fieldList)
+/* Ensure that there would be no name conflicts in fieldList if all fields were lower-cased. */
+{
+struct slName *field;
+struct hash *hash = hashNew(0);
+for (field = fieldList; field != NULL; field = field->next)
+    {
+    char *s = field->name;
+    int len = strlen(s);
+    assert(len<512);  // avoid stack overflow
+    char lower[len+1];
+    strcpy(lower, s);
+    strLower(lower);
+    char *conflict = hashFindVal(hash, lower);
+    if (conflict)
+	 {
+	 if (sameString(conflict,s))
+	     errAbort("Duplicate symbol %s", s);
+	 else
+	     errAbort("Conflict between symbols with different cases: %s vs %s",
+		conflict, s);
+	 }
+    hashAdd(hash, lower, s);
+    }
+hashFree(&hash);
+}
+