X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fstdio%2Fvsnprintf.c;h=b3510a63408abe2d4d08e630aa1ddf5b7ba1480a;hb=9b132e556774c744f9052581d2d8d0fab417e97c;hp=ff792e1717223c0dd51f2d46433961a5aa6677f1;hpb=5eb0d33ec0f08b123c5c10877d6258d05fa9453a;p=musl diff --git a/src/stdio/vsnprintf.c b/src/stdio/vsnprintf.c index ff792e17..b3510a63 100644 --- a/src/stdio/vsnprintf.c +++ b/src/stdio/vsnprintf.c @@ -1,34 +1,55 @@ #include "stdio_impl.h" +#include +#include +#include +#include + +struct cookie { + char *s; + size_t n; +}; + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) static size_t sn_write(FILE *f, const unsigned char *s, size_t l) { - /* pretend to succeed, but discard data */ + struct cookie *c = f->cookie; + size_t k = MIN(c->n, f->wpos - f->wbase); + if (k) { + memcpy(c->s, f->wbase, k); + c->s += k; + c->n -= k; + } + k = MIN(c->n, l); + if (k) { + memcpy(c->s, s, k); + c->s += k; + c->n -= k; + } + *c->s = 0; + f->wpos = f->wbase = f->buf; + /* pretend to succeed, even if we discarded extra data */ return l; } -int vsnprintf(char *s, size_t n, const char *fmt, va_list ap) +int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap) { - int r; - FILE f; unsigned char buf[1]; + char dummy[1]; + struct cookie c = { .s = n ? s : dummy, .n = n ? n-1 : 0 }; + FILE f = { + .lbf = EOF, + .write = sn_write, + .lock = -1, + .buf = buf, + .cookie = &c, + }; - memset(&f, 0, sizeof(FILE)); - f.lbf = EOF; - f.write = sn_write; - f.buf_size = 1; - f.buf = buf; - f.owner = -1; if (n > INT_MAX) { errno = EOVERFLOW; return -1; - } else if (n > 0) { - if (n > (char *)0+SIZE_MAX-s) n = (char *)0+SIZE_MAX-s; - f.wpos = s; - f.wbase = f.wend = s+n-1; - f.wstop = f.wend - 1; } - r = vfprintf(&f, fmt, ap); - /* wpos points just after last byte written, or to s+n-1 (wbase) */ - *f.wpos = 0; - return r; + + *c.s = 0; + return vfprintf(&f, fmt, ap); }