1 /*
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <ctype.h>
31 #include <errno.h>
32 #include <inttypes.h>
33 #include <limits.h>
34 #include <stdlib.h>
35 
StrToI(const char * nptr,char ** endptr,int base)36 template <typename T, T Min, T Max> T StrToI(const char* nptr, char** endptr, int base) {
37   // Ensure that base is between 2 and 36 inclusive, or the special value of 0.
38   if (base < 0 || base == 1 || base > 36) {
39     if (endptr != nullptr) *endptr = const_cast<char*>(nptr);
40     errno = EINVAL;
41     return 0;
42   }
43 
44   // Skip white space and pick up leading +/- sign if any.
45   // If base is 0, allow 0x for hex and 0 for octal, else
46   // assume decimal; if base is already 16, allow 0x.
47   const char* s = nptr;
48   int c;
49   do {
50     c = *s++;
51   } while (isspace(c));
52   int neg;
53   if (c == '-') {
54     neg = 1;
55     c = *s++;
56   } else {
57     neg = 0;
58     if (c == '+') c = *s++;
59   }
60   if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X') && isxdigit(s[1])) {
61     c = s[1];
62     s += 2;
63     base = 16;
64   }
65   if (base == 0) base = (c == '0') ? 8 : 10;
66 
67   // We always work in the negative space because the most negative value has a
68   // larger magnitude than the most positive value.
69   T cutoff = Min / base;
70   int cutlim = -(Min % base);
71   // Non-zero if any digits consumed; negative to indicate overflow/underflow.
72   int any = 0;
73   T acc = 0;
74   for (; ; c = *s++) {
75     if (isdigit(c)) {
76       c -= '0';
77     } else if (isalpha(c)) {
78       c -= isupper(c) ? 'A' - 10 : 'a' - 10;
79     } else {
80       break;
81     }
82     if (c >= base) break;
83     if (any < 0) continue;
84     if (acc < cutoff || (acc == cutoff && c > cutlim)) {
85       any = -1;
86       acc = Min;
87       errno = ERANGE;
88     } else {
89       any = 1;
90       acc *= base;
91       acc -= c;
92     }
93   }
94   if (endptr != nullptr) *endptr = const_cast<char*>(any ? s - 1 : nptr);
95   if (!neg) {
96     if (acc == Min) {
97       errno = ERANGE;
98       acc = Max;
99     } else {
100       acc = -acc;
101     }
102   }
103   return acc;
104 }
105 
StrToU(const char * nptr,char ** endptr,int base)106 template <typename T, T Max> T StrToU(const char* nptr, char** endptr, int base) {
107   if (base < 0 || base == 1 || base > 36) {
108     if (endptr != nullptr) *endptr = const_cast<char*>(nptr);
109     errno = EINVAL;
110     return 0;
111   }
112 
113   const char* s = nptr;
114   int c;
115   do {
116     c = *s++;
117   } while (isspace(c));
118   int neg;
119   if (c == '-') {
120     neg = 1;
121     c = *s++;
122   } else {
123     neg = 0;
124     if (c == '+') c = *s++;
125   }
126   if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X') && isxdigit(s[1])) {
127     c = s[1];
128     s += 2;
129     base = 16;
130   }
131   if (base == 0) base = (c == '0') ? 8 : 10;
132 
133   T cutoff = Max / static_cast<T>(base);
134   int cutlim = Max % static_cast<T>(base);
135   T acc = 0;
136   int any = 0;
137   for (; ; c = *s++) {
138     if (isdigit(c)) {
139       c -= '0';
140     } else if (isalpha(c)) {
141       c -= isupper(c) ? 'A' - 10 : 'a' - 10;
142     } else {
143       break;
144     }
145     if (c >= base) break;
146     if (any < 0) continue;
147     if (acc > cutoff || (acc == cutoff && c > cutlim)) {
148       any = -1;
149       acc = Max;
150       errno = ERANGE;
151     } else {
152       any = 1;
153       acc *= base;
154       acc += c;
155     }
156   }
157   if (neg && any > 0) acc = -acc;
158   if (endptr != nullptr) *endptr = const_cast<char*>(any ? s - 1 : nptr);
159   return acc;
160 }
161 
atoi(const char * s)162 int atoi(const char* s) {
163   return strtol(s, nullptr, 10);
164 }
165 
atol(const char * s)166 long atol(const char* s) {
167   return strtol(s, nullptr, 10);
168 }
169 
atoll(const char * s)170 long long atoll(const char* s) {
171   return strtoll(s, nullptr, 10);
172 }
173 
strtoimax(const char * s,char ** end,int base)174 intmax_t strtoimax(const char* s, char** end, int base) {
175   return StrToI<intmax_t, INTMAX_MIN, INTMAX_MAX>(s, end, base);
176 }
177 
strtol(const char * s,char ** end,int base)178 long strtol(const char* s, char** end, int base) {
179   return StrToI<long, LONG_MIN, LONG_MAX>(s, end, base);
180 }
181 
strtoll(const char * s,char ** end,int base)182 long long strtoll(const char* s, char** end, int base) {
183   return StrToI<long long, LLONG_MIN, LLONG_MAX>(s, end, base);
184 }
185 
186 // Public API since L, but not in any header.
187 __strong_alias(strtoq, strtoll);
188 
strtoul(const char * s,char ** end,int base)189 unsigned long strtoul(const char* s, char** end, int base) {
190   return StrToU<unsigned long, ULONG_MAX>(s, end, base);
191 }
192 
strtoull(const char * s,char ** end,int base)193 unsigned long long strtoull(const char* s, char** end, int base) {
194   return StrToU<unsigned long long, ULLONG_MAX>(s, end, base);
195 }
196 
strtoumax(const char * s,char ** end,int base)197 uintmax_t strtoumax(const char* s, char** end, int base) {
198   return StrToU<uintmax_t, UINTMAX_MAX>(s, end, base);
199 }
200 
201 // Public API since L, but not in any header.
202 __strong_alias(strtouq, strtoull);
203