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