1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdarg.h>
8 #include <stddef.h>
9 #include <sys/cbprintf.h>
10 
cbprintf(cbprintf_cb out,void * ctx,const char * format,...)11 int cbprintf(cbprintf_cb out, void *ctx, const char *format, ...)
12 {
13 	va_list ap;
14 	int rc;
15 
16 	va_start(ap, format);
17 	rc = cbvprintf(out, ctx, format, ap);
18 	va_end(ap);
19 
20 	return rc;
21 }
22 
23 #if defined(CONFIG_CBPRINTF_LIBC_SUBSTS)
24 
25 #include <stdio.h>
26 
27 /* Context for sn* variants is the next space in the buffer, and the buffer
28  * end.
29  */
30 struct str_ctx {
31 	char *dp;
32 	char *const dpe;
33 };
34 
str_out(int c,void * ctx)35 static int str_out(int c,
36 		   void *ctx)
37 {
38 	struct str_ctx *scp = ctx;
39 
40 	/* s*printf must return the number of characters that would be
41 	 * output, even if they don't all fit, so conditionally store
42 	 * and unconditionally succeed.
43 	 */
44 	if (scp->dp < scp->dpe) {
45 		*(scp->dp++) = c;
46 	}
47 
48 	return c;
49 }
50 
fprintfcb(FILE * stream,const char * format,...)51 int fprintfcb(FILE *stream, const char *format, ...)
52 {
53 	va_list ap;
54 	int rc;
55 
56 	va_start(ap, format);
57 	rc = vfprintfcb(stream, format, ap);
58 	va_end(ap);
59 
60 	return rc;
61 }
62 
vfprintfcb(FILE * stream,const char * format,va_list ap)63 int vfprintfcb(FILE *stream, const char *format, va_list ap)
64 {
65 	return cbvprintf(fputc, stream, format, ap);
66 }
67 
printfcb(const char * format,...)68 int printfcb(const char *format, ...)
69 {
70 	va_list ap;
71 	int rc;
72 
73 	va_start(ap, format);
74 	rc = vprintfcb(format, ap);
75 	va_end(ap);
76 
77 	return rc;
78 }
79 
vprintfcb(const char * format,va_list ap)80 int vprintfcb(const char *format, va_list ap)
81 {
82 	return cbvprintf(fputc, stdout, format, ap);
83 }
84 
snprintfcb(char * str,size_t size,const char * format,...)85 int snprintfcb(char *str, size_t size, const char *format, ...)
86 {
87 	va_list ap;
88 	int rc;
89 
90 	va_start(ap, format);
91 	rc = vsnprintfcb(str, size, format, ap);
92 	va_end(ap);
93 
94 	return rc;
95 }
96 
vsnprintfcb(char * str,size_t size,const char * format,va_list ap)97 int vsnprintfcb(char *str, size_t size, const char *format, va_list ap)
98 {
99 	struct str_ctx ctx = {
100 		.dp = str,
101 		.dpe = str + size,
102 	};
103 	int rv = cbvprintf(str_out, &ctx, format, ap);
104 
105 	if (ctx.dp < ctx.dpe) {
106 		ctx.dp[0] = 0;
107 	} else {
108 		ctx.dp[-1] = 0;
109 	}
110 
111 	return rv;
112 }
113 
114 #endif /* CONFIG_CBPRINTF_LIBC_SUBSTS */
115