xref: /aosp_15_r20/external/musl/src/stdio/vsnprintf.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
1*c9945492SAndroid Build Coastguard Worker #include "stdio_impl.h"
2*c9945492SAndroid Build Coastguard Worker #include <limits.h>
3*c9945492SAndroid Build Coastguard Worker #include <string.h>
4*c9945492SAndroid Build Coastguard Worker #include <errno.h>
5*c9945492SAndroid Build Coastguard Worker #include <stdint.h>
6*c9945492SAndroid Build Coastguard Worker 
7*c9945492SAndroid Build Coastguard Worker struct cookie {
8*c9945492SAndroid Build Coastguard Worker 	char *s;
9*c9945492SAndroid Build Coastguard Worker 	size_t n;
10*c9945492SAndroid Build Coastguard Worker };
11*c9945492SAndroid Build Coastguard Worker 
12*c9945492SAndroid Build Coastguard Worker #define MIN(a, b) ((a) < (b) ? (a) : (b))
13*c9945492SAndroid Build Coastguard Worker 
sn_write(FILE * f,const unsigned char * s,size_t l)14*c9945492SAndroid Build Coastguard Worker static size_t sn_write(FILE *f, const unsigned char *s, size_t l)
15*c9945492SAndroid Build Coastguard Worker {
16*c9945492SAndroid Build Coastguard Worker 	struct cookie *c = f->cookie;
17*c9945492SAndroid Build Coastguard Worker 	size_t k = MIN(c->n, f->wpos - f->wbase);
18*c9945492SAndroid Build Coastguard Worker 	if (k) {
19*c9945492SAndroid Build Coastguard Worker 		memcpy(c->s, f->wbase, k);
20*c9945492SAndroid Build Coastguard Worker 		c->s += k;
21*c9945492SAndroid Build Coastguard Worker 		c->n -= k;
22*c9945492SAndroid Build Coastguard Worker 	}
23*c9945492SAndroid Build Coastguard Worker 	k = MIN(c->n, l);
24*c9945492SAndroid Build Coastguard Worker 	if (k) {
25*c9945492SAndroid Build Coastguard Worker 		memcpy(c->s, s, k);
26*c9945492SAndroid Build Coastguard Worker 		c->s += k;
27*c9945492SAndroid Build Coastguard Worker 		c->n -= k;
28*c9945492SAndroid Build Coastguard Worker 	}
29*c9945492SAndroid Build Coastguard Worker 	*c->s = 0;
30*c9945492SAndroid Build Coastguard Worker 	f->wpos = f->wbase = f->buf;
31*c9945492SAndroid Build Coastguard Worker 	/* pretend to succeed, even if we discarded extra data */
32*c9945492SAndroid Build Coastguard Worker 	return l;
33*c9945492SAndroid Build Coastguard Worker }
34*c9945492SAndroid Build Coastguard Worker 
vsnprintf(char * restrict s,size_t n,const char * restrict fmt,va_list ap)35*c9945492SAndroid Build Coastguard Worker int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap)
36*c9945492SAndroid Build Coastguard Worker {
37*c9945492SAndroid Build Coastguard Worker 	unsigned char buf[1];
38*c9945492SAndroid Build Coastguard Worker 	char dummy[1];
39*c9945492SAndroid Build Coastguard Worker 	struct cookie c = { .s = n ? s : dummy, .n = n ? n-1 : 0 };
40*c9945492SAndroid Build Coastguard Worker 	FILE f = {
41*c9945492SAndroid Build Coastguard Worker 		.lbf = EOF,
42*c9945492SAndroid Build Coastguard Worker 		.write = sn_write,
43*c9945492SAndroid Build Coastguard Worker 		.lock = -1,
44*c9945492SAndroid Build Coastguard Worker 		.buf = buf,
45*c9945492SAndroid Build Coastguard Worker 		.cookie = &c,
46*c9945492SAndroid Build Coastguard Worker 	};
47*c9945492SAndroid Build Coastguard Worker 
48*c9945492SAndroid Build Coastguard Worker 	*c.s = 0;
49*c9945492SAndroid Build Coastguard Worker 	return vfprintf(&f, fmt, ap);
50*c9945492SAndroid Build Coastguard Worker }
51