diff options
-rw-r--r-- | parse.c | 61 | ||||
-rw-r--r-- | strv.c | 14 | ||||
-rw-r--r-- | strv.h | 13 |
3 files changed, 47 insertions, 41 deletions
diff --git a/parse.c b/parse.c index a57c1b3..b6fedd1 100644 --- a/parse.c +++ b/parse.c @@ -2,13 +2,9 @@ #include <string.h> #include "parse.h" +#include "strv.h" #include "err.h" -struct str_slice { - const char *s; - size_t n; -}; - int isurlch(char c) { return isalpha(c) || isdigit(c) || c == '-' || c == '.' || c == '_' || c == '~' || c == '!' || c == '$' || c == '\'' || c == '(' || c == ')' || c == '*' || c == '+' || c == ',' || c == ';' || c == '=' || c == '%' || c == '@' || c == ':' || c == '/'; } @@ -47,20 +43,7 @@ int parse_plain(struct doc *d, const buf_t *b) { return 0; } -static struct str_slice gmbit(size_t *i, const char *s, size_t n) { - struct str_slice ss = { - &s[*i], - 0 - }; - while (*i < n && s[*i] != '\t') { - *i += 1; - ss.n++; - } - *i += 1; - return ss; -} - -size_t scatss(char *buf, size_t i, size_t n, struct str_slice ss) { +size_t scatss(char *buf, size_t i, size_t n, strv_t ss) { size_t si = 0; while (i < n && si < ss.n) { buf[i++] = ss.s[si++]; @@ -68,25 +51,25 @@ size_t scatss(char *buf, size_t i, size_t n, struct str_slice ss) { return i; } -int parse_gophermap_line(struct doc *d, const char *s, size_t n) { +int parse_gophermap_line(struct doc *d, strv_t ln) { char url[512] = "gopher://"; size_t urln = 9; struct { char item_type; - struct str_slice dstr; - struct str_slice sel; - struct str_slice host; - struct str_slice port; + strv_t dstr; + strv_t sel; + strv_t host; + strv_t port; } bits; size_t i = 0; - bits.item_type = s[i++]; - bits.dstr = gmbit(&i, s, n); - bits.sel = gmbit(&i, s, n); - bits.host = gmbit(&i, s, n); - bits.port = gmbit(&i, s, n); + bits.item_type = ln.s[i++]; + bits.dstr = strv_head(ln, '\t', &i); + bits.sel = strv_head(ln, '\t', &i); + bits.host = strv_head(ln, '\t', &i); + bits.port = strv_head(ln, '\t', &i); switch (bits.item_type) { case '.': - if (n == 1) return 1; + if (ln.n == 1) return 1; default: urln = scatss(url, urln, sizeof url, bits.host); if (urln < sizeof url) url[urln++] = ':'; @@ -106,17 +89,13 @@ int parse_gophermap_line(struct doc *d, const char *s, size_t n) { int parse_gophermap(struct doc *d, const buf_t *b) { doc_init(d); - size_t ln_start = 0; - for (size_t i = 0; i < b->sz; i++) { - if (b->buf[i] == '\r') continue; - if (b->buf[i] == '\n') { - char *ln_str = &b->buf[ln_start]; - size_t ln_len = i - ln_start; - if (i > 0 && b->buf[i - 1] == '\r') ln_len--; - if (parse_gophermap_line(d, ln_str, ln_len)) { - break; - } - ln_start = i + 1; + size_t i = 0; + strv_t bufss = { b->buf, b->sz }; + while (i < b->sz) { + strv_t ln = strv_head(bufss, '\n', &i); + if (ln.n > 0 && ln.s[ln.n - 1] == '\r') ln.n--; + if (parse_gophermap_line(d, ln)) { + break; } } return 0; diff --git a/strv.c b/strv.c new file mode 100644 index 0000000..5da11f5 --- /dev/null +++ b/strv.c @@ -0,0 +1,14 @@ +#include <string.h> + +#include "strv.h" + +strv_t strv_head(strv_t ss, int chr, size_t *i) { + size_t j = i ? *i : 0; + char *c = memchr(&ss.s[j], chr, ss.n - j); + strv_t r = { + &ss.s[j], + c ? c - &ss.s[j] : ss.n - j + }; + if (i) *i = j + r.n + !!c; + return r; +} diff --git a/strv.h b/strv.h new file mode 100644 index 0000000..553a39c --- /dev/null +++ b/strv.h @@ -0,0 +1,13 @@ +#ifndef STRV_H +#define STRV_H + +#include <stddef.h> + +typedef struct { + const char *s; + size_t n; +} strv_t; + +strv_t strv_head(strv_t ss, int chr, size_t *i); + +#endif |