| /* | 
 |  * Copyright (c) 2020 Nordic Semiconductor ASA | 
 |  * | 
 |  * SPDX-License-Identifier: Apache-2.0 | 
 |  */ | 
 |  | 
 | #include <stdarg.h> | 
 | #include <stddef.h> | 
 | #include <zephyr/sys/cbprintf.h> | 
 |  | 
 | int cbprintf(cbprintf_cb out, void *ctx, const char *format, ...) | 
 | { | 
 | 	va_list ap; | 
 | 	int rc; | 
 |  | 
 | 	va_start(ap, format); | 
 | 	rc = cbvprintf(out, ctx, format, ap); | 
 | 	va_end(ap); | 
 |  | 
 | 	return rc; | 
 | } | 
 |  | 
 | #if defined(CONFIG_CBPRINTF_LIBC_SUBSTS) | 
 |  | 
 | #include <stdio.h> | 
 |  | 
 | /* Context for sn* variants is the next space in the buffer, and the buffer | 
 |  * end. | 
 |  */ | 
 | struct str_ctx { | 
 | 	char *dp; | 
 | 	char *const dpe; | 
 | }; | 
 |  | 
 | static int str_out(int c, | 
 | 		   void *ctx) | 
 | { | 
 | 	struct str_ctx *scp = ctx; | 
 |  | 
 | 	/* s*printf must return the number of characters that would be | 
 | 	 * output, even if they don't all fit, so conditionally store | 
 | 	 * and unconditionally succeed. | 
 | 	 */ | 
 | 	if (scp->dp < scp->dpe) { | 
 | 		*(scp->dp++) = c; | 
 | 	} | 
 |  | 
 | 	return c; | 
 | } | 
 |  | 
 | int fprintfcb(FILE *stream, const char *format, ...) | 
 | { | 
 | 	va_list ap; | 
 | 	int rc; | 
 |  | 
 | 	va_start(ap, format); | 
 | 	rc = vfprintfcb(stream, format, ap); | 
 | 	va_end(ap); | 
 |  | 
 | 	return rc; | 
 | } | 
 |  | 
 | int vfprintfcb(FILE *stream, const char *format, va_list ap) | 
 | { | 
 | 	return cbvprintf(fputc, stream, format, ap); | 
 | } | 
 |  | 
 | int printfcb(const char *format, ...) | 
 | { | 
 | 	va_list ap; | 
 | 	int rc; | 
 |  | 
 | 	va_start(ap, format); | 
 | 	rc = vprintfcb(format, ap); | 
 | 	va_end(ap); | 
 |  | 
 | 	return rc; | 
 | } | 
 |  | 
 | int vprintfcb(const char *format, va_list ap) | 
 | { | 
 | 	return cbvprintf(fputc, stdout, format, ap); | 
 | } | 
 |  | 
 | int snprintfcb(char *str, size_t size, const char *format, ...) | 
 | { | 
 | 	va_list ap; | 
 | 	int rc; | 
 |  | 
 | 	va_start(ap, format); | 
 | 	rc = vsnprintfcb(str, size, format, ap); | 
 | 	va_end(ap); | 
 |  | 
 | 	return rc; | 
 | } | 
 |  | 
 | int vsnprintfcb(char *str, size_t size, const char *format, va_list ap) | 
 | { | 
 | 	struct str_ctx ctx = { | 
 | 		.dp = str, | 
 | 		.dpe = str + size, | 
 | 	}; | 
 | 	int rv = cbvprintf(str_out, &ctx, format, ap); | 
 |  | 
 | 	if (ctx.dp < ctx.dpe) { | 
 | 		ctx.dp[0] = 0; | 
 | 	} else { | 
 | 		ctx.dp[-1] = 0; | 
 | 	} | 
 |  | 
 | 	return rv; | 
 | } | 
 |  | 
 | #endif /* CONFIG_CBPRINTF_LIBC_SUBSTS */ |