• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <errno.h>
31 #include <inttypes.h>
32 #include <limits.h>
33 #include <stdlib.h>
34 
35 #include <private/bionic_ctype.h>
36 
StrToI(const char * nptr,char ** endptr,int base)37 template <typename T, T Min, T Max> T StrToI(const char* nptr, char** endptr, int base) {
38   // Ensure that base is between 2 and 36 inclusive, or the special value of 0.
39   if (base < 0 || base == 1 || base > 36) {
40     if (endptr != nullptr) *endptr = const_cast<char*>(nptr);
41     errno = EINVAL;
42     return 0;
43   }
44 
45   // Skip white space and pick up leading +/- sign if any.
46   // If base is 0, allow 0x for hex and 0 for octal, else
47   // assume decimal; if base is already 16, allow 0x.
48   const char* s = nptr;
49   int c;
50   do {
51     c = *s++;
52   } while (IsSpace(c));
53   int neg;
54   if (c == '-') {
55     neg = 1;
56     c = *s++;
57   } else {
58     neg = 0;
59     if (c == '+') c = *s++;
60   }
61   if ((base == 0 || base == 16) && c == '0' &&
62       (*s == 'x' || *s == 'X') && IsXDigit(s[1])) {
63     c = s[1];
64     s += 2;
65     base = 16;
66   }
67   if (base == 0) base = (c == '0') ? 8 : 10;
68 
69   // We always work in the negative space because the most negative value has a
70   // larger magnitude than the most positive value.
71   T cutoff = Min / base;
72   int cutlim = -(Min % base);
73   // Non-zero if any digits consumed; negative to indicate overflow/underflow.
74   int any = 0;
75   T acc = 0;
76   for (; ; c = *s++) {
77     if (IsDigit(c)) {
78       c -= '0';
79     } else if (IsAlpha(c)) {
80       c -= IsUpper(c) ? 'A' - 10 : 'a' - 10;
81     } else {
82       break;
83     }
84     if (c >= base) break;
85     if (any < 0) continue;
86     if (acc < cutoff || (acc == cutoff && c > cutlim)) {
87       any = -1;
88       acc = Min;
89       errno = ERANGE;
90     } else {
91       any = 1;
92       acc *= base;
93       acc -= c;
94     }
95   }
96   if (endptr != nullptr) *endptr = const_cast<char*>(any ? s - 1 : nptr);
97   if (!neg) {
98     if (acc == Min) {
99       errno = ERANGE;
100       acc = Max;
101     } else {
102       acc = -acc;
103     }
104   }
105   return acc;
106 }
107 
StrToU(const char * nptr,char ** endptr,int base)108 template <typename T, T Max> T StrToU(const char* nptr, char** endptr, int base) {
109   if (base < 0 || base == 1 || base > 36) {
110     if (endptr != nullptr) *endptr = const_cast<char*>(nptr);
111     errno = EINVAL;
112     return 0;
113   }
114 
115   const char* s = nptr;
116   int c;
117   do {
118     c = *s++;
119   } while (IsSpace(c));
120   int neg;
121   if (c == '-') {
122     neg = 1;
123     c = *s++;
124   } else {
125     neg = 0;
126     if (c == '+') c = *s++;
127   }
128   if ((base == 0 || base == 16) && c == '0' &&
129       (*s == 'x' || *s == 'X') && IsXDigit(s[1])) {
130     c = s[1];
131     s += 2;
132     base = 16;
133   }
134   if (base == 0) base = (c == '0') ? 8 : 10;
135 
136   T cutoff = Max / static_cast<T>(base);
137   int cutlim = Max % static_cast<T>(base);
138   T acc = 0;
139   int any = 0;
140   for (; ; c = *s++) {
141     if (IsDigit(c)) {
142       c -= '0';
143     } else if (IsAlpha(c)) {
144       c -= IsUpper(c) ? 'A' - 10 : 'a' - 10;
145     } else {
146       break;
147     }
148     if (c >= base) break;
149     if (any < 0) continue;
150     if (acc > cutoff || (acc == cutoff && c > cutlim)) {
151       any = -1;
152       acc = Max;
153       errno = ERANGE;
154     } else {
155       any = 1;
156       acc *= base;
157       acc += c;
158     }
159   }
160   if (neg && any > 0) acc = -acc;
161   if (endptr != nullptr) *endptr = const_cast<char*>(any ? s - 1 : nptr);
162   return acc;
163 }
164 
atoi(const char * s)165 int atoi(const char* s) {
166   return strtol(s, nullptr, 10);
167 }
168 
atol(const char * s)169 long atol(const char* s) {
170   return strtol(s, nullptr, 10);
171 }
172 
atoll(const char * s)173 long long atoll(const char* s) {
174   return strtoll(s, nullptr, 10);
175 }
176 
strtoimax(const char * s,char ** end,int base)177 intmax_t strtoimax(const char* s, char** end, int base) {
178   return StrToI<intmax_t, INTMAX_MIN, INTMAX_MAX>(s, end, base);
179 }
180 
strtol(const char * s,char ** end,int base)181 long strtol(const char* s, char** end, int base) {
182   return StrToI<long, LONG_MIN, LONG_MAX>(s, end, base);
183 }
184 
strtoll(const char * s,char ** end,int base)185 long long strtoll(const char* s, char** end, int base) {
186   return StrToI<long long, LLONG_MIN, LLONG_MAX>(s, end, base);
187 }
188 
189 // Public API since L, but not in any header.
strtoq(const char * s,char ** end,int base)190 extern "C" long long strtoq(const char* s, char** end, int base) {
191   return strtoll(s, end, base);
192 }
193 
strtoul(const char * s,char ** end,int base)194 unsigned long strtoul(const char* s, char** end, int base) {
195   return StrToU<unsigned long, ULONG_MAX>(s, end, base);
196 }
197 
strtoull(const char * s,char ** end,int base)198 unsigned long long strtoull(const char* s, char** end, int base) {
199   return StrToU<unsigned long long, ULLONG_MAX>(s, end, base);
200 }
201 
strtoumax(const char * s,char ** end,int base)202 uintmax_t strtoumax(const char* s, char** end, int base) {
203   return StrToU<uintmax_t, UINTMAX_MAX>(s, end, base);
204 }
205 
206 // Public API since L, but not in any header.
strtouq(const char * s,char ** end,int base)207 extern "C" unsigned long long strtouq(const char* s, char** end, int base) {
208   return strtoull(s, end, base);
209 }
210