diff options
Diffstat (limited to 'dstring.c')
-rw-r--r-- | dstring.c | 220 |
1 files changed, 0 insertions, 220 deletions
diff --git a/dstring.c b/dstring.c deleted file mode 100644 index f344d09..0000000 --- a/dstring.c +++ /dev/null @@ -1,220 +0,0 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2016-2022 Tavian Barnes <tavianator@tavianator.com> * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ - -#include "dstring.h" -#include <assert.h> -#include <stdarg.h> -#include <stdio.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[]; -}; - -/** Get the string header from the string data pointer. */ -static struct dstring *dstrheader(const char *dstr) { - return (struct dstring *)(dstr - offsetof(struct dstring, data)); -} - -/** Get the correct size for a dstring with the given capacity. */ -static size_t dstrsize(size_t capacity) { - return BFS_FLEX_SIZEOF(struct dstring, data, capacity + 1); -} - -/** Allocate a dstring with the given contents. */ -static char *dstralloc_impl(size_t capacity, size_t length, const char *data) { - // Avoid reallocations for small strings - if (capacity < 7) { - capacity = 7; - } - - struct dstring *header = malloc(dstrsize(capacity)); - if (!header) { - return NULL; - } - - header->capacity = capacity; - header->length = length; - - memcpy(header->data, data, length); - header->data[length] = '\0'; - return header->data; -} - -char *dstralloc(size_t capacity) { - return dstralloc_impl(capacity, 0, ""); -} - -char *dstrdup(const char *str) { - size_t len = strlen(str); - return dstralloc_impl(len, len, str); -} - -char *dstrndup(const char *str, size_t n) { - size_t len = strnlen(str, n); - return dstralloc_impl(len, len, str); -} - -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; -} - -/** Common implementation of dstr{cat,ncat,app}. */ -static int dstrcat_impl(char **dest, const char *src, size_t srclen) { - size_t oldlen = dstrlen(*dest); - size_t newlen = oldlen + srclen; - - if (dstresize(dest, newlen) != 0) { - return -1; - } - - memcpy(*dest + oldlen, src, srclen); - return 0; -} - -int dstrcat(char **dest, const char *src) { - return dstrcat_impl(dest, src, strlen(src)); -} - -int dstrncat(char **dest, const char *src, size_t n) { - return dstrcat_impl(dest, src, strnlen(src, n)); -} - -int dstrdcat(char **dest, const char *src) { - return dstrcat_impl(dest, src, dstrlen(src)); -} - -int dstrapp(char **str, char c) { - return dstrcat_impl(str, &c, 1); -} - -char *dstrprintf(const char *format, ...) { - va_list args; - - va_start(args, format); - char *str = dstrvprintf(format, args); - va_end(args); - - return str; -} - -char *dstrvprintf(const char *format, va_list args) { - // Guess a capacity to try to avoid reallocating - char *str = dstralloc(2*strlen(format)); - if (!str) { - return NULL; - } - - if (dstrvcatf(&str, format, args) != 0) { - dstrfree(str); - return NULL; - } - - return str; -} - -int dstrcatf(char **str, const char *format, ...) { - va_list args; - - va_start(args, format); - int ret = dstrvcatf(str, format, args); - va_end(args); - - return ret; -} - -int dstrvcatf(char **str, const char *format, va_list args) { - // Guess a capacity to try to avoid calling vsnprintf() twice - size_t len = dstrlen(*str); - dstreserve(str, len + 2*strlen(format)); - size_t cap = dstrheader(*str)->capacity; - - va_list copy; - va_copy(copy, args); - - char *tail = *str + len; - int ret = vsnprintf(tail, cap - len + 1, format, args); - if (ret < 0) { - goto fail; - } - - size_t tail_len = ret; - if (tail_len > cap - len) { - cap = len + tail_len; - if (dstreserve(str, cap) != 0) { - goto fail; - } - - tail = *str + len; - ret = vsnprintf(tail, tail_len + 1, format, copy); - if (ret < 0 || (size_t)ret != tail_len) { - assert(!"Length of formatted string changed"); - goto fail; - } - } - - va_end(copy); - - struct dstring *header = dstrheader(*str); - header->length += tail_len; - return 0; - -fail: - *tail = '\0'; - return -1; -} - -void dstrfree(char *dstr) { - if (dstr) { - free(dstrheader(dstr)); - } -} |