32
32
#endif
33
33
34
34
#include < cstddef>
35
+ #include < cstdint>
35
36
#include < cstdlib>
36
37
#include < cstring>
37
38
#include < ctime>
38
39
#include < limits>
39
40
#include < string>
40
41
#include < type_traits>
41
42
43
+ #include " absl/base/attributes.h"
42
44
#include " absl/base/config.h"
43
45
#include " absl/base/internal/endian.h"
44
46
#include " absl/base/macros.h"
@@ -127,6 +129,18 @@ namespace absl {
127
129
ABSL_NAMESPACE_BEGIN
128
130
namespace numbers_internal {
129
131
132
+ template <typename int_type>
133
+ constexpr bool is_signed () {
134
+ if constexpr (std::is_arithmetic<int_type>::value) {
135
+ // Use std::numeric_limits<T>::is_signed where it's defined to work.
136
+ return std::numeric_limits<int_type>::is_signed;
137
+ }
138
+ // TODO(jorg): This signed-ness check is used because it works correctly
139
+ // with enums, and it also serves to check that int_type is not a pointer.
140
+ // If one day something like std::is_signed<enum E> works, switch to it.
141
+ return static_cast <int_type>(1 ) - 2 < 0 ;
142
+ }
143
+
130
144
// Digit conversion.
131
145
ABSL_DLL extern const char kHexChar [17 ]; // 0123456789abcdef
132
146
ABSL_DLL extern const char
@@ -142,12 +156,20 @@ void PutTwoDigits(uint32_t i, absl::Nonnull<char*> buf);
142
156
143
157
// safe_strto?() functions for implementing SimpleAtoi()
144
158
159
+ bool safe_strto8_base (absl::string_view text, absl::Nonnull<int8_t *> value,
160
+ int base);
161
+ bool safe_strto16_base (absl::string_view text, absl::Nonnull<int16_t *> value,
162
+ int base);
145
163
bool safe_strto32_base (absl::string_view text, absl::Nonnull<int32_t *> value,
146
164
int base);
147
165
bool safe_strto64_base (absl::string_view text, absl::Nonnull<int64_t *> value,
148
166
int base);
149
167
bool safe_strto128_base (absl::string_view text,
150
168
absl::Nonnull<absl::int128*> value, int base);
169
+ bool safe_strtou8_base (absl::string_view text, absl::Nonnull<uint8_t *> value,
170
+ int base);
171
+ bool safe_strtou16_base (absl::string_view text, absl::Nonnull<uint16_t *> value,
172
+ int base);
151
173
bool safe_strtou32_base (absl::string_view text, absl::Nonnull<uint32_t *> value,
152
174
int base);
153
175
bool safe_strtou64_base (absl::string_view text, absl::Nonnull<uint64_t *> value,
@@ -186,11 +208,8 @@ absl::Nonnull<char*> FastIntToBuffer(int_type i, absl::Nonnull<char*> buffer)
186
208
ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize ) {
187
209
static_assert (sizeof (i) <= 64 / 8 ,
188
210
" FastIntToBuffer works only with 64-bit-or-less integers." );
189
- // TODO(jorg): This signed-ness check is used because it works correctly
190
- // with enums, and it also serves to check that int_type is not a pointer.
191
- // If one day something like std::is_signed<enum E> works, switch to it.
192
211
// These conditions are constexpr bools to suppress MSVC warning C4127.
193
- constexpr bool kIsSigned = static_cast <int_type>(1 ) - 2 < 0 ;
212
+ constexpr bool kIsSigned = is_signed <int_type>() ;
194
213
constexpr bool kUse64Bit = sizeof (i) > 32 / 8 ;
195
214
if (kIsSigned ) {
196
215
if (kUse64Bit ) {
@@ -213,36 +232,50 @@ template <typename int_type>
213
232
ABSL_MUST_USE_RESULT bool safe_strtoi_base (absl::string_view s,
214
233
absl::Nonnull<int_type*> out,
215
234
int base) {
216
- static_assert (sizeof (*out) == 4 || sizeof (*out) == 8 ,
217
- " SimpleAtoi works only with 32-bit or 64-bit integers." );
235
+ static_assert (sizeof (*out) == 1 || sizeof (*out) == 2 || sizeof (*out) == 4 ||
236
+ sizeof (*out) == 8 ,
237
+ " SimpleAtoi works only with 8, 16, 32, or 64-bit integers." );
218
238
static_assert (!std::is_floating_point<int_type>::value,
219
239
" Use SimpleAtof or SimpleAtod instead." );
220
240
bool parsed;
221
- // TODO(jorg): This signed-ness check is used because it works correctly
222
- // with enums, and it also serves to check that int_type is not a pointer.
223
- // If one day something like std::is_signed<enum E> works, switch to it.
224
241
// These conditions are constexpr bools to suppress MSVC warning C4127.
225
- constexpr bool kIsSigned = static_cast <int_type>(1 ) - 2 < 0 ;
226
- constexpr bool kUse64Bit = sizeof (*out) == 64 / 8 ;
242
+ constexpr bool kIsSigned = is_signed <int_type>() ;
243
+ constexpr int kIntTypeSize = sizeof (*out) * 8 ;
227
244
if (kIsSigned ) {
228
- if (kUse64Bit ) {
245
+ if (kIntTypeSize == 64 ) {
229
246
int64_t val;
230
247
parsed = numbers_internal::safe_strto64_base (s, &val, base);
231
248
*out = static_cast <int_type>(val);
232
- } else {
249
+ } else if ( kIntTypeSize == 32 ) {
233
250
int32_t val;
234
251
parsed = numbers_internal::safe_strto32_base (s, &val, base);
235
252
*out = static_cast <int_type>(val);
253
+ } else if (kIntTypeSize == 16 ) {
254
+ int16_t val;
255
+ parsed = numbers_internal::safe_strto16_base (s, &val, base);
256
+ *out = static_cast <int_type>(val);
257
+ } else if (kIntTypeSize == 8 ) {
258
+ int8_t val;
259
+ parsed = numbers_internal::safe_strto8_base (s, &val, base);
260
+ *out = static_cast <int_type>(val);
236
261
}
237
262
} else {
238
- if (kUse64Bit ) {
263
+ if (kIntTypeSize == 64 ) {
239
264
uint64_t val;
240
265
parsed = numbers_internal::safe_strtou64_base (s, &val, base);
241
266
*out = static_cast <int_type>(val);
242
- } else {
267
+ } else if ( kIntTypeSize == 32 ) {
243
268
uint32_t val;
244
269
parsed = numbers_internal::safe_strtou32_base (s, &val, base);
245
270
*out = static_cast <int_type>(val);
271
+ } else if (kIntTypeSize == 16 ) {
272
+ uint16_t val;
273
+ parsed = numbers_internal::safe_strtou16_base (s, &val, base);
274
+ *out = static_cast <int_type>(val);
275
+ } else if (kIntTypeSize == 8 ) {
276
+ uint8_t val;
277
+ parsed = numbers_internal::safe_strtou8_base (s, &val, base);
278
+ *out = static_cast <int_type>(val);
246
279
}
247
280
}
248
281
return parsed;
0 commit comments