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