1570af302Sopenharmony_ci#include "stdio_impl.h"
2570af302Sopenharmony_ci#include <limits.h>
3570af302Sopenharmony_ci#include <string.h>
4570af302Sopenharmony_ci#include <errno.h>
5570af302Sopenharmony_ci#include <stdint.h>
6570af302Sopenharmony_ci
7570af302Sopenharmony_cistruct cookie {
8570af302Sopenharmony_ci	char *s;
9570af302Sopenharmony_ci	size_t n;
10570af302Sopenharmony_ci};
11570af302Sopenharmony_ci
12570af302Sopenharmony_ci#define MIN(a, b) ((a) < (b) ? (a) : (b))
13570af302Sopenharmony_ci
14570af302Sopenharmony_cistatic size_t sn_write(FILE *f, const unsigned char *s, size_t l)
15570af302Sopenharmony_ci{
16570af302Sopenharmony_ci	struct cookie *c = f->cookie;
17570af302Sopenharmony_ci	size_t already_size = f->wpos - f->wbase;
18570af302Sopenharmony_ci	if (already_size <= c->n) {
19570af302Sopenharmony_ci		size_t k = MIN(l, c->n - already_size);
20570af302Sopenharmony_ci		memcpy(f->wpos, s, k);
21570af302Sopenharmony_ci		f->wpos += k;
22570af302Sopenharmony_ci	}
23570af302Sopenharmony_ci	/* pretend to succeed, even if we discarded extra data */
24570af302Sopenharmony_ci	return l;
25570af302Sopenharmony_ci}
26570af302Sopenharmony_ci
27570af302Sopenharmony_ciint vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap)
28570af302Sopenharmony_ci{
29570af302Sopenharmony_ci	unsigned char dummy[1];
30570af302Sopenharmony_ci	struct cookie c = { .s = n ? s : dummy, .n = n ? n-1 : 0 };
31570af302Sopenharmony_ci	FILE f = {
32570af302Sopenharmony_ci		.lbf = EOF,
33570af302Sopenharmony_ci		.lock = -1,
34570af302Sopenharmony_ci		.buf = (unsigned char *)(n ? s: dummy),
35570af302Sopenharmony_ci		.buf_size = n ? n - 1 : 0,
36570af302Sopenharmony_ci		.flags = F_PBUF,
37570af302Sopenharmony_ci		.cookie = &c,
38570af302Sopenharmony_ci		.write = sn_write,
39570af302Sopenharmony_ci	};
40570af302Sopenharmony_ci
41570af302Sopenharmony_ci	return vfprintf(&f, fmt, ap);
42570af302Sopenharmony_ci}
43