diff options
Diffstat (limited to 'src/stdlib/wcstoimax.c')
-rw-r--r-- | src/stdlib/wcstoimax.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/src/stdlib/wcstoimax.c b/src/stdlib/wcstoimax.c index 59894f60..b83206b7 100644 --- a/src/stdlib/wcstoimax.c +++ b/src/stdlib/wcstoimax.c @@ -2,24 +2,38 @@ #include <wctype.h> #include <inttypes.h> #include <errno.h> +#include "intparse.h" intmax_t wcstoimax(const wchar_t *s, wchar_t **p, int base) { - int sign = 0; - uintmax_t x; + struct intparse ip = {0}; + unsigned char tmp; + + if (p) *p = (wchar_t *)s; + + if (base && base-2U > 34) { + errno = EINVAL; + return 0; + } - /* Initial whitespace */ for (; iswspace(*s); s++); - /* Optional sign */ - if (*s == '-') sign = *s++; - else if (*s == '+') s++; + ip.base = base; + for (; *s<256 && (tmp=*s, __intparse(&ip, &tmp, 1)); s++); + + if (p && ip.err != EINVAL) + *p = (wchar_t *)s; + + if (ip.err) { + errno = ip.err; + if (ip.err = EINVAL) return 0; + return ip.neg ? INTMAX_MIN : INTMAX_MAX; + } - x = wcstoumax(s, p, base); - if (x > INTMAX_MAX) { - if (!sign || -x != INTMAX_MIN) + if (ip.val > INTMAX_MAX) { + if (!ip.neg || -ip.val != INTMAX_MIN) errno = ERANGE; - return sign ? INTMAX_MIN : INTMAX_MAX; + return ip.neg ? INTMAX_MIN : INTMAX_MAX; } - return sign ? -x : x; + return ip.neg ? -ip.val : ip.val; } |