From ed05695316105ec19906272e73214bfe3fbdc37f Mon Sep 17 00:00:00 2001 From: Matthew Fernandez Date: Mon, 31 Aug 2020 17:34:09 -0700 Subject: [PATCH] implement a printf-like interface to agxbuf --- lib/cgraph/agxbuf.c | 44 +++++++++++++++++++++++++++++++++++++++++++- lib/cgraph/agxbuf.h | 15 +++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/lib/cgraph/agxbuf.c b/lib/cgraph/agxbuf.c index 3f2c809a6..92a9927ca 100644 --- a/lib/cgraph/agxbuf.c +++ b/lib/cgraph/agxbuf.c @@ -11,7 +11,8 @@ * Contributors: See CVS logs. Details at http://www.graphviz.org/ *************************************************************************/ - +#include +#include #include #include #include @@ -66,6 +67,47 @@ int agxbmore(agxbuf * xb, size_t ssz) return 0; } +int agxbprint(agxbuf * xb, const char *fmt, ...) { + va_list ap; + size_t size; + int result; + + va_start(ap, fmt); + + /* determine how many bytes we need to print */ + { + va_list ap2; + int rc; + va_copy(ap2, ap); + rc = vsnprintf(NULL, 0, fmt, ap2); + va_end(ap2); + if (rc < 0) { + va_end(ap); + return rc; + } + size = (size_t)rc + 1; /* account for NUL terminator */ + } + + /* do we need to expand the buffer? */ + { + size_t unused_space = (size_t)(xb->eptr - xb->ptr); + if (unused_space < size) { + size_t extra = size - unused_space; + (void)agxbmore(xb, extra); + } + } + + /* we can now safely print into the buffer */ + result = vsnprintf((char*)xb->ptr, size, fmt, ap); + assert(result == (int)(size - 1) || result < 0); + if (result > 0) { + xb->ptr += (size_t)result; + } + + va_end(ap); + return result; +} + /* agxbput_n: * Append string s of length n onto xb */ diff --git a/lib/cgraph/agxbuf.h b/lib/cgraph/agxbuf.h index deb2e8e9f..eeb12235b 100644 --- a/lib/cgraph/agxbuf.h +++ b/lib/cgraph/agxbuf.h @@ -47,6 +47,21 @@ extern "C" { AGXBUF_API void agxbinit(agxbuf * xb, unsigned int hint, unsigned char *init); +/* support for extra API misuse warnings if available */ +#ifdef __GNUC__ + #define PRINTF_LIKE(index, first) __attribute__((format(printf, index, first))) +#else + #define PRINTF_LIKE(index, first) /* nothing */ +#endif + +/* agxbprint: + * Printf-style output to an agxbuf + */ + AGXBUF_API int agxbprint(agxbuf * xb, const char *fmt, ...) + PRINTF_LIKE(2, 3); + +#undef PRINTF_LIKE + /* agxbput_n: * Append string s of length n into xb */ -- 2.40.0