xref: /netbsd/external/bsd/ntp/dist/libntp/xsbprintf.c (revision 9034ec65)
1 /*	$NetBSD: xsbprintf.c,v 1.2 2020/05/25 20:47:25 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
xvsbprintf(char ** ppbuf,char * const pend,char const * pfmt,va_list va)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
xsbprintf(char ** ppbuf,char * const pend,char const * pfmt,...)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