f190247654930826f363599b8c098a93de1900c3
[musl] / src / stdlib / strtoumax.c
1 #include <inttypes.h>
2 #include <stdlib.h>
3 #include <errno.h>
4 #include <ctype.h>
5 #include <stdio.h>
6
7 /* Lookup table for digit values. -1==255>=36 -> invalid */
8 static const unsigned char digits[] = {
9 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
10 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
11 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
12  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
13 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
14 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
15 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
16 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
17 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
18 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
19 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
20 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
21 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
22 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
24 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
25 };
26
27 uintmax_t strtoumax(const char *s1, char **p, int base)
28 {
29         const unsigned char *s = (void *)s1;
30         size_t x1, z1;
31         uintmax_t x, z=0;
32         int sign = 0;
33         int shift;
34
35         if (!p) p = (char **)&s1;
36
37         /* Initial whitespace */
38         for (; isspace(*s); s++);
39
40         /* Optional sign */
41         if (*s == '-') sign = *s++;
42         else if (*s == '+') s++;
43
44         /* Default base 8, 10, or 16 depending on prefix */
45         if (base == 0) {
46                 if (s[0] == '0') {
47                         if ((s[1]|32) == 'x') base = 16;
48                         else base = 8;
49                 } else {
50                         base = 10;
51                 }
52         }
53
54         if ((unsigned)base-2 > 36-2 || digits[*s]>=base) {
55                 *p = (char *)s1;
56                 errno = EINVAL;
57                 return 0;
58         }
59
60         /* Main loops. Only use big types if we have to. */
61         if (base == 10) {
62                 for (x1=0; isdigit(*s) && x1<=SIZE_MAX/10-10; s++)
63                         x1 = 10*x1 + *s-'0';
64                 for (x=x1; isdigit(*s) && x<=UINTMAX_MAX/10-10; s++)
65                         x = 10*x + *s-'0';
66                 if (isdigit(*s)) {
67                         if (isdigit(s[1]) || 10*x>UINTMAX_MAX-(*s-'0'))
68                                 goto overflow;
69                         x = 10*x + *s-'0';
70                 }
71         } else if (!(base & base/2)) {
72                 if (base == 16) {
73                         if (s[0]=='0' && (s[1]|32)=='x' && digits[s[2]]<16)
74                                 s+=2;
75                         shift=4;
76                         z1 = SIZE_MAX/16;
77                         z = UINTMAX_MAX/16;
78                 } else if (base == 8) {
79                         shift=3;
80                         z1 = SIZE_MAX/8;
81                         z = UINTMAX_MAX/8;
82                 } else if (base == 2) {
83                         shift=1;
84                         z1 = SIZE_MAX/2;
85                         z = UINTMAX_MAX/2;
86                 } else if (base == 4) {
87                         shift=2;
88                         z1 = SIZE_MAX/4;
89                         z = UINTMAX_MAX/4;
90                 } else /* if (base == 32) */ {
91                         shift=5;
92                         z1 = SIZE_MAX/32;
93                         z = UINTMAX_MAX/32;
94                 }
95                 for (x1=0; digits[*s]<base && x1<=z1; s++)
96                         x1 = (x1<<shift) + digits[*s];
97                 for (x=x1; digits[*s]<base && x<=z; s++)
98                         x = (x<<shift) + digits[*s];
99                 if (digits[*s] < base) goto overflow;
100         } else {
101                 z1 = SIZE_MAX/base-base;
102                 for (x1=0; digits[*s]<base && x1<=z1; s++)
103                         x1 = x1*base + digits[*s];
104                 if (digits[*s]<base)
105                         z = UINTMAX_MAX/base-base;
106                 for (x=x1; digits[*s]<base && x<=z; s++)
107                         x = x*base + digits[*s];
108                 if (digits[*s] < base) {
109                         if (digits[s[1]]<base || x*base>UINTMAX_MAX-digits[*s])
110                                 goto overflow;
111                         x = x*base + digits[*s];
112                 }
113         }
114
115         *p = (char *)s;
116         return sign ? -x : x;
117
118 overflow:
119         for (; digits[*s] < base; s++);
120         *p = (char *)s;
121         errno = ERANGE;
122         return UINTMAX_MAX;
123 }