diff options
Diffstat (limited to 'system/lib/libc/musl/src/stdio/vsnprintf.c')
-rw-r--r-- | system/lib/libc/musl/src/stdio/vsnprintf.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/system/lib/libc/musl/src/stdio/vsnprintf.c b/system/lib/libc/musl/src/stdio/vsnprintf.c new file mode 100644 index 00000000..9dcc84af --- /dev/null +++ b/system/lib/libc/musl/src/stdio/vsnprintf.c @@ -0,0 +1,45 @@ +#include "stdio_impl.h" +#include <limits.h> +#include <string.h> +#include <errno.h> +#include <stdint.h> + +static size_t sn_write(FILE *f, const unsigned char *s, size_t l) +{ + size_t k = f->wend - f->wpos; + if (k > l) k = l; + memcpy(f->wpos, s, k); + f->wpos += k; + /* pretend to succeed, but discard extra data */ + return l; +} + +// XXX Emscripten Call to musl-specific vfprintf for better asm.js performance, instead of the handwritten js function. +#define vfprintf MUSL_vfprintf + +int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap) +{ + int r; + char b; + FILE f = { .lbf = EOF, .write = sn_write, .lock = -1 }; + + if (n-1 > INT_MAX-1) { + if (n) { + errno = EOVERFLOW; + return -1; + } + s = &b; + n = 1; + } + + /* Ensure pointers don't wrap if "infinite" n is passed in */ + if (n > (char *)0+SIZE_MAX-s-1) n = (char *)0+SIZE_MAX-s-1; + f.buf_size = n; + f.buf = f.wpos = (void *)s; + f.wbase = f.wend = (void *)(s+n); + r = vfprintf(&f, fmt, ap); + + /* Null-terminate, overwriting last char if dest buffer is full */ + if (n) f.wpos[-(f.wpos == f.wend)] = 0; + return r; +} |