From c21902d3e005d49fabb5f70eb69cbe597a8f7366 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Wed, 11 May 2022 22:06:01 +0100 Subject: [PATCH] Implemented a proper version of strtoul() --- photon/libc/stdlib/strtoul.c | 67 +++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/photon/libc/stdlib/strtoul.c b/photon/libc/stdlib/strtoul.c index 8f43e65..892a680 100644 --- a/photon/libc/stdlib/strtoul.c +++ b/photon/libc/stdlib/strtoul.c @@ -5,5 +5,70 @@ unsigned long strtoul(const char *nptr, char **endptr, int base) { - return (unsigned long)strtol(nptr, endptr, base); + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + do { + c = *s++; + } while (isspace(c)); + + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') { + c = *s++; + } if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } else if ((base == 0 || base == 2) && + c == '0' && (*s == 'b' || *s == 'B')) { + c = s[1]; + s += 2; + base = 2; + } + + if (base == 0) { + base = c == '0' ? 8 : 10; + } + + cutoff = ULONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) { + c -= '0'; + } else if (isalpha(c)) { + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + } else { + break; + } + + if (c >= base) { + break; + } if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) { + any = -1; + } else { + any = 1; + acc *= base; + acc += c; + } + } + + if (any < 0) { + acc = ULONG_MAX; + } else if (neg) { + acc = -acc; + } + + if (endptr != 0) { + *endptr = (char *)(any ? s - 1 : nptr); + } + + return acc; }