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