1#include "stdio_impl.h"
2#include <errno.h>
3#include <limits.h>
4#include <stdint.h>
5#include <string.h>
6#include <wchar.h>
7
8struct cookie {
9    wchar_t* ws;
10    size_t l;
11};
12
13static size_t sw_write(FILE* f, const unsigned char* s, size_t l) {
14    size_t l0 = l;
15    int i = 0;
16    struct cookie* c = f->cookie;
17    if (s != f->wbase && sw_write(f, f->wbase, f->wpos - f->wbase) == -1)
18        return -1;
19    while (c->l && l && (i = mbtowc(c->ws, (void*)s, l)) >= 0) {
20        s += i;
21        l -= i;
22        c->l--;
23        c->ws++;
24    }
25    *c->ws = 0;
26    return i < 0 ? i : l0;
27}
28
29int vswprintf(wchar_t* restrict s, size_t n, const wchar_t* restrict fmt, va_list ap) {
30    int r;
31    FILE f;
32    unsigned char buf[256];
33    struct cookie c = {s, n - 1};
34
35    memset(&f, 0, sizeof(FILE));
36    f.lbf = EOF;
37    f.write = sw_write;
38    f.buf_size = sizeof buf;
39    f.buf = buf;
40    f.lock = -1;
41    f.cookie = &c;
42    if (!n) {
43        return -1;
44    } else if (n > INT_MAX) {
45        errno = EOVERFLOW;
46        return -1;
47    }
48    r = vfwprintf(&f, fmt, ap);
49    sw_write(&f, 0, 0);
50    return r >= n ? -1 : r;
51}
52