From 244e5f67d35dc81167a1d2b7ecbd4b2a243bcedf Mon Sep 17 00:00:00 2001
From: Sergey Lyubka <sergey.lyubka@cesanta.com>
Date: Wed, 28 Jun 2017 19:18:42 +0100
Subject: [PATCH] Commonize  pattern matching functions

PUBLISHED_FROM=e69e298a51dbe0f9c47184169ecad06eef0676fc
---
 docs/c-api/util.h/intro.md                    |   2 -
 docs/c-api/util.h/mg_match_prefix.md          |  14 --
 docs/c-api/util.h/mg_next_comma_list_entry.md |  21 --
 mongoose.c                                    | 179 +++++++++---------
 mongoose.h                                    |  53 +++---
 5 files changed, 119 insertions(+), 150 deletions(-)
 delete mode 100644 docs/c-api/util.h/mg_match_prefix.md
 delete mode 100644 docs/c-api/util.h/mg_next_comma_list_entry.md

diff --git a/docs/c-api/util.h/intro.md b/docs/c-api/util.h/intro.md
index 4a390e484..d04619a17 100644
--- a/docs/c-api/util.h/intro.md
+++ b/docs/c-api/util.h/intro.md
@@ -14,10 +14,8 @@ items:
   - { name: mg_hexdump_connection.md }
   - { name: mg_hexdumpf.md }
   - { name: mg_is_big_endian.md }
-  - { name: mg_match_prefix.md }
   - { name: mg_mbuf_append_base64.md }
   - { name: mg_mbuf_append_base64_putc.md }
-  - { name: mg_next_comma_list_entry.md }
   - { name: mg_open.md }
   - { name: mg_skip.md }
   - { name: mg_sock_addr_to_str.md }
diff --git a/docs/c-api/util.h/mg_match_prefix.md b/docs/c-api/util.h/mg_match_prefix.md
deleted file mode 100644
index 15ddc9ef1..000000000
--- a/docs/c-api/util.h/mg_match_prefix.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "mg_match_prefix()"
-decl_name: "mg_match_prefix"
-symbol_kind: "func"
-signature: |
-  int mg_match_prefix(const char *pattern, int pattern_len, const char *str);
----
-
-Matches 0-terminated string (mg_match_prefix) or string with given length
-mg_match_prefix_n against a glob pattern.
-
-Match is case-insensitive. Returns number of bytes matched, or -1 if no
-match. 
-
diff --git a/docs/c-api/util.h/mg_next_comma_list_entry.md b/docs/c-api/util.h/mg_next_comma_list_entry.md
deleted file mode 100644
index a96103936..000000000
--- a/docs/c-api/util.h/mg_next_comma_list_entry.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-title: "mg_next_comma_list_entry()"
-decl_name: "mg_next_comma_list_entry"
-symbol_kind: "func"
-signature: |
-  const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
-                                       struct mg_str *eq_val);
----
-
-A helper function for traversing a comma separated list of values.
-It returns a list pointer shifted to the next value or NULL if the end
-of the list found.
-The value is stored in a val vector. If the value has a form "x=y", then
-eq_val vector is initialised to point to the "y" part, and val vector length
-is adjusted to point only to "x".
-If the list is just a comma separated list of entries, like "aa,bb,cc" then
-`eq_val` will contain zero-length string.
-
-The purpose of this function is to parse comma separated string without
-any copying/memory allocation. 
-
diff --git a/mongoose.c b/mongoose.c
index 677ce124f..8379c6eb0 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -1858,6 +1858,98 @@ int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap) {
   return len;
 }
 
