From 936e7bbc8873a1888bf29f472550f7066c8072d9 Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Fri, 2 Feb 2024 23:36:12 +0000 Subject: [PATCH] mg_split -> mg_span. Remove mg_commalist --- mongoose.c | 68 +++++++++++++++-------------------- mongoose.h | 6 +--- src/http.c | 20 ++++++----- src/sntp.c | 2 +- src/str.c | 36 ++++++------------- src/str.h | 6 +--- src/util.c | 10 +++--- test/unit_test.c | 92 +++++++++++++++++++++++++----------------------- 8 files changed, 105 insertions(+), 135 deletions(-) diff --git a/mongoose.c b/mongoose.c index f8a6eb1f..6d25f19a 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2329,9 +2329,10 @@ void mg_http_bauth(struct mg_connection *c, const char *user, } struct mg_str mg_http_var(struct mg_str buf, struct mg_str name) { - struct mg_str k, v, result = mg_str_n(NULL, 0); - while (mg_split(&buf, &k, &v, '&')) { - if (name.len == k.len && mg_ncasecmp(name.ptr, k.ptr, k.len) == 0) { + struct mg_str entry, k, v, result = mg_str_n(NULL, 0); + while (mg_span(buf, &entry, &buf, '&')) { + if (mg_span(entry, &k, &v, '=') && name.len == k.len && + mg_ncasecmp(name.ptr, k.ptr, k.len) == 0) { result = v; break; } @@ -2722,7 +2723,7 @@ static struct mg_str s_known_types[] = { // clang-format on static struct mg_str guess_content_type(struct mg_str path, const char *extra) { - struct mg_str k, v, s = mg_str(extra); + struct mg_str entry, k, v, s = mg_str(extra); size_t i = 0; // Shrink path to its extension only @@ -2731,8 +2732,8 @@ static struct mg_str guess_content_type(struct mg_str path, const char *extra) { path.len = i; // Process user-provided mime type overrides, if any - while (mg_commalist(&s, &k, &v)) { - if (mg_strcmp(path, k) == 0) return v; + while (mg_span(s, &entry, &s, ',')) { + if (mg_span(entry, &k, &v, '=') && mg_strcmp(path, k) == 0) return v; } // Process built-in mime types @@ -2748,7 +2749,7 @@ static int getrange(struct mg_str *s, size_t *a, size_t *b) { for (i = 0; i + 6 < s->len; i++) { struct mg_str k, v = mg_str_n(s->ptr + i + 6, s->len - i - 6); if (memcmp(&s->ptr[i], "bytes=", 6) != 0) continue; - if (mg_split(&v, &k, NULL, '-')) { + if (mg_span(v, &k, &v, '-')) { if (mg_to_size_t(k, a)) numparsed++; if (v.len > 0 && mg_to_size_t(v, b)) numparsed++; } else { @@ -3028,8 +3029,9 @@ static int uri_to_path(struct mg_connection *c, struct mg_http_message *hm, const struct mg_http_serve_opts *opts, char *path, size_t path_size) { struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs; - struct mg_str k, v, s = mg_str(opts->root_dir), u = {0, 0}, p = {0, 0}; - while (mg_commalist(&s, &k, &v)) { + struct mg_str k, v, part, s = mg_str(opts->root_dir), u = {NULL, 0}, p = u; + while (mg_span(s, &part, &s, ',')) { + if (!mg_span(part, &k, &v, '=')) k = part, v = mg_str_n(NULL, 0); if (v.len == 0) v = k, k = mg_str("/"), u = k, p = v; if (hm->uri.len < k.len) continue; if (mg_strcmp(k, mg_str_n(hm->uri.ptr, k.len)) != 0) continue; @@ -7011,7 +7013,7 @@ static void sntp_cb(struct mg_connection *c, int ev, void *ev_data) { if (ev == MG_EV_READ) { int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len); if (milliseconds > 0) { - MG_INFO(("%lu got time: %lld ms from epoch", c->id, milliseconds)); + MG_DEBUG(("%lu got time: %lld ms from epoch", c->id, milliseconds)); mg_call(c, MG_EV_SNTP_TIME, (uint64_t *) &milliseconds); MG_VERBOSE(("%u.%u", (unsigned) (milliseconds / 1000), (unsigned) (milliseconds % 1000))); @@ -8003,31 +8005,17 @@ bool mg_globmatch(const char *s1, size_t n1, const char *s2, size_t n2) { return mg_match(mg_str_n(s2, n2), mg_str_n(s1, n1), NULL); } -static size_t mg_nce(const char *s, size_t n, size_t ofs, size_t *koff, - size_t *klen, size_t *voff, size_t *vlen, char delim) { - size_t kvlen, kl; - for (kvlen = 0; ofs + kvlen < n && s[ofs + kvlen] != delim;) kvlen++; - for (kl = 0; kl < kvlen && s[ofs + kl] != '=';) kl++; - if (koff != NULL) *koff = ofs; - if (klen != NULL) *klen = kl; - if (voff != NULL) *voff = kl < kvlen ? ofs + kl + 1 : 0; - if (vlen != NULL) *vlen = kl < kvlen ? kvlen - kl - 1 : 0; - ofs += kvlen + 1; - return ofs > n ? n : ofs; -} - -bool mg_split(struct mg_str *s, struct mg_str *k, struct mg_str *v, char sep) { - size_t koff = 0, klen = 0, voff = 0, vlen = 0, off = 0; - if (s->ptr == NULL || s->len == 0) return 0; - off = mg_nce(s->ptr, s->len, 0, &koff, &klen, &voff, &vlen, sep); - if (k != NULL) *k = mg_str_n(s->ptr + koff, klen); - if (v != NULL) *v = mg_str_n(s->ptr + voff, vlen); - *s = mg_str_n(s->ptr + off, s->len - off); - return off > 0; -} - -bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v) { - return mg_split(s, k, v, ','); +bool mg_span(struct mg_str s, struct mg_str *a, struct mg_str *b, char sep) { + if (s.len == 0 || s.ptr == NULL) { + return false; // Empty string, nothing to span - fail + } else { + size_t len = 0; + while (len < s.len && s.ptr[len] != sep) len++; // Find separator + if (a) *a = mg_str_n(s.ptr, len); // Init a + if (b) *b = mg_str_n(s.ptr + len, s.len - len); // Init b + if (b && len < s.len) b->ptr++, b->len--; // Skip separator + return true; + } } char *mg_hex(const void *buf, size_t len, char *to) { @@ -13880,18 +13868,18 @@ static int parse_net(const char *spec, uint32_t *net, uint32_t *mask) { } int mg_check_ip_acl(struct mg_str acl, struct mg_addr *remote_ip) { - struct mg_str k, v; + struct mg_str entry; int allowed = acl.len == 0 ? '+' : '-'; // If any ACL is set, deny by default uint32_t remote_ip4; if (remote_ip->is_ip6) { return -1; // TODO(): handle IPv6 ACL and addresses } else { // IPv4 memcpy((void *) &remote_ip4, remote_ip->ip, sizeof(remote_ip4)); - while (mg_commalist(&acl, &k, &v)) { + while (mg_span(acl, &entry, &acl, ',')) { uint32_t net, mask; - if (k.ptr[0] != '+' && k.ptr[0] != '-') return -1; - if (parse_net(&k.ptr[1], &net, &mask) == 0) return -2; - if ((mg_ntohl(remote_ip4) & mask) == net) allowed = k.ptr[0]; + if (entry.ptr[0] != '+' && entry.ptr[0] != '-') return -1; + if (parse_net(&entry.ptr[1], &net, &mask) == 0) return -2; + if ((mg_ntohl(remote_ip4) & mask) == net) allowed = entry.ptr[0]; } } return allowed == '+'; diff --git a/mongoose.h b/mongoose.h index 9ac3edf7..8295160a 100644 --- a/mongoose.h +++ b/mongoose.h @@ -840,9 +840,6 @@ struct mg_str { size_t len; // String len }; -#define MG_NULL_STR \ - { NULL, 0 } - #define MG_C_STR(a) \ { (a), sizeof(a) - 1 } @@ -862,8 +859,7 @@ struct mg_str mg_strdup(const struct mg_str s); const char *mg_strstr(const struct mg_str haystack, const struct mg_str needle); bool mg_match(struct mg_str str, struct mg_str pattern, struct mg_str *caps); bool mg_globmatch(const char *pattern, size_t plen, const char *s, size_t n); -bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v); -bool mg_split(struct mg_str *s, struct mg_str *k, struct mg_str *v, char delim); +bool mg_span(struct mg_str s, struct mg_str *a, struct mg_str *b, char delim); char *mg_hex(const void *buf, size_t len, char *dst); void mg_unhex(const char *buf, size_t len, unsigned char *to); unsigned long mg_unhexn(const char *s, size_t len); diff --git a/src/http.c b/src/http.c index 14a7cb4b..f3a19cc1 100644 --- a/src/http.c +++ b/src/http.c @@ -113,9 +113,10 @@ void mg_http_bauth(struct mg_connection *c, const char *user, } struct mg_str mg_http_var(struct mg_str buf, struct mg_str name) { - struct mg_str k, v, result = mg_str_n(NULL, 0); - while (mg_split(&buf, &k, &v, '&')) { - if (name.len == k.len && mg_ncasecmp(name.ptr, k.ptr, k.len) == 0) { + struct mg_str entry, k, v, result = mg_str_n(NULL, 0); + while (mg_span(buf, &entry, &buf, '&')) { + if (mg_span(entry, &k, &v, '=') && name.len == k.len && + mg_ncasecmp(name.ptr, k.ptr, k.len) == 0) { result = v; break; } @@ -506,7 +507,7 @@ static struct mg_str s_known_types[] = { // clang-format on static struct mg_str guess_content_type(struct mg_str path, const char *extra) { - struct mg_str k, v, s = mg_str(extra); + struct mg_str entry, k, v, s = mg_str(extra); size_t i = 0; // Shrink path to its extension only @@ -515,8 +516,8 @@ static struct mg_str guess_content_type(struct mg_str path, const char *extra) { path.len = i; // Process user-provided mime type overrides, if any - while (mg_commalist(&s, &k, &v)) { - if (mg_strcmp(path, k) == 0) return v; + while (mg_span(s, &entry, &s, ',')) { + if (mg_span(entry, &k, &v, '=') && mg_strcmp(path, k) == 0) return v; } // Process built-in mime types @@ -532,7 +533,7 @@ static int getrange(struct mg_str *s, size_t *a, size_t *b) { for (i = 0; i + 6 < s->len; i++) { struct mg_str k, v = mg_str_n(s->ptr + i + 6, s->len - i - 6); if (memcmp(&s->ptr[i], "bytes=", 6) != 0) continue; - if (mg_split(&v, &k, NULL, '-')) { + if (mg_span(v, &k, &v, '-')) { if (mg_to_size_t(k, a)) numparsed++; if (v.len > 0 && mg_to_size_t(v, b)) numparsed++; } else { @@ -812,8 +813,9 @@ static int uri_to_path(struct mg_connection *c, struct mg_http_message *hm, const struct mg_http_serve_opts *opts, char *path, size_t path_size) { struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs; - struct mg_str k, v, s = mg_str(opts->root_dir), u = {0, 0}, p = {0, 0}; - while (mg_commalist(&s, &k, &v)) { + struct mg_str k, v, part, s = mg_str(opts->root_dir), u = {NULL, 0}, p = u; + while (mg_span(s, &part, &s, ',')) { + if (!mg_span(part, &k, &v, '=')) k = part, v = mg_str_n(NULL, 0); if (v.len == 0) v = k, k = mg_str("/"), u = k, p = v; if (hm->uri.len < k.len) continue; if (mg_strcmp(k, mg_str_n(hm->uri.ptr, k.len)) != 0) continue; diff --git a/src/sntp.c b/src/sntp.c index b3f2962c..4d2d9a6e 100644 --- a/src/sntp.c +++ b/src/sntp.c @@ -42,7 +42,7 @@ static void sntp_cb(struct mg_connection *c, int ev, void *ev_data) { if (ev == MG_EV_READ) { int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len); if (milliseconds > 0) { - MG_INFO(("%lu got time: %lld ms from epoch", c->id, milliseconds)); + MG_DEBUG(("%lu got time: %lld ms from epoch", c->id, milliseconds)); mg_call(c, MG_EV_SNTP_TIME, (uint64_t *) &milliseconds); MG_VERBOSE(("%u.%u", (unsigned) (milliseconds / 1000), (unsigned) (milliseconds % 1000))); diff --git a/src/str.c b/src/str.c index 50ed0347..7902b783 100644 --- a/src/str.c +++ b/src/str.c @@ -129,31 +129,17 @@ bool mg_globmatch(const char *s1, size_t n1, const char *s2, size_t n2) { return mg_match(mg_str_n(s2, n2), mg_str_n(s1, n1), NULL); } -static size_t mg_nce(const char *s, size_t n, size_t ofs, size_t *koff, - size_t *klen, size_t *voff, size_t *vlen, char delim) { - size_t kvlen, kl; - for (kvlen = 0; ofs + kvlen < n && s[ofs + kvlen] != delim;) kvlen++; - for (kl = 0; kl < kvlen && s[ofs + kl] != '=';) kl++; - if (koff != NULL) *koff = ofs; - if (klen != NULL) *klen = kl; - if (voff != NULL) *voff = kl < kvlen ? ofs + kl + 1 : 0; - if (vlen != NULL) *vlen = kl < kvlen ? kvlen - kl - 1 : 0; - ofs += kvlen + 1; - return ofs > n ? n : ofs; -} - -bool mg_split(struct mg_str *s, struct mg_str *k, struct mg_str *v, char sep) { - size_t koff = 0, klen = 0, voff = 0, vlen = 0, off = 0; - if (s->ptr == NULL || s->len == 0) return 0; - off = mg_nce(s->ptr, s->len, 0, &koff, &klen, &voff, &vlen, sep); - if (k != NULL) *k = mg_str_n(s->ptr + koff, klen); - if (v != NULL) *v = mg_str_n(s->ptr + voff, vlen); - *s = mg_str_n(s->ptr + off, s->len - off); - return off > 0; -} - -bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v) { - return mg_split(s, k, v, ','); +bool mg_span(struct mg_str s, struct mg_str *a, struct mg_str *b, char sep) { + if (s.len == 0 || s.ptr == NULL) { + return false; // Empty string, nothing to span - fail + } else { + size_t len = 0; + while (len < s.len && s.ptr[len] != sep) len++; // Find separator + if (a) *a = mg_str_n(s.ptr, len); // Init a + if (b) *b = mg_str_n(s.ptr + len, s.len - len); // Init b + if (b && len < s.len) b->ptr++, b->len--; // Skip separator + return true; + } } char *mg_hex(const void *buf, size_t len, char *to) { diff --git a/src/str.h b/src/str.h index f0a7ea31..2ae80b80 100644 --- a/src/str.h +++ b/src/str.h @@ -7,9 +7,6 @@ struct mg_str { size_t len; // String len }; -#define MG_NULL_STR \ - { NULL, 0 } - #define MG_C_STR(a) \ { (a), sizeof(a) - 1 } @@ -29,8 +26,7 @@ struct mg_str mg_strdup(const struct mg_str s); const char *mg_strstr(const struct mg_str haystack, const struct mg_str needle); bool mg_match(struct mg_str str, struct mg_str pattern, struct mg_str *caps); bool mg_globmatch(const char *pattern, size_t plen, const char *s, size_t n); -bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v); -bool mg_split(struct mg_str *s, struct mg_str *k, struct mg_str *v, char delim); +bool mg_span(struct mg_str s, struct mg_str *a, struct mg_str *b, char delim); char *mg_hex(const void *buf, size_t len, char *dst); void mg_unhex(const char *buf, size_t len, unsigned char *to); unsigned long mg_unhexn(const char *s, size_t len); diff --git a/src/util.c b/src/util.c index de6604f1..e983e177 100644 --- a/src/util.c +++ b/src/util.c @@ -89,18 +89,18 @@ static int parse_net(const char *spec, uint32_t *net, uint32_t *mask) { } int mg_check_ip_acl(struct mg_str acl, struct mg_addr *remote_ip) { - struct mg_str k, v; + struct mg_str entry; int allowed = acl.len == 0 ? '+' : '-'; // If any ACL is set, deny by default uint32_t remote_ip4; if (remote_ip->is_ip6) { return -1; // TODO(): handle IPv6 ACL and addresses } else { // IPv4 memcpy((void *) &remote_ip4, remote_ip->ip, sizeof(remote_ip4)); - while (mg_commalist(&acl, &k, &v)) { + while (mg_span(acl, &entry, &acl, ',')) { uint32_t net, mask; - if (k.ptr[0] != '+' && k.ptr[0] != '-') return -1; - if (parse_net(&k.ptr[1], &net, &mask) == 0) return -2; - if ((mg_ntohl(remote_ip4) & mask) == net) allowed = k.ptr[0]; + if (entry.ptr[0] != '+' && entry.ptr[0] != '-') return -1; + if (parse_net(&entry.ptr[1], &net, &mask) == 0) return -2; + if ((mg_ntohl(remote_ip4) & mask) == net) allowed = entry.ptr[0]; } } return allowed == '+'; diff --git a/test/unit_test.c b/test/unit_test.c index 2da5e44c..5d365466 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -128,38 +128,6 @@ static void test_globmatch(void) { } } -static void test_commalist(void) { - struct mg_str k, v, s1 = mg_str(""), s2 = mg_str("a"), s3 = mg_str("a,b"); - struct mg_str s4 = mg_str("a=123"), s5 = mg_str("a,b=123"); - ASSERT(mg_commalist(&s1, &k, &v) == false); - - v.len = k.len = 42; - ASSERT(mg_commalist(&s2, &k, &v) == true); - ASSERT(v.len == 0 && mg_vcmp(&k, "a") == 0); - ASSERT(mg_commalist(&s2, &k, &v) == false); - - v.len = k.len = 42; - ASSERT(mg_commalist(&s3, &k, &v) == true); - ASSERT(v.len == 0 && mg_vcmp(&k, "a") == 0); - v.len = k.len = 42; - ASSERT(mg_commalist(&s3, &k, &v) == true); - ASSERT(v.len == 0 && mg_vcmp(&k, "b") == 0); - ASSERT(mg_commalist(&s3, &k, &v) == false); - - v.len = k.len = 42; - ASSERT(mg_commalist(&s4, &k, &v) == true); - ASSERT(mg_vcmp(&k, "a") == 0 && mg_vcmp(&v, "123") == 0); - ASSERT(mg_commalist(&s4, &k, &v) == false); - ASSERT(mg_commalist(&s4, &k, &v) == false); - - v.len = k.len = 42; - ASSERT(mg_commalist(&s5, &k, &v) == true); - ASSERT(v.len == 0 && mg_vcmp(&k, "a") == 0); - ASSERT(mg_commalist(&s5, &k, &v) == true); - ASSERT(mg_vcmp(&k, "b") == 0 && mg_vcmp(&v, "123") == 0); - ASSERT(mg_commalist(&s4, &k, &v) == false); -} - static void test_http_get_var(void) { char buf[256]; struct mg_str body; @@ -3262,20 +3230,55 @@ static void test_sha1(void) { test_sha1_str(")_)+_)!&^*%$#>>>{}}}{{{][[[[]]]", expected_hash_3); } - static void test_split(void) { - struct mg_str k = mg_str_n("", 7), v = mg_str_n("", 8), s = mg_str(""); - ASSERT(mg_split(&s, &k, NULL, '.') == false); - ASSERT(mg_split(&s, &k, &v, '.') == false); + struct mg_str a, b, s; + s = mg_str(""); - ASSERT(mg_split(&s, NULL, NULL, '.') == false); - s = mg_str("aa.bb"); - k = mg_str_n("", 7); - ASSERT(mg_split(&s, &k, NULL, '.') == true); - ASSERT(mg_strcmp(k, mg_str("aa")) == 0); - ASSERT(mg_split(&s, &k, NULL, '.') == true); - ASSERT(mg_strcmp(k, mg_str("bb")) == 0); - ASSERT(mg_split(&s, &k, NULL, '.') == false); + ASSERT(mg_span(s, &a, &s, '.') == false); + ASSERT(mg_span(s, &a, NULL, '.') == false); + ASSERT(mg_span(s, NULL, &b, '.') == false); + ASSERT(mg_span(s, NULL, NULL, '.') == false); + ASSERT(mg_span(s, &a, &b, '.') == false); + + s = mg_str("aa.bb.cc"), a = mg_str_n(NULL, 0), b = mg_str_n(NULL, 0); + ASSERT(mg_span(s, &a, &b, '.') == true); + ASSERT(mg_strcmp(a, mg_str("aa")) == 0); + ASSERT(mg_strcmp(b, mg_str("bb.cc")) == 0); + ASSERT(mg_strcmp(s, mg_str("aa.bb.cc")) == 0); + + s = mg_str("aa.bb.cc"), a = mg_str_n(NULL, 0), b = mg_str_n(NULL, 0); + ASSERT(mg_span(s, &a, NULL, '.') == true); + ASSERT(mg_strcmp(a, mg_str("aa")) == 0); + ASSERT(mg_strcmp(s, mg_str("aa.bb.cc")) == 0); + + s = mg_str("aa.bb.cc"), a = mg_str_n(NULL, 0), b = mg_str_n(NULL, 0); + ASSERT(mg_span(s, NULL, &b, '.') == true); + ASSERT(mg_strcmp(b, mg_str("bb.cc")) == 0); + ASSERT(mg_strcmp(s, mg_str("aa.bb.cc")) == 0); + + s = mg_str("aa.bb.cc"), a = mg_str_n(NULL, 0), b = mg_str_n(NULL, 0); + ASSERT(mg_span(s, NULL, NULL, '.') == true); + ASSERT(mg_strcmp(s, mg_str("aa.bb.cc")) == 0); + + s = mg_str("aa.bb.cc"), a = mg_str_n(NULL, 0), b = mg_str_n(NULL, 0); + ASSERT(mg_span(s, &a, &s, '.') == true); + ASSERT(mg_strcmp(a, mg_str("aa")) == 0); + ASSERT(mg_strcmp(s, mg_str("bb.cc")) == 0); + + s = mg_str(".aa"), a = mg_str_n(NULL, 0), b = mg_str_n(NULL, 0); + ASSERT(mg_span(s, &a, &b, '.') == true); + ASSERT(mg_strcmp(a, mg_str("")) == 0); + ASSERT(mg_strcmp(b, mg_str("aa")) == 0); + + s = mg_str("aa."), a = mg_str_n(NULL, 0), b = mg_str_n(NULL, 0); + ASSERT(mg_span(s, &a, &b, '.') == true); + ASSERT(mg_strcmp(a, mg_str("aa")) == 0); + ASSERT(mg_strcmp(b, mg_str("")) == 0); + + s = mg_str("aa"), a = mg_str_n(NULL, 0), b = mg_str_n(NULL, 0); + ASSERT(mg_span(s, &a, &b, '.') == true); + ASSERT(mg_strcmp(a, mg_str("aa")) == 0); + ASSERT(mg_strcmp(b, mg_str("")) == 0); } int main(void) { @@ -3306,7 +3309,6 @@ int main(void) { test_timer(); test_url(); test_iobuf(); - test_commalist(); test_base64(); test_http_get_var(); test_http_client();