summaryrefslogtreecommitdiff
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;
+}