diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2020-10-01 10:59:53 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2020-10-01 10:59:53 -0400 |
commit | 345fd739496034fcfccf8fb943765a4e3beaedc4 (patch) | |
tree | 45a9f6c0129b537809fc988a641626dfb342b05c | |
parent | 958d591c888a4b9ab457ae414ef120dae77ee589 (diff) | |
download | bfs-345fd739496034fcfccf8fb943765a4e3beaedc4.tar.xz |
dstring: Try to avoid calling vsnprintf() twice in dstrprintf()
-rw-r--r-- | dstring.c | 36 |
1 files changed, 26 insertions, 10 deletions
@@ -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) { |