• 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 * s,CharT ** end_ptr,int base)38 __attribute__((always_inline)) T StrToI(const CharT* s, CharT** end_ptr, 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 (end_ptr != nullptr) *end_ptr = const_cast<CharT*>(s);
42     errno = EINVAL;
43     return 0;
44   }
45 
46   // Skip white space and pick up leading +/- sign if any.
47   const CharT* p = s;
48   int c;
49   while (isspace(c = *p++)) {
50   }
51   bool neg = false;
52   if (c == '-') {
53     neg = true;
54     c = *p++;
55   } else if (c == '+') {
56     c = *p++;
57   }
58 
59   // If base is 0 or 16, allow "0x" prefix for hex.
60   if ((base == 0 || base == 16) && c == '0' && (*p == 'x' || *p == 'X') && isxdigit(p[1])) {
61     c = p[1];
62     p += 2;
63     base = 16;
64   }
65   // If base is 0 or 2, allow "0b" prefix for binary.
66   if ((base == 0 || base == 2) && c == '0' && (*p == 'b' || *p == 'B') && isdigit(p[1])) {
67     c = p[1];
68     p += 2;
69     base = 2;
70   }
71   // If base is 0, allow "0" prefix for octal, otherwise base is 10.
72   if (base == 0) base = (c == '0') ? 8 : 10;
73 
74   constexpr bool is_signed = (Min != 0);
75   T acc = 0;
76   // Non-zero if any digits consumed; negative to indicate overflow/underflow.
77   int any = 0;
78   for (;; c = *p++) {
79     if (isdigit(c)) {
80       c -= '0';
81     } else if (isalpha(c)) {
82       c = 10 + (_tolower(c) - 'a');
83     } else {
84       break;
85     }
86     if (c >= base) break;
87     if (any < 0) continue;
88     if (is_signed) {
89       // We work in the negative space because the most negative value has a
90       // larger magnitude than the most positive value.
91       if (__builtin_mul_overflow(acc, base, &acc) || __builtin_sub_overflow(acc, c, &acc)) {
92         any = -1;
93         continue;
94       }
95     } else {
96       if (__builtin_mul_overflow(acc, base, &acc) || __builtin_add_overflow(acc, c, &acc)) {
97         any = -1;
98         continue;
99       }
100     }
101     any = 1;
102   }
103 
104   if (end_ptr != nullptr) *end_ptr = const_cast<CharT*>(any ? p - 1 : s);
105 
106   // Detected overflow/underflow in the loop?
107   if (any == -1) {
108     errno = ERANGE;
109     return (is_signed && neg) ? Min : Max;
110   }
111 
112   // Will we overflow by trying to negate the most negative value?
113   if (any > 0 && is_signed && !neg && acc == Min) {
114     errno = ERANGE;
115     return Max;
116   }
117 
118   if (is_signed) return neg ? acc : -acc;
119   return neg ? -acc : acc;
120 }
121 
atoi(const char * s)122 int atoi(const char* s) {
123   return strtol(s, nullptr, 10);
124 }
125 
atol(const char * s)126 long atol(const char* s) {
127   return strtol(s, nullptr, 10);
128 }
129 
atoll(const char * s)130 long long atoll(const char* s) {
131   return strtoll(s, nullptr, 10);
132 }
133 
strtoimax(const char * s,char ** end,int base)134 intmax_t strtoimax(const char* s, char** end, int base) {
135   return StrToI<intmax_t, INTMAX_MIN, INTMAX_MAX, char>(s, end, base);
136 }
137 
wcstoimax(const wchar_t * s,wchar_t ** end,int base)138 intmax_t wcstoimax(const wchar_t* s, wchar_t** end, int base) {
139   return StrToI<intmax_t, INTMAX_MIN, INTMAX_MAX, wchar_t>(s, end, base);
140 }
141 
strtol(const char * s,char ** end,int base)142 long strtol(const char* s, char** end, int base) {
143   return StrToI<long, LONG_MIN, LONG_MAX, char>(s, end, base);
144 }
145 
wcstol(const wchar_t * s,wchar_t ** end,int base)146 long wcstol(const wchar_t* s, wchar_t** end, int base) {
147   return StrToI<long, LONG_MIN, LONG_MAX, wchar_t>(s, end, base);
148 }
149 
strtoll(const char * s,char ** end,int base)150 long long strtoll(const char* s, char** end, int base) {
151   return StrToI<long long, LLONG_MIN, LLONG_MAX, char>(s, end, base);
152 }
153 
wcstoll(const wchar_t * s,wchar_t ** end,int base)154 long long wcstoll(const wchar_t* s, wchar_t** end, int base) {
155   return StrToI<long long, LLONG_MIN, LLONG_MAX, wchar_t>(s, end, base);
156 }
157 
strtoul(const char * s,char ** end,int base)158 unsigned long strtoul(const char* s, char** end, int base) {
159   return StrToI<unsigned long, 0, ULONG_MAX, char>(s, end, base);
160 }
161 
wcstoul(const wchar_t * s,wchar_t ** end,int base)162 unsigned long wcstoul(const wchar_t* s, wchar_t** end, int base) {
163   return StrToI<unsigned long, 0, ULONG_MAX, wchar_t>(s, end, base);
164 }
165 
strtoull(const char * s,char ** end,int base)166 unsigned long long strtoull(const char* s, char** end, int base) {
167   return StrToI<unsigned long long, 0, ULLONG_MAX, char>(s, end, base);
168 }
169 
wcstoull(const wchar_t * s,wchar_t ** end,int base)170 unsigned long long wcstoull(const wchar_t* s, wchar_t** end, int base) {
171   return StrToI<unsigned long long, 0, ULLONG_MAX, wchar_t>(s, end, base);
172 }
173 
strtoumax(const char * s,char ** end,int base)174 uintmax_t strtoumax(const char* s, char** end, int base) {
175   return StrToI<uintmax_t, 0, UINTMAX_MAX, char>(s, end, base);
176 }
177 
wcstoumax(const wchar_t * s,wchar_t ** end,int base)178 uintmax_t wcstoumax(const wchar_t* s, wchar_t** end, int base) {
179   return StrToI<uintmax_t, 0, UINTMAX_MAX, wchar_t>(s, end, base);
180 }
181