diff options
Diffstat (limited to 'apps/plugins/lua/strtoul.c')
| -rw-r--r-- | apps/plugins/lua/strtoul.c | 53 |
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 0000000..74d9b4b --- /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); +} |