From 345fd739496034fcfccf8fb943765a4e3beaedc4 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 1 Oct 2020 10:59:53 -0400 Subject: dstring: Try to avoid calling vsnprintf() twice in dstrprintf() --- dstring.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'dstring.c') diff --git a/dstring.c b/dstring.c index 8b226bc..d370598 100644 --- a/dstring.c +++ b/dstring.c @@ -129,28 +129,44 @@ int dstrapp(char **str, char c) { } char *dstrprintf(const char *format, ...) { + // Guess a length to try to avoid calling vsnprintf() twice + int len, cap = 2*strlen(format); + char *str = dstralloc(cap); + if (!str) { + return NULL; + } + va_list args; va_start(args, format); - int len = vsnprintf(NULL, 0, format, args); + len = vsnprintf(str, cap + 1, format, args); va_end(args); - assert(len > 0); + if (len > cap) { + if (dstreserve(&str, len) != 0) { + goto fail; + } - char *str = dstralloc(len); - if (!str) { - return NULL; + cap = len; + + va_start(args, format); + len = vsnprintf(str, cap + 1, format, args); + va_end(args); + + assert(len == cap); } - va_start(args, format); - len = vsnprintf(str, len + 1, format, args); - va_end(args); + if (len < 0) { + goto fail; + } struct dstring *header = dstrheader(str); - assert(len == header->capacity); header->length = len; - return str; + +fail: + dstrfree(str); + return NULL; } void dstrfree(char *dstr) { -- cgit v1.2.3