summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parse.c61
-rw-r--r--strv.c14
-rw-r--r--strv.h13
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