X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/db2bf4111cde36048ac66bbac58547d105bc7e80..67b5031ec6d160b5cae425466a34d1be3b211dd4:/utils/gprintf.c?ds=sidebyside diff --git a/utils/gprintf.c b/utils/gprintf.c index f527186..b575e1f 100644 --- a/utils/gprintf.c +++ b/utils/gprintf.c @@ -563,6 +563,54 @@ int gprintf(const struct gprintf_ops *ops, void *out, const char *p, ...) return (n); } +/*----- Utilities ---------------------------------------------------------*/ + +/* --- @gprintf_memputf@ --- * + * + * Arguments: @char **buf_inout@ = address of output buffer pointer + * @size_t *sz_inout@ = address of buffer size + * @size_t maxsz@ = buffer size needed for this operation + * @const char *p@ = pointer to format string + * @va_list *ap@ = captured format-arguments tail + * + * Returns: The formatted length. + * + * Use: Generic utility for mostly implementing the @nputf@ output + * function, if you don't have a better option. + * + * On entry, @*buf_inout@ should be null or a buffer pointer, + * with @*sz_inout@ either zero or the buffer's size, + * respectively. On exit, @*buf_input@ and @*sz_inout@ will be + * updated, if necessary, to describe a sufficiently large + * buffer, and the formatted string will have been written to + * the buffer. + * + * When the buffer is no longer required, free it using @xfree@. + */ + +size_t gprintf_memputf(char **buf_inout, size_t *sz_inout, + size_t maxsz, const char *p, va_list ap) +{ + char *buf = *buf_inout; + size_t sz = *sz_inout; + int n; + + if (sz <= maxsz) { + if (!sz) sz = 32; + while (sz <= maxsz) sz *= 2; + if (buf) xfree(buf); + buf = xmalloc(sz); *buf_inout = buf; *sz_inout = sz; + } + +#ifdef HAVE_SNPRINTF + n = vsnprintf(buf, maxsz + 1, p, ap); +#else + n = vsprintf(buf, p, ap); +#endif + assert(0 <= n && n <= maxsz); + return (n); +} + /*----- Standard printers -------------------------------------------------*/ static int file_putch(void *out, int ch)