From 475c83618a043c88e7414b839228c28452658166 Mon Sep 17 00:00:00 2001
From: Přemysl Janouch 
Date: Sun, 13 Jul 2014 04:30:23 +0200
Subject: Only compile regex's once
---
 src/kike.c | 45 +++++++++++++++++++++++++++++++--------------
 1 file changed, 31 insertions(+), 14 deletions(-)
(limited to 'src/kike.c')
diff --git a/src/kike.c b/src/kike.c
index d5a777c..0ce7092 100644
--- a/src/kike.c
+++ b/src/kike.c
@@ -103,13 +103,24 @@ enum validation_result
 #define IRC_NICKNAME_MAX    9
 #define IRC_HOSTNAME_MAX   63
 
-// Anything to keep it as short as possible
-#define SN "[0-9A-Za-z][-0-9A-Za-z]*[0-9A-Za-z]*"
-#define N4 "[0-9]{1,3}"
-#define N6 "[0-9ABCDEFabcdef]{1,}"
+static bool
+irc_regex_match (const char *regex, const char *s)
+{
+	static struct str_map cache;
+	static bool initialized;
 
-#define LE "A-Za-z"
-#define SP "\\[\\]\\\\`_^{|}"
+	if (!initialized)
+	{
+		regex_cache_init (&cache);
+		initialized = true;
+	}
+
+	struct error *e = NULL;
+	bool result = regex_cache_match (&cache, regex,
+		REG_EXTENDED | REG_NOSUB, s, &e);
+	hard_assert (!e);
+	return result;
+}
 
 static const char *
 irc_validate_to_str (enum validation_result result)
@@ -124,14 +135,20 @@ irc_validate_to_str (enum validation_result result)
 	}
 }
 
-// TODO: at least cache the resulting `regex_t' in a `struct str_map'
+// Anything to keep it as short as possible
+#define SN "[0-9A-Za-z][-0-9A-Za-z]*[0-9A-Za-z]*"
+#define N4 "[0-9]{1,3}"
+#define N6 "[0-9ABCDEFabcdef]{1,}"
+
+#define LE "A-Za-z"
+#define SP "\\[\\]\\\\`_^{|}"
 
 static enum validation_result
 irc_validate_hostname (const char *hostname)
 {
 	if (!*hostname)
 		return VALIDATION_ERROR_EMPTY;
-	if (!regex_match ("^" SN "(\\." SN ")*$", hostname, NULL))
+	if (!irc_regex_match ("^" SN "(\\." SN ")*$", hostname))
 		return VALIDATION_ERROR_INVALID;
 	if (strlen (hostname) > IRC_HOSTNAME_MAX)
 		return VALIDATION_ERROR_TOO_LONG;
@@ -141,11 +158,11 @@ irc_validate_hostname (const char *hostname)
 static bool
 irc_is_valid_hostaddr (const char *hostaddr)
 {
-	if (regex_match ("^" N4 "\\." N4 "\\." N4 "\\." N4 "$", hostaddr, NULL)
-	 || regex_match ("^" N6 ":" N6 ":" N6 ":" N6 ":"
-		N6 ":" N6 ":" N6 ":" N6 "$", hostaddr, NULL)
-	 || regex_match ("^0:0:0:0:0:(0|[Ff]{4}):"
-		N4 "\\." N4 "\\." N4 "\\." N4 "$", hostaddr, NULL))
+	if (irc_regex_match ("^" N4 "\\." N4 "\\." N4 "\\." N4 "$", hostaddr)
+	 || irc_regex_match ("^" N6 ":" N6 ":" N6 ":" N6 ":"
+		N6 ":" N6 ":" N6 ":" N6 "$", hostaddr)
+	 || irc_regex_match ("^0:0:0:0:0:(0|[Ff]{4}):"
+		N4 "\\." N4 "\\." N4 "\\." N4 "$", hostaddr))
 		return true;
 	return false;
 }
@@ -162,7 +179,7 @@ irc_validate_nickname (const char *nickname)
 {
 	if (!*nickname)
 		return VALIDATION_ERROR_EMPTY;
-	if (!regex_match ("^[" LE SP "][-0-9" LE SP "]*$", nickname, NULL))
+	if (!irc_regex_match ("^[" LE SP "][-0-9" LE SP "]*$", nickname))
 		return VALIDATION_ERROR_INVALID;
 	if (strlen (nickname) > IRC_NICKNAME_MAX)
 		return VALIDATION_ERROR_TOO_LONG;
-- 
cgit v1.2.3-70-g09d2