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