1#include "intscan.h"
2#include "shgetc.h"
3#include "stdio_impl.h"
4#include <inttypes.h>
5#include <limits.h>
6#include <wchar.h>
7#include <wctype.h>
8
9/* This read function heavily cheats. It knows:
10 *  (1) len will always be 1
11 *  (2) non-ascii characters don't matter */
12
13static size_t do_read(FILE* f, unsigned char* buf, size_t len) {
14    size_t i;
15    const wchar_t* wcs = f->cookie;
16
17    if (!wcs[0])
18        wcs = L"@";
19    for (i = 0; i < f->buf_size && wcs[i]; i++)
20        f->buf[i] = wcs[i] < 128 ? wcs[i] : '@';
21    f->rpos = f->buf;
22    f->rend = f->buf + i;
23    f->cookie = (void*)(wcs + i);
24
25    if (i && len) {
26        *buf = *f->rpos++;
27        return 1;
28    }
29    return 0;
30}
31
32static unsigned long long wcstox(const wchar_t* s, wchar_t** p, int base, unsigned long long lim) {
33    wchar_t* t = (wchar_t*)s;
34    unsigned char buf[64];
35    FILE f = {};
36    f.flags = 0;
37    f.rpos = f.rend = 0;
38    f.buf = buf + 4;
39    f.buf_size = sizeof buf - 4;
40    f.lock = -1;
41    f.read = do_read;
42    while (iswspace(*t))
43        t++;
44    f.cookie = (void*)t;
45    shlim(&f, 0);
46    unsigned long long y = __intscan(&f, base, 1, lim);
47    if (p) {
48        size_t cnt = shcnt(&f);
49        *p = cnt ? t + cnt : (wchar_t*)s;
50    }
51    return y;
52}
53
54unsigned long long wcstoull(const wchar_t* restrict s, wchar_t** restrict p, int base) {
55    return wcstox(s, p, base, ULLONG_MAX);
56}
57
58long long wcstoll(const wchar_t* restrict s, wchar_t** restrict p, int base) {
59    return wcstox(s, p, base, LLONG_MIN);
60}
61
62unsigned long wcstoul(const wchar_t* restrict s, wchar_t** restrict p, int base) {
63    return wcstox(s, p, base, ULONG_MAX);
64}
65
66long wcstol(const wchar_t* restrict s, wchar_t** restrict p, int base) {
67    return wcstox(s, p, base, 0UL + LONG_MIN);
68}
69
70intmax_t wcstoimax(const wchar_t* restrict s, wchar_t** restrict p, int base) {
71    return wcstoll(s, p, base);
72}
73
74uintmax_t wcstoumax(const wchar_t* restrict s, wchar_t** restrict p, int base) {
75    return wcstoull(s, p, base);
76}
77