diff options
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/mem.h | 4 | ||||
-rw-r--r-- | src/shared/printf.c | 31 |
2 files changed, 34 insertions, 1 deletions
diff --git a/src/shared/mem.h b/src/shared/mem.h index 8c83f2f..aac87f5 100644 --- a/src/shared/mem.h +++ b/src/shared/mem.h @@ -1,4 +1,5 @@ #pragma once +#include <stdarg.h> #include <stddef.h> /* note: (partially) tested in the userland tests */ @@ -11,3 +12,6 @@ void *memset(void *s, int c, size_t n); int strcmp(const char *s1, const char *s2); size_t strlen(const char *s); + +int snprintf(char *restrict str, size_t len, const char *restrict fmt, ...); +int vsnprintf(char *restrict str, size_t len, const char *restrict fmt, va_list ap); diff --git a/src/shared/printf.c b/src/shared/printf.c index c1206f3..2dc3048 100644 --- a/src/shared/printf.c +++ b/src/shared/printf.c @@ -1,6 +1,7 @@ -#include <stdbool.h> #include <shared/mem.h> #include <shared/printf.h> +#include <stdarg.h> +#include <stdbool.h> struct out_state { void (*back)(void *, const char *, size_t); @@ -165,3 +166,31 @@ int __printf_internal(const char *fmt, va_list argp, seg = fmt; } } + + +static void vsnprintf_backend(void *arg, const char *buf, size_t len) { + char **ptrs = arg; + size_t space = ptrs[1] - ptrs[0]; + if (len > space) len = space; + + memcpy(ptrs[0], buf, len); + ptrs[0] += len; + /* ptrs[1] is the last byte of the buffer, it must be 0. + * on overflow: + * ptrs[0] + (ptrs[1] - ptrs[0]) = ptrs[1] */ + *ptrs[0] = '\0'; +} + +int vsnprintf(char *restrict str, size_t len, const char *restrict fmt, va_list ap) { + char *ptrs[2] = {str, str + len - 1}; + return __printf_internal(fmt, ap, vsnprintf_backend, &ptrs); +} + +int snprintf(char *restrict str, size_t len, const char *restrict fmt, ...) { + int ret; + va_list argp; + va_start(argp, fmt); + ret = vsnprintf(str, len, fmt, argp); + va_end(argp); + return ret; +} |