summary refs log tree commit diff
diff options
context:
space:
mode:
authorWormHeamer2024-11-10 00:53:34 -0500
committerWormHeamer2024-11-10 00:57:53 -0500
commit9a513348057d8c62a65e08214206dae77b766b83 (patch)
treebfe0f4c23b72bda67f3db15ceca83a207fc97747
parent3f54d883edc90d0e6419210eff6be8125ba89daf (diff)
add str_fmt()
-rw-r--r--parse.c55
-rw-r--r--str.c25
-rw-r--r--str.h2
3 files changed, 48 insertions, 34 deletions
diff --git a/parse.c b/parse.c
index b2ac019..ab59fb2 100644
--- a/parse.c
+++ b/parse.c
@@ -35,18 +35,12 @@ int parse_plain(struct doc *d, const str_t *b) {
 	return 0;
 }
 
-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++];
-	}
-	return i;
+int parse_gophermap_line(struct doc *d, strv_t ln) {
+	return 0;
 }
 
-int parse_gophermap_line(struct doc *d, strv_t ln) {
-	if (ln.n == 1 && ln.s[0] == '.') return 1;
-	char url[512] = "gopher://";
-	size_t urln = 9;
+int parse_gophermap(struct doc *d, const str_t *b) {
+	str_t url;
 	struct {
 		char item_type;
 		strv_t dstr;
@@ -54,35 +48,28 @@ int parse_gophermap_line(struct doc *d, strv_t ln) {
 		strv_t host;
 		strv_t port;
 	} bits;
-	bits.item_type = strv_next(&ln);
-	strv_split(&ln, '\t', &bits.dstr);
-	strv_split(&ln, '\t', &bits.sel);
-	strv_split(&ln, '\t', &bits.host);
-	strv_split(&ln, '\t', &bits.port);
-	switch (bits.item_type) {
-	default:
-		urln = scatss(url, urln, sizeof url, bits.host);
-		if (urln < sizeof url) url[urln++] = ':';
-		urln = scatss(url, urln, sizeof url, bits.port);
-		if (urln < sizeof url) url[urln++] = '/';
-		if (urln < sizeof url) url[urln++] = bits.item_type;
-		urln = scatss(url, urln, sizeof url, bits.sel);
-		doc_set_link(d, doc_add_link(d, (strv_t) { url, urln }));
-	case 'i':
-		doc_add_text(d, bits.dstr);
-		doc_new_line(d);
-		break;
-	}
-	return 0;
-}
-
-int parse_gophermap(struct doc *d, const str_t *b) {
 	doc_init(d);
+	str_init(&url, 64);
 	strv_t ln, buf = { b->buf, b->sz };
 	while (strv_split(&buf, '\n', &ln)) {
 		if (ln.n > 0 && ln.s[ln.n - 1] == '\r') ln.n--;
-		if (parse_gophermap_line(d, ln)) break;
+		if (ln.n == 1 && ln.s[0] == '.') break;
+		bits.item_type = strv_next(&ln);
+		strv_split(&ln, '\t', &bits.dstr);
+		strv_split(&ln, '\t', &bits.sel);
+		strv_split(&ln, '\t', &bits.host);
+		strv_split(&ln, '\t', &bits.port);
+		switch (bits.item_type) {
+		default:
+			str_fmt(&url, "%s:%s/%c%s", bits.host, bits.port, bits.item_type, bits.sel);
+			doc_set_link(d, doc_add_link(d, (strv_t) { url.buf, url.sz }));
+		case 'i':
+			doc_add_text(d, bits.dstr);
+			doc_new_line(d);
+			break;
+		}
 	}
+	str_free(&url);
 	return 0;
 }
 
diff --git a/str.c b/str.c
index 1c09f11..8d1806e 100644
--- a/str.c
+++ b/str.c
@@ -1,4 +1,5 @@
 #include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
 #include "str.h"
 #include "err.h"
@@ -67,3 +68,27 @@ char strv_next(strv_t *s) {
 		return 0;
 	}
 }
+
+void str_fmt(str_t *b, const char *fmt, ...) {
+	va_list ap;
+	char c;
+	b->sz = 0;
+	va_start(ap, fmt);
+	while ((c = *fmt++)) {
+		if (c == '%' && *fmt) {
+			switch ((c = *fmt++)) {
+			case 'c':
+				str_catc(b, va_arg(ap, int));
+				break;
+			case 's':
+				str_cat(b, va_arg(ap, strv_t));
+				break;
+			default:
+				str_catc(b, c);
+			}
+		} else {
+			str_catc(b, c);
+		}
+	}
+	va_end(ap);
+}
diff --git a/str.h b/str.h
index a078cfd..a6324f0 100644
--- a/str.h
+++ b/str.h
@@ -28,4 +28,6 @@ void str_free(str_t *);
 void str_cat(str_t *b, strv_t s);
 void str_catc(str_t *b, char c);
 
+void str_fmt(str_t *b, const char *fmt, ...);
+
 #endif