1b99bc125d897c0712377c4fb4d23ff9f6cbca9f
angie
  Fri Feb 25 11:43:27 2011 -0800
New src/inc/regexHelper.h module replaces the regex conveniencefunctions that were previously down in hg/lib/hgFindSpecCustom.c.
The primary motivation for this is so I can use regex functions in
the new src/lib/vcf.c for Feature #2821 (VCF parser), but I hope
this will make it easier in general to use regexes in any new code.

diff --git src/lib/regexHelper.c src/lib/regexHelper.c
new file mode 100644
index 0000000..9b42886
--- /dev/null
+++ src/lib/regexHelper.c
@@ -0,0 +1,80 @@
+/* regexHelper: easy wrappers on POSIX Extended Regular Expressions (man 7 regex, man 3 regex) */
+
+#include "regexHelper.h"
+#include "hash.h"
+
+const regex_t *regexCompile(const char *exp, const char *description, int compileFlags)
+/* Compile exp (or die with an informative-as-possible error message).
+ * Cache pre-compiled regex's internally (so don't free result after use). */
+{
+static struct hash *reHash = NULL;
+struct hashEl *hel = NULL;
+char key[512];
+safef(key, sizeof(key), "%d.%s", compileFlags, exp);
+
+if (reHash == NULL)
+    reHash = newHash(10);
+hel = hashLookup(reHash, key);
+if (hel != NULL)
+    return((regex_t *)hel->val);
+else
+    {
+    regex_t *compiledExp = NULL;
+    int errNum = 0;
+    AllocVar(compiledExp);
+    errNum = regcomp(compiledExp, exp, compileFlags);
+    if (errNum != 0)
+	{
+	char errBuf[512];
+	regerror(errNum, compiledExp, errBuf, sizeof(errBuf));
+	errAbort("%s \"%s\" got regular expression compilation error %d:\n%s\n",
+		 description, exp, errNum, errBuf);
+	}
+    hashAdd(reHash, key, compiledExp);
+    return(compiledExp);
+    }
+}
+
+static boolean regexMatchSubstrMaybeCase(const char *string, const char *exp,
+					 regmatch_t substrArr[], size_t substrArrSize,
+					 boolean isCaseInsensitive)
+/* Return TRUE if string matches regular expression exp;
+ * regexec fills in substrArr with substring offsets. */
+{
+int compileFlags = REG_EXTENDED;
+if (isCaseInsensitive)
+    compileFlags |= REG_ICASE;
+if (substrArr == NULL)
+    compileFlags |= REG_NOSUB;
+const regex_t *compiledExp = regexCompile(exp, "Regular expression w/substrings", compileFlags);
+return(regexec(compiledExp, string, substrArrSize, substrArr, 0) == 0);
+}
+
+boolean regexMatch(const char *string, const char *exp)
+/* Return TRUE if string matches regular expression exp (case sensitive). */
+{
+return regexMatchSubstrMaybeCase(string, exp, NULL, 0, FALSE);
+}
+
+boolean regexMatchNoCase(const char *string, const char *exp)
+/* Return TRUE if string matches regular expression exp (case insensitive). */
+{
+return regexMatchSubstrMaybeCase(string, exp, NULL, 0, TRUE);
+}
+
+boolean regexMatchSubstr(const char *string, const char *exp,
+			 regmatch_t substrArr[], size_t substrArrSize)
+/* Return TRUE if string matches regular expression exp (case sensitive);
+ * regexec fills in substrArr with substring offsets. */
+{
+return regexMatchSubstrMaybeCase(string, exp, substrArr, substrArrSize, FALSE);
+}
+
+boolean regexMatchSubstrNoCase(const char *string, const char *exp,
+			       regmatch_t substrArr[], size_t substrArrSize)
+/* Return TRUE if string matches regular expression exp (case insensitive);
+ * regexec fills in substrArr with substring offsets. */
+{
+return regexMatchSubstrMaybeCase(string, exp, substrArr, substrArrSize, TRUE);
+}
+