diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2016-04-13 21:05:27 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2016-04-13 21:05:27 -0400 |
commit | f108e0952615e08a304d4e8564789d3534233e69 (patch) | |
tree | 27d160f84d91e4c7963d93b2c4d4e4a0ce62d234 /dstring.c | |
parent | 185ae8494bfd82757dc25b0ad92ddd833415c0ad (diff) | |
download | bfs-f108e0952615e08a304d4e8564789d3534233e69.tar.xz |
dstring: Split out the dynamic string logic.
Diffstat (limited to 'dstring.c')
-rw-r--r-- | dstring.c | 99 |
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)); + } +} |