/* * This software is licensed under the terms of the MIT License. * See COPYING for further information. * --- * Copyright (c) 2011-2024, Lukas Weber . * Copyright (c) 2012-2024, Andrei Alexeyev . */ #include "strbuf.h" #include "util/miscmath.h" #include int strbuf_printf(StringBuffer *strbuf, const char *format, ...) { va_list va; va_start(va, format); int r = strbuf_vprintf(strbuf, format, va); va_end(va); return r; } static size_t strbuf_size_available(StringBuffer *strbuf) { ptrdiff_t offset = strbuf->pos - strbuf->start; assume_nolog(offset >= 0); ptrdiff_t size_available = strbuf->buf_size - offset; assume_nolog(size_available >= 0); return size_available; } static size_t strbuf_reserve(StringBuffer *strbuf, size_t size_required) { size_t size_available = strbuf_size_available(strbuf); if(size_required >= size_available) { ptrdiff_t offset = strbuf->pos - strbuf->start; size_t new_size = topow2_u64(strbuf->buf_size + (size_required - size_available + 1)); strbuf->start = mem_realloc(strbuf->start, new_size); strbuf->pos = strbuf->start + offset; strbuf->buf_size = new_size; size_available = new_size - offset; } return size_available; } int strbuf_vprintf(StringBuffer *strbuf, const char *format, va_list args) { size_t size_available = strbuf_size_available(strbuf); va_list args_copy; va_copy(args_copy, args); int size_required = vsnprintf(strbuf->pos, size_available, format, args_copy); va_end(args_copy); if(size_required >= size_available) { size_available = strbuf_reserve(strbuf, size_required); va_copy(args_copy, args); size_required = vsnprintf(strbuf->pos, size_available, format, args_copy); va_end(args_copy); assume_nolog(size_required < size_available); } strbuf->pos += size_required; assume_nolog(*strbuf->pos == 0); return size_required; } int strbuf_ncat(StringBuffer *strbuf, size_t datasize, const char data[]) { if(UNLIKELY(!datasize)) { return 0; } assert(datasize < INT32_MAX); strbuf_reserve(strbuf, datasize + 1); assert_nolog(strbuf_size_available(strbuf) >= datasize + 1); memcpy(strbuf->pos, data, datasize); strbuf->pos += datasize; *strbuf->pos = 0; return datasize; } void strbuf_clear(StringBuffer *strbuf) { strbuf->pos = strbuf->start; if(strbuf->start) { *strbuf->pos = 0; } } void strbuf_free(StringBuffer *strbuf) { mem_free(strbuf->start); memset(strbuf, 0, sizeof(*strbuf)); }