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