1 /* $NetBSD: xsbprintf.c,v 1.3 2024/08/18 20:47:13 christos Exp $ */ 2 3 /* 4 * xsbprintf.c - string buffer formatting helpers 5 * 6 * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. 7 * The contents of 'html/copyright.html' apply. 8 */ 9 10 #include <config.h> 11 #include <sys/types.h> 12 13 #include "ntp_stdlib.h" 14 15 /* eXtended Varlist String Buffer printf 16 * 17 * Formats via 'vsnprintf' into a string buffer, with some semantic 18 * specialties: 19 * 20 * - The start of the buffer pointer is updated according to the number 21 * of characters written. 22 * - If the buffer is insufficient to format the number of charactes, 23 * the partial result will be be discarded, and zero is returned to 24 * indicate nothing was written to the buffer. 25 * - On successful formatting, the return code is the return value of 26 * the inner call to 'vsnprintf()'. 27 * - If there is any error, the state of the buffer will not be 28 * changed. (Bytes in the buffer might be smashed, but the buffer 29 * position does not change, and the NUL marker stays in place at the 30 * current buffer position.) 31 * - If '(*ppbuf - pend) <= 0' (or ppbuf is NULL), fail with EINVAL. 32 */ 33 int 34 xvsbprintf( 35 char **ppbuf, /* pointer to buffer pointer (I/O) */ 36 char * const pend, /* buffer end (I) */ 37 char const *pfmt, /* printf-like format string */ 38 va_list va /* formatting args for above */ 39 ) 40 { 41 char *pbuf = (ppbuf) ? *ppbuf : NULL; 42 int rc = -1; 43 if (pbuf && (pend - pbuf > 0)) { 44 size_t blen = (size_t)(pend - pbuf); 45 rc = vsnprintf(pbuf, blen, pfmt, va); 46 if (rc > 0) { 47 if ((size_t)rc >= blen) 48 rc = 0; 49 pbuf += rc; 50 } 51 *pbuf = '\0'; /* fear of bad vsnprintf */ 52 *ppbuf = pbuf; 53 } else { 54 errno = EINVAL; 55 } 56 return rc; 57 } 58 59 /* variadic wrapper around the buffer string formatter */ 60 int 61 xsbprintf( 62 char **ppbuf, /* pointer to buffer pointer (I/O) */ 63 char * const pend, /* buffer end (I) */ 64 char const *pfmt, /* printf-like format string */ 65 ... /* formatting args for above */ 66 ) 67 { 68 va_list va; 69 int rc; 70 71 va_start(va, pfmt); 72 rc = xvsbprintf(ppbuf, pend, pfmt, va); 73 va_end(va); 74 return rc; 75 } 76 77 /* that's all folks! */ 78