diff options
Diffstat (limited to 'libntp/xsbprintf.c')
-rw-r--r-- | libntp/xsbprintf.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/libntp/xsbprintf.c b/libntp/xsbprintf.c new file mode 100644 index 0000000000000..4586758bc88aa --- /dev/null +++ b/libntp/xsbprintf.c @@ -0,0 +1,75 @@ +/* + * xsbprintf.c - string buffer formatting helpers + * + * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. + * The contents of 'html/copyright.html' apply. + */ + +#include <config.h> +#include <sys/types.h> + +#include "ntp_stdlib.h" + +/* eXtended Varlist String Buffer printf + * + * Formats via 'vsnprintf' into a string buffer, with some semantic + * specialties: + * + * - The start of the buffer pointer is updated according to the number + * of characters written. + * - If the buffer is insufficient to format the number of charactes, + * the partial result will be be discarded, and zero is returned to + * indicate nothing was written to the buffer. + * - On successful formatting, the return code is the return value of + * the inner call to 'vsnprintf()'. + * - If there is any error, the state of the buffer will not be + * changed. (Bytes in the buffer might be smashed, but the buffer + * position does not change, and the NUL marker stays in place at the + * current buffer position.) + * - If '(*ppbuf - pend) <= 0' (or ppbuf is NULL), fail with EINVAL. + */ +int +xvsbprintf( + char **ppbuf, /* pointer to buffer pointer (I/O) */ + char * const pend, /* buffer end (I) */ + char const *pfmt, /* printf-like format string */ + va_list va /* formatting args for above */ + ) +{ + char *pbuf = (ppbuf) ? *ppbuf : NULL; + int rc = -1; + if (pbuf && (pend - pbuf > 0)) { + size_t blen = (size_t)(pend - pbuf); + rc = vsnprintf(pbuf, blen, pfmt, va); + if (rc > 0) { + if ((size_t)rc >= blen) + rc = 0; + pbuf += rc; + } + *pbuf = '\0'; /* fear of bad vsnprintf */ + *ppbuf = pbuf; + } else { + errno = EINVAL; + } + return rc; +} + +/* variadic wrapper around the buffer string formatter */ +int +xsbprintf( + char **ppbuf, /* pointer to buffer pointer (I/O) */ + char * const pend, /* buffer end (I) */ + char const *pfmt, /* printf-like format string */ + ... /* formatting args for above */ + ) +{ + va_list va; + int rc; + + va_start(va, pfmt); + rc = xvsbprintf(ppbuf, pend, pfmt, va); + va_end(va); + return rc; +} + +/* that's all folks! */ |