1#ifdef __wasilibc_unmodified_upstream // Changes to optimize printf/scanf when long double isn't needed
 2#else
 3#include "printscan.h"
 4#endif
 5#include "shgetc.h"
 6#include "floatscan.h"
 7#include "stdio_impl.h"
 8#include <wchar.h>
 9#include <wctype.h>
10
11/* This read function heavily cheats. It knows:
12 *  (1) len will always be 1
13 *  (2) non-ascii characters don't matter */
14
15static size_t do_read(FILE *f, unsigned char *buf, size_t len)
16{
17	size_t i;
18	const wchar_t *wcs = f->cookie;
19
20	if (!wcs[0]) wcs=L"@";
21	for (i=0; i<f->buf_size && wcs[i]; i++)
22		f->buf[i] = wcs[i] < 128 ? wcs[i] : '@';
23	f->rpos = f->buf;
24	f->rend = f->buf + i;
25	f->cookie = (void *)(wcs+i);
26
27	if (i && len) {
28		*buf = *f->rpos++;
29		return 1;
30	}
31	return 0;
32}
33
34#if defined(__wasilibc_printscan_no_long_double)
35static long_double wcstox(const wchar_t *s, wchar_t **p, int prec)
36#else
37static long double wcstox(const wchar_t *s, wchar_t **p, int prec)
38#endif
39{
40	wchar_t *t = (wchar_t *)s;
41	unsigned char buf[64];
42	FILE f = {0};
43	f.flags = 0;
44	f.rpos = f.rend = f.buf = buf + 4;
45	f.buf_size = sizeof buf - 4;
46#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
47	f.lock = -1;
48#endif
49	f.read = do_read;
50	while (iswspace(*t)) t++;
51	f.cookie = (void *)t;
52	shlim(&f, 0);
53#if defined(__wasilibc_printscan_no_long_double)
54	long_double y = __floatscan(&f, prec, 1);
55#else
56	long double y = __floatscan(&f, prec, 1);
57#endif
58	if (p) {
59		size_t cnt = shcnt(&f);
60		*p = cnt ? t + cnt : (wchar_t *)s;
61	}
62	return y;
63}
64
65float wcstof(const wchar_t *restrict s, wchar_t **restrict p)
66{
67	return wcstox(s, p, 0);
68}
69
70double wcstod(const wchar_t *restrict s, wchar_t **restrict p)
71{
72	return wcstox(s, p, 1);
73}
74
75long double wcstold(const wchar_t *restrict s, wchar_t **restrict p)
76{
77#if defined(__wasilibc_printscan_no_long_double)
78	long_double_not_supported();
79#else
80	return wcstox(s, p, 2);
81#endif
82}