From 6404f30139488ac1beda5d387f772c20f382d148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sat, 1 Jan 2011 12:43:37 +0100 Subject: [PATCH] Make htsbuf_vqprintf() work with arbitrary output lengths --- src/htsbuf.c | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/htsbuf.c b/src/htsbuf.c index afc88c71..9dc08e0b 100644 --- a/src/htsbuf.c +++ b/src/htsbuf.c @@ -241,13 +241,48 @@ htsbuf_drop(htsbuf_queue_t *hq, size_t len) } /** - * + * Inspired by vsnprintf man page */ void -htsbuf_vqprintf(htsbuf_queue_t *hq, const char *fmt, va_list ap) +htsbuf_vqprintf(htsbuf_queue_t *hq, const char *fmt, va_list ap0) { - char buf[5000]; - htsbuf_append(hq, buf, vsnprintf(buf, sizeof(buf), fmt, ap)); + // First try to format it on-stack + va_list ap; + int n, size; + char buf[100], *p, *np; + + va_copy(ap, ap0); + + n = vsnprintf(buf, sizeof(buf), fmt, ap); + if(n > -1 && n < sizeof(buf)) { + htsbuf_append(hq, buf, n); + return; + } + + // Else, do allocations + size = sizeof(buf) * 2; + + p = malloc(size); + while (1) { + /* Try to print in the allocated space. */ + va_copy(ap, ap0); + n = vsnprintf(p, size, fmt, ap); + if(n > -1 && n < size) { + htsbuf_append_prealloc(hq, p, n); + return; + } + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n+1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + if ((np = realloc (p, size)) == NULL) { + free(p); + abort(); + } else { + p = np; + } + } }