summaryrefslogtreecommitdiffstats
path: root/dstring.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2016-04-13 21:05:27 -0400
committerTavian Barnes <tavianator@tavianator.com>2016-04-13 21:05:27 -0400
commitf108e0952615e08a304d4e8564789d3534233e69 (patch)
tree27d160f84d91e4c7963d93b2c4d4e4a0ce62d234 /dstring.c
parent185ae8494bfd82757dc25b0ad92ddd833415c0ad (diff)
downloadbfs-f108e0952615e08a304d4e8564789d3534233e69.tar.xz
dstring: Split out the dynamic string logic.
Diffstat (limited to 'dstring.c')
-rw-r--r--dstring.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/dstring.c b/dstring.c
new file mode 100644
index 0000000..9c65757
--- /dev/null
+++ b/dstring.c
@@ -0,0 +1,99 @@
+/*********************************************************************
+ * bfs *
+ * Copyright (C) 2016 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This program is free software. It comes without any warranty, to *
+ * the extent permitted by applicable law. You can redistribute it *
+ * and/or modify it under the terms of the Do What The Fuck You Want *
+ * To Public License, Version 2, as published by Sam Hocevar. See *
+ * the COPYING file or http://www.wtfpl.net/ for more details. *
+ *********************************************************************/
+
+#include "dstring.h"
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * The memory representation of a dynamic string. Users get a pointer to data.
+ */
+struct dstring {
+ size_t capacity;
+ size_t length;
+ char data[];
+};
+
+static struct dstring *dstrheader(const char *dstr) {
+ return (struct dstring *)(dstr - offsetof(struct dstring, data));
+}
+
+static size_t dstrsize(size_t capacity) {
+ return sizeof(struct dstring) + capacity + 1;
+}
+
+char *dstralloc(size_t capacity) {
+ struct dstring *header = malloc(dstrsize(capacity));
+ if (!header) {
+ return NULL;
+ }
+
+ header->capacity = capacity;
+ header->length = 0;
+ return header->data;
+}
+
+size_t dstrlen(const char *dstr) {
+ return dstrheader(dstr)->length;
+}
+
+int dstreserve(char **dstr, size_t capacity) {
+ struct dstring *header = dstrheader(*dstr);
+
+ if (capacity > header->capacity) {
+ capacity *= 2;
+
+ header = realloc(header, dstrsize(capacity));
+ if (!header) {
+ return -1;
+ }
+ header->capacity = capacity;
+
+ *dstr = header->data;
+ }
+
+ return 0;
+}
+
+int dstresize(char **dstr, size_t length) {
+ if (dstreserve(dstr, length) != 0) {
+ return -1;
+ }
+
+ struct dstring *header = dstrheader(*dstr);
+ header->length = length;
+ header->data[length] = '\0';
+
+ return 0;
+}
+
+int dstrcat(char **dest, const char *src) {
+ struct dstring *header = dstrheader(*dest);
+ return dstrcatat(dest, header->length, src);
+}
+
+int dstrcatat(char **dest, size_t pos, const char *src) {
+ size_t srclen = strlen(src);
+ size_t destlen = pos + srclen;
+
+ if (dstresize(dest, destlen) != 0) {
+ return -1;
+ }
+
+ memcpy(*dest + pos, src, srclen);
+ return 0;
+}
+
+void dstrfree(char *dstr) {
+ if (dstr) {
+ free(dstrheader(dstr));
+ }
+}