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 0000000000..74d9b4bb09 --- /dev/null +++ b/apps/plugins/lua/strtoul.c | |||
@@ -0,0 +1,53 @@ | |||
1 | #include "rocklibc.h" | ||
2 | |||
3 | unsigned long int strtoul(const char *ptr, char **endptr, int base) | ||
4 | { | ||
5 | int neg = 0, overflow = 0; | ||
6 | unsigned long int v=0; | ||
7 | const char* orig; | ||
8 | const char* nptr=ptr; | ||
9 | |||
10 | while(isspace(*nptr)) ++nptr; | ||
11 | |||
12 | if (*nptr == '-') { neg=1; nptr++; } | ||
13 | else if (*nptr == '+') ++nptr; | ||
14 | orig=nptr; | ||
15 | if (base==16 && nptr[0]=='0') goto skip0x; | ||
16 | if (base) { | ||
17 | register unsigned int b=base-2; | ||
18 | if (__unlikely(b>34)) { errno=EINVAL; return 0; } | ||
19 | } else { | ||
20 | if (*nptr=='0') { | ||
21 | base=8; | ||
22 | skip0x: | ||
23 | if ((nptr[1]=='x'||nptr[1]=='X') && isxdigit(nptr[2])) { | ||
24 | nptr+=2; | ||
25 | base=16; | ||
26 | } | ||
27 | } else | ||
28 | base=10; | ||
29 | } | ||
30 | while(__likely(*nptr)) { | ||
31 | register unsigned char c=*nptr; | ||
32 | c=(c>='a'?c-'a'+10:c>='A'?c-'A'+10:c<='9'?c-'0':0xff); | ||
33 | if (__unlikely(c>=base)) break; /* out of base */ | ||
34 | { | ||
35 | register unsigned long x=(v&0xff)*base+c; | ||
36 | register unsigned long w=(v>>8)*base+(x>>8); | ||
37 | if (w>(ULONG_MAX>>8)) overflow=1; | ||
38 | v=(w<<8)+(x&0xff); | ||
39 | } | ||
40 | ++nptr; | ||
41 | } | ||
42 | if (__unlikely(nptr==orig)) { /* no conversion done */ | ||
43 | nptr=ptr; | ||
44 | errno=EINVAL; | ||
45 | v=0; | ||
46 | } | ||
47 | if (endptr) *endptr=(char *)nptr; | ||
48 | if (overflow) { | ||
49 | errno=ERANGE; | ||
50 | return ULONG_MAX; | ||
51 | } | ||
52 | return (neg?-v:v); | ||
53 | } | ||