+const char *mg_next_comma_list_entry(const char *, struct mg_str *,
+                                     struct mg_str *) WEAK;
+const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
+                                     struct mg_str *eq_val) {
+  if (list == NULL || *list == '\0') {
+    /* End of the list */
+    list = NULL;
+  } else {
+    val->p = list;
+    if ((list = strchr(val->p, ',')) != NULL) {
+      /* Comma found. Store length and shift the list ptr */
+      val->len = list - val->p;
+      list++;
+    } else {
+      /* This value is the last one */
+      list = val->p + strlen(val->p);
+      val->len = list - val->p;
+    }
+
+    if (eq_val != NULL) {
+      /* Value has form "x=y", adjust pointers and lengths */
+      /* so that val points to "x", and eq_val points to "y". */
+      eq_val->len = 0;
+      eq_val->p = (const char *) memchr(val->p, '=', val->len);
+      if (eq_val->p != NULL) {
+        eq_val->p++; /* Skip over '=' character */
+        eq_val->len = val->p + val->len - eq_val->p;
+        val->len = (eq_val->p - val->p) - 1;
+      }
+    }
+  }
+
+  return list;
+}
+
+int mg_match_prefix_n(const struct mg_str, const struct mg_str) WEAK;
+int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str) {
+  const char *or_str;
+  size_t len, i = 0, j = 0;
+  int res;
+
+  if ((or_str = (const char *) memchr(pattern.p, '|', pattern.len)) != NULL ||
+      (or_str = (const char *) memchr(pattern.p, ',', pattern.len)) != NULL) {
+    struct mg_str pstr = {pattern.p, (size_t)(or_str - pattern.p)};
+    res = mg_match_prefix_n(pstr, str);
+    if (res > 0) return res;
+    pstr.p = or_str + 1;
+    pstr.len = (pattern.p + pattern.len) - (or_str + 1);
+    return mg_match_prefix_n(pstr, str);
+  }
+
+  for (; i < pattern.len; i++, j++) {
+    if (pattern.p[i] == '?' && j != str.len) {
+      continue;
+    } else if (pattern.p[i] == '$') {
+      return j == str.len ? (int) j : -1;
+    } else if (pattern.p[i] == '*') {
+      i++;
+      if (i < pattern.len && pattern.p[i] == '*') {
+        i++;
+        len = str.len - j;
+      } else {
+        len = 0;
+        while (j + len != str.len && str.p[j + len] != '/') {
+          len++;
+        }
+      }
+      if (i == pattern.len) {
+        return j + len;
+      }
+      do {
+        const struct mg_str pstr = {pattern.p + i, pattern.len - i};
+        const struct mg_str sstr = {str.p + j + len, str.len - j - len};
+        res = mg_match_prefix_n(pstr, sstr);
+      } while (res == -1 && len-- > 0);
+      return res == -1 ? -1 : (int) (j + res + len);
+    } else if (str_util_lowercase(&pattern.p[i]) !=
+               str_util_lowercase(&str.p[j])) {
+      return -1;
+    }
+  }
+  return j;
+}
+
+int mg_match_prefix(const char *, int, const char *) WEAK;
+int mg_match_prefix(const char *pattern, int pattern_len, const char *str) {
+  const struct mg_str pstr = {pattern, (size_t) pattern_len};
+  struct mg_str s = {str, 0};
+  if (str != NULL) s.len = strlen(str);
+  return mg_match_prefix_n(pstr, s);
+}
+
 #endif /* EXCLUDE_COMMON */
 #ifdef MG_MODULE_LINES
 #line 1 "mongoose/src/tun.h"
@@ -9451,10 +9543,6 @@ const char *mg_skip(const char *s, const char *end, const char *delims,
   return s;
 }
 
