Index: fusl/src/stdlib/wcstod.c |
diff --git a/fusl/src/stdlib/wcstod.c b/fusl/src/stdlib/wcstod.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..26fe9af8b4cc7d7c5f69fbab349d1bb1735f18f8 |
--- /dev/null |
+++ b/fusl/src/stdlib/wcstod.c |
@@ -0,0 +1,65 @@ |
+#include "shgetc.h" |
+#include "floatscan.h" |
+#include "stdio_impl.h" |
+#include <wchar.h> |
+#include <wctype.h> |
+ |
+/* This read function heavily cheats. It knows: |
+ * (1) len will always be 1 |
+ * (2) non-ascii characters don't matter */ |
+ |
+static size_t do_read(FILE *f, unsigned char *buf, size_t len) |
+{ |
+ size_t i; |
+ const wchar_t *wcs = f->cookie; |
+ |
+ if (!wcs[0]) wcs=L"@"; |
+ for (i=0; i<f->buf_size && wcs[i]; i++) |
+ f->buf[i] = wcs[i] < 128 ? wcs[i] : '@'; |
+ f->rpos = f->buf; |
+ f->rend = f->buf + i; |
+ f->cookie = (void *)(wcs+i); |
+ |
+ if (i && len) { |
+ *buf = *f->rpos++; |
+ return 1; |
+ } |
+ return 0; |
+} |
+ |
+static long double wcstox(const wchar_t *s, wchar_t **p, int prec) |
+{ |
+ wchar_t *t = (wchar_t *)s; |
+ unsigned char buf[64]; |
+ FILE f = {0}; |
+ f.flags = 0; |
+ f.rpos = f.rend = 0; |
+ f.buf = buf + 4; |
+ f.buf_size = sizeof buf - 4; |
+ f.lock = -1; |
+ f.read = do_read; |
+ while (iswspace(*t)) t++; |
+ f.cookie = (void *)t; |
+ shlim(&f, 0); |
+ long double y = __floatscan(&f, prec, 1); |
+ if (p) { |
+ size_t cnt = shcnt(&f); |
+ *p = cnt ? t + cnt : (wchar_t *)s; |
+ } |
+ return y; |
+} |
+ |
+float wcstof(const wchar_t *restrict s, wchar_t **restrict p) |
+{ |
+ return wcstox(s, p, 0); |
+} |
+ |
+double wcstod(const wchar_t *restrict s, wchar_t **restrict p) |
+{ |
+ return wcstox(s, p, 1); |
+} |
+ |
+long double wcstold(const wchar_t *restrict s, wchar_t **restrict p) |
+{ |
+ return wcstox(s, p, 2); |
+} |