summary refs log tree commit diff
path: root/str.c
diff options
context:
space:
mode:
Diffstat (limited to 'str.c')
-rw-r--r--str.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/str.c b/str.c
new file mode 100644
index 0000000..10d64e1
--- /dev/null
+++ b/str.c
@@ -0,0 +1,60 @@
+#include <stdlib.h>
+#include <string.h>
+#include "str.h"
+#include "err.h"
+
+/* strings */
+
+void str_init(str_t *b, size_t n) {
+	b->buf = calloc(1, n);
+	if (!b->buf) {
+		efatal("str_init");
+	}
+	b->cap = n;
+	b->sz = 0;
+}
+
+/* does NOT change sz! just makes room */
+void str_grow(str_t *b, size_t n) {
+	size_t sz = b->sz + n;
+	size_t c = b->cap;
+	if (sz > c) {
+		while (sz > c) c <<= 1;
+		char *p = realloc(b->buf, c);
+		if (!p) efatal("str_grow");
+		b->buf = p;
+		b->cap = c;
+	}
+}
+
+void str_cat(str_t *b, strv_t s) {
+	str_grow(b, s.n);
+	memcpy(&b->buf[b->sz], s.s, s.n);
+	b->sz += s.n;
+}
+
+void str_catc(str_t *b, char c) {
+	str_grow(b, 1);
+	b->buf[b->sz++] = c;
+}
+
+void str_free(str_t *b) {
+	free(b->buf);
+}
+
+/* string views */
+
+strv_t strv(const char *s) {
+	return (strv_t) { s, strlen(s) };
+}
+
+int strv_split(strv_t *src, int chr, strv_t *dest) {
+	char *c = memchr(src->s, chr, src->n);
+	*dest = (strv_t) {
+		src->s,
+		c ? c - src->s : src->n 
+	};
+	src->s = c ? c + 1 : &src->s[src->n];
+	src->n -= dest->n + !!c;
+	return dest->n > 0;
+}