-static int lowercase(const char *s) {
-  return tolower(*(const unsigned char *) s);
-}
-
 #if MG_ENABLE_FILESYSTEM && !defined(MG_USER_FILE_FUNCTIONS)
 int mg_stat(const char *path, cs_stat_t *st) {
 #ifdef _WIN32
@@ -9707,89 +9795,6 @@ int mg_is_big_endian(void) {
   return ((char *) &n)[0] == 0;
 }
 
-const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
-                                     struct mg_str *eq_val) {
-  if (list == NULL || *list == '\0') {
-    /* End of the list */
-    list = NULL;
-  } else {
-    val->p = list;
-    if ((list = strchr(val->p, ',')) != NULL) {
-      /* Comma found. Store length and shift the list ptr */
-      val->len = list - val->p;
-      list++;
-    } else {
-      /* This value is the last one */
-      list = val->p + strlen(val->p);
-      val->len = list - val->p;
-    }
-
-    if (eq_val != NULL) {
-      /* Value has form "x=y", adjust pointers and lengths */
-      /* so that val points to "x", and eq_val points to "y". */
-      eq_val->len = 0;
-      eq_val->p = (const char *) memchr(val->p, '=', val->len);
-      if (eq_val->p != NULL) {
-        eq_val->p++; /* Skip over '=' character */
-        eq_val->len = val->p + val->len - eq_val->p;
-        val->len = (eq_val->p - val->p) - 1;
-      }
-    }
-  }
-
-  return list;
-}
-
-int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str) {
-  const char *or_str;
-  size_t len, i = 0, j = 0;
-  int res;
-
-  if ((or_str = (const char *) memchr(pattern.p, '|', pattern.len)) != NULL) {
-    struct mg_str pstr = {pattern.p, (size_t)(or_str - pattern.p)};
-    res = mg_match_prefix_n(pstr, str);
-    if (res > 0) return res;
-    pstr.p = or_str + 1;
-    pstr.len = (pattern.p + pattern.len) - (or_str + 1);
-    return mg_match_prefix_n(pstr, str);
-  }
-
-  for (; i < pattern.len; i++, j++) {
-    if (pattern.p[i] == '?' && j != str.len) {
-      continue;
-    } else if (pattern.p[i] == '$') {
-      return j == str.len ? (int) j : -1;
-    } else if (pattern.p[i] == '*') {
-      i++;
-      if (i < pattern.len && pattern.p[i] == '*') {
-        i++;
-        len = str.len - j;
-      } else {
-        len = 0;
-        while (j + len != str.len && str.p[j + len] != '/') {
-          len++;
-        }
-      }
-      if (i == pattern.len) {
-        return j + len;
-      }
-      do {
-        const struct mg_str pstr = {pattern.p + i, pattern.len - i};
-        const struct mg_str sstr = {str.p + j + len, str.len - j - len};
-        res = mg_match_prefix_n(pstr, sstr);
-      } while (res == -1 && len-- > 0);
-      return res == -1 ? -1 : (int) (j + res + len);
-    } else if (lowercase(&pattern.p[i]) != lowercase(&str.p[j])) {
-      return -1;
-    }
-  }
-  return j;
-}
-
-int mg_match_prefix(const char *pattern, int pattern_len, const char *str) {
-  const struct mg_str pstr = {pattern, (size_t) pattern_len};
-  return mg_match_prefix_n(pstr, mg_mk_str(str));
-}
 
 DO_NOT_WARN_UNUSED MG_INTERNAL int mg_get_errno(void) {
 #ifndef WINCE
diff --git a/mongoose.h b/mongoose.h
index 1067ed3b0..76bab9281 100644
--- a/mongoose.h
+++ b/mongoose.h
@@ -1955,6 +1955,7 @@ int cs_base64_decode(const unsigned char *s, int len, char *dst, int *dec_len);
 #include <stdlib.h>
 
 /* Amalgamated: #include "common/platform.h" */
+/* Amalgamated: #include "common/mg_str.h" */
 
 #ifndef CS_ENABLE_STRDUP
 #define CS_ENABLE_STRDUP 0
@@ -2049,6 +2050,32 @@ int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
 /* Same as mg_asprintf, but takes varargs list. */
 int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
 
+/*
+ * A helper function for traversing a comma separated list of values.
+ * It returns a list pointer shifted to the next value or NULL if the end
+ * of the list found.
+ * The value is stored in a val vector. If the value has a form "x=y", then
+ * eq_val vector is initialised to point to the "y" part, and val vector length
+ * is adjusted to point only to "x".
+ * If the list is just a comma separated list of entries, like "aa,bb,cc" then
+ * `eq_val` will contain zero-length string.
+ *
+ * The purpose of this function is to parse comma separated string without
+ * any copying/memory allocation.
+ */
+const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
+                                     struct mg_str *eq_val);
+
+/*
+ * Matches 0-terminated string (mg_match_prefix) or string with given length
+ * mg_match_prefix_n against a glob pattern.
+ *
+ * Match is case-insensitive. Returns number of bytes matched, or -1 if no
+ * match.
+ */
+int mg_match_prefix(const char *pattern, int pattern_len, const char *str);
+int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str);
+
 #ifdef __cplusplus
 }
 #endif
@@ -4048,32 +4075,6 @@ void mg_hexdump_connection(struct mg_connection *nc, const char *path,
  */
 int mg_is_big_endian(void);
 
-/*
- * A helper function for traversing a comma separated list of values.
- * It returns a list pointer shifted to the next value or NULL if the end
- * of the list found.
- * The value is stored in a val vector. If the value has a form "x=y", then
- * eq_val vector is initialised to point to the "y" part, and val vector length
- * is adjusted to point only to "x".
- * If the list is just a comma separated list of entries, like "aa,bb,cc" then
- * `eq_val` will contain zero-length string.
- *
- * The purpose of this function is to parse comma separated string without
- * any copying/memory allocation.
- */
-const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
-                                     struct mg_str *eq_val);
-
-/*
- * Matches 0-terminated string (mg_match_prefix) or string with given length
- * mg_match_prefix_n against a glob pattern.
- *
- * Match is case-insensitive. Returns number of bytes matched, or -1 if no
- * match.
- */
-int mg_match_prefix(const char *pattern, int pattern_len, const char *str);
-int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str);
-
 /*
  * Use with cs_base64_init/update/finish in order to write out base64 in chunks.
  */
-- 
GitLab