diff options
author | Rich Felker <dalias@aerifal.cx> | 2011-07-14 00:51:45 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2011-07-14 00:51:45 -0400 |
commit | ecc9c5fcfa4831b290cc1a63c0346cbb0c1fcf42 (patch) | |
tree | 2fb20d623af9622cb8ac9f461e542ca23fc6d791 /src/stdlib/strtoimax.c | |
parent | 0e2331c9b6e0c0b4f24019d4062f4c655d28cbaf (diff) | |
download | musl-ecc9c5fcfa4831b290cc1a63c0346cbb0c1fcf42.tar.gz musl-ecc9c5fcfa4831b290cc1a63c0346cbb0c1fcf42.tar.bz2 musl-ecc9c5fcfa4831b290cc1a63c0346cbb0c1fcf42.tar.xz musl-ecc9c5fcfa4831b290cc1a63c0346cbb0c1fcf42.zip |
new restartable integer parsing framework.
this fixes a number of bugs in integer parsing due to lazy haphazard
wrapping, as well as some misinterpretations of the standard. the new
parser is able to work character-at-a-time or on whole strings, making
it easy to support the wide functions without unbounded space for
conversion. it will also be possible to update scanf to use the new
parser.
Diffstat (limited to 'src/stdlib/strtoimax.c')
-rw-r--r-- | src/stdlib/strtoimax.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/src/stdlib/strtoimax.c b/src/stdlib/strtoimax.c index aeb0397f..247f91d4 100644 --- a/src/stdlib/strtoimax.c +++ b/src/stdlib/strtoimax.c @@ -1,25 +1,38 @@ #include <inttypes.h> #include <errno.h> #include <ctype.h> +#include "intparse.h" intmax_t strtoimax(const char *s1, char **p, int base) { - const unsigned char *s = (const void *)s1; - int sign = 0; - uintmax_t x; + const unsigned char *s = (void *)s1; + struct intparse ip = {0}; + + if (p) *p = (char *)s1; + + if (base && base-2U > 34) { + errno = EINVAL; + return 0; + } - /* Initial whitespace */ for (; isspace(*s); s++); - /* Optional sign */ - if (*s == '-') sign = *s++; - else if (*s == '+') s++; + ip.base = base; + __intparse(&ip, s, SIZE_MAX); + + if (p && ip.err != EINVAL) + *p = (char *)s + ip.cnt; + + if (ip.err) { + errno = ip.err; + if (ip.err = EINVAL) return 0; + return ip.neg ? INTMAX_MIN : INTMAX_MAX; + } - x = strtoumax((const void *)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; } |