Merge pull request #2597 from cesanta/str

mg_split -> mg_span. Remove mg_commalist
This commit is contained in:
Sergey Lyubka 2024-02-04 09:39:08 +00:00 committed by GitHub
commit e4bfb2b5b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 105 additions and 135 deletions

View File

@ -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 == '+';

View File

@ -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);

View File

@ -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;

View File

@ -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)));

View File

@ -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) {

View File

@ -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);

View File

@ -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 == '+';

View File

@ -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();