summaryrefslogtreecommitdiffstats
path: root/apps/plugins/lua/strtoul.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/lua/strtoul.c')
-rw-r--r--apps/plugins/lua/strtoul.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/apps/plugins/lua/strtoul.c b/apps/plugins/lua/strtoul.c
new file mode 100644
index 0000000000..74d9b4bb09
--- /dev/null
+++ b/apps/plugins/lua/strtoul.c
@@ -0,0 +1,53 @@
+#include "rocklibc.h"
+
+unsigned long int strtoul(const char *ptr, char **endptr, int base)
+{
+ int neg = 0, overflow = 0;
+ unsigned long int v=0;
+ const char* orig;
+ const char* nptr=ptr;
+
+ while(isspace(*nptr)) ++nptr;
+
+ if (*nptr == '-') { neg=1; nptr++; }
+ else if (*nptr == '+') ++nptr;
+ orig=nptr;
+ if (base==16 && nptr[0]=='0') goto skip0x;
+ if (base) {
+ register unsigned int b=base-2;
+ if (__unlikely(b>34)) { errno=EINVAL; return 0; }
+ } else {
+ if (*nptr=='0') {
+ base=8;
+skip0x:
+ if ((nptr[1]=='x'||nptr[1]=='X') && isxdigit(nptr[2])) {
+ nptr+=2;
+ base=16;
+ }
+ } else
+ base=10;
+ }
+ while(__likely(*nptr)) {
+ register unsigned char c=*nptr;
+ c=(c>='a'?c-'a'+10:c>='A'?c-'A'+10:c<='9'?c-'0':0xff);
+ if (__unlikely(c>=base)) break; /* out of base */
+ {
+ register unsigned long x=(v&0xff)*base+c;
+ register unsigned long w=(v>>8)*base+(x>>8);
+ if (w>(ULONG_MAX>>8)) overflow=1;
+ v=(w<<8)+(x&0xff);
+ }
+ ++nptr;
+ }
+ if (__unlikely(nptr==orig)) { /* no conversion done */
+ nptr=ptr;
+ errno=EINVAL;
+ v=0;
+ }
+ if (endptr) *endptr=(char *)nptr;
+ if (overflow) {
+ errno=ERANGE;
+ return ULONG_MAX;
+ }
+ return (neg?-v:v);
+}