commit e6a49e347382074b4fc3e9c9088ef5c82244efea
parent 72132b63edb25a63073636e379749ee395666ed5
Author: Roberto Vargas <roberto.vargas@arm.com>
Date: Fri, 2 Nov 2018 14:21:43 +0000
[libc] Add strtoull
Diffstat:
2 files changed, 67 insertions(+), 0 deletions(-)
diff --git a/src/libc/stdlib/Makefile b/src/libc/stdlib/Makefile
@@ -22,5 +22,6 @@ OBJS = __abs.o\
qsort.o\
rand.o\
realloc.o\
+ strtoull.o\
all: $(OBJS)
diff --git a/src/libc/stdlib/strtoull.c b/src/libc/stdlib/strtoull.c
@@ -0,0 +1,66 @@
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#undef strtoull
+
+unsigned long long
+strtoull(const char *s, char **end, int base)
+{
+ int d, sign = 1;
+ unsigned long long n;
+ static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ const char *t, *p;
+
+ while (isspace(*s))
+ ++s;
+
+ switch (*s) {
+ case '-':
+ sign = -1;
+ case '+':
+ ++s;
+ }
+
+ if (base == 0) {
+ if (*s == '0' && toupper(s[1]) == 'x')
+ base = 16;
+ else if (*s == '0')
+ base = 8;
+ else
+ base = 10;
+ }
+
+ if (base == 16 && *s == '0' && toupper(s[1]) == 'X')
+ s += 2;
+ else if (base == 8 && *s == '0')
+ s++;
+
+ n = 0;
+ for (t = s; p = strchr(toupper(*t), digits); ++t) {
+ if ((d = p - digits) >= base)
+ break;
+ if (n > base/ULLONG_MAX)
+ goto overflow;
+ n *= base;
+ if (d > ULLONG_MAX - n)
+ goto overflow;
+ n += d;
+ }
+
+
+ if (end)
+ *end = t;
+ if (n == 0 && s == t)
+ errno = EINVAL;
+ return n*sign;;
+
+overflow:
+ if (end)
+ *end = t;
+ errno = ERANGE;
+
+ return ULLONG_MAX;
+}