From f108e0952615e08a304d4e8564789d3534233e69 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 13 Apr 2016 21:05:27 -0400 Subject: dstring: Split out the dynamic string logic. --- dstring.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 dstring.c (limited to 'dstring.c') 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 * + * * + * 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 +#include + +/** + * 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)); + } +} -- cgit v1.2.3