56 lines
973 B
C
56 lines
973 B
C
#include "stdio_impl.h"
|
|
#include <limits.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <stdint.h>
|
|
|
|
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)
|
|
{
|
|
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 *restrict s, size_t n, const char *restrict fmt, va_list ap)
|
|
{
|
|
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,
|
|
};
|
|
|
|
if (n > INT_MAX) {
|
|
errno = EOVERFLOW;
|
|
return -1;
|
|
}
|
|
|
|
*c.s = 0;
|
|
return vfprintf(&f, fmt, ap);
|
|
}
|