summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authordzwdz2022-08-06 00:12:51 +0200
committerdzwdz2022-08-06 00:12:51 +0200
commit03c6f3cf458c89df17b02557cd232f9cde73ed54 (patch)
treea89076307f32d9df6eec550f175accaa73d72408 /src/shared
parent641b857dcfe1cfca625fbd75646b743142a9069c (diff)
make snprintf shared; dynamic resolution support
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/mem.h4
-rw-r--r--src/shared/printf.c31
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;
+}