Skip to content

Commit 2bcf1c5

Browse files
asedenocopybara-github
authored andcommitted
Add support for 8-bit and 16-bit integers to absl::SimpleAtoi
Closes abseil/abseil-cpp#1762 PiperOrigin-RevId: 730514635 Change-Id: I33aa7140a457a81bf7b0f878854fbc127258c439
1 parent 4cd2009 commit 2bcf1c5

File tree

3 files changed

+692
-117
lines changed

3 files changed

+692
-117
lines changed

absl/strings/numbers.cc

+20
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,16 @@ ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] =
11111111
"e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
11121112
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
11131113

1114+
bool safe_strto8_base(absl::string_view text, absl::Nonnull<int8_t*> value,
1115+
int base) {
1116+
return safe_int_internal<int8_t>(text, value, base);
1117+
}
1118+
1119+
bool safe_strto16_base(absl::string_view text, absl::Nonnull<int16_t*> value,
1120+
int base) {
1121+
return safe_int_internal<int16_t>(text, value, base);
1122+
}
1123+
11141124
bool safe_strto32_base(absl::string_view text, absl::Nonnull<int32_t*> value,
11151125
int base) {
11161126
return safe_int_internal<int32_t>(text, value, base);
@@ -1126,6 +1136,16 @@ bool safe_strto128_base(absl::string_view text, absl::Nonnull<int128*> value,
11261136
return safe_int_internal<absl::int128>(text, value, base);
11271137
}
11281138

1139+
bool safe_strtou8_base(absl::string_view text, absl::Nonnull<uint8_t*> value,
1140+
int base) {
1141+
return safe_uint_internal<uint8_t>(text, value, base);
1142+
}
1143+
1144+
bool safe_strtou16_base(absl::string_view text, absl::Nonnull<uint16_t*> value,
1145+
int base) {
1146+
return safe_uint_internal<uint16_t>(text, value, base);
1147+
}
1148+
11291149
bool safe_strtou32_base(absl::string_view text, absl::Nonnull<uint32_t*> value,
11301150
int base) {
11311151
return safe_uint_internal<uint32_t>(text, value, base);

absl/strings/numbers.h

+48-15
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@
3232
#endif
3333

3434
#include <cstddef>
35+
#include <cstdint>
3536
#include <cstdlib>
3637
#include <cstring>
3738
#include <ctime>
3839
#include <limits>
3940
#include <string>
4041
#include <type_traits>
4142

43+
#include "absl/base/attributes.h"
4244
#include "absl/base/config.h"
4345
#include "absl/base/internal/endian.h"
4446
#include "absl/base/macros.h"
@@ -127,6 +129,18 @@ namespace absl {
127129
ABSL_NAMESPACE_BEGIN
128130
namespace numbers_internal {
129131

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+
130144
// Digit conversion.
131145
ABSL_DLL extern const char kHexChar[17]; // 0123456789abcdef
132146
ABSL_DLL extern const char
@@ -142,12 +156,20 @@ void PutTwoDigits(uint32_t i, absl::Nonnull<char*> buf);
142156

143157
// safe_strto?() functions for implementing SimpleAtoi()
144158

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);
145163
bool safe_strto32_base(absl::string_view text, absl::Nonnull<int32_t*> value,
146164
int base);
147165
bool safe_strto64_base(absl::string_view text, absl::Nonnull<int64_t*> value,
148166
int base);
149167
bool safe_strto128_base(absl::string_view text,
150168
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);
151173
bool safe_strtou32_base(absl::string_view text, absl::Nonnull<uint32_t*> value,
152174
int base);
153175
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)
186208
ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize) {
187209
static_assert(sizeof(i) <= 64 / 8,
188210
"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.
192211
// 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>();
194213
constexpr bool kUse64Bit = sizeof(i) > 32 / 8;
195214
if (kIsSigned) {
196215
if (kUse64Bit) {
@@ -213,36 +232,50 @@ template <typename int_type>
213232
ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s,
214233
absl::Nonnull<int_type*> out,
215234
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.");
218238
static_assert(!std::is_floating_point<int_type>::value,
219239
"Use SimpleAtof or SimpleAtod instead.");
220240
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.
224241
// 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;
227244
if (kIsSigned) {
228-
if (kUse64Bit) {
245+
if (kIntTypeSize == 64) {
229246
int64_t val;
230247
parsed = numbers_internal::safe_strto64_base(s, &val, base);
231248
*out = static_cast<int_type>(val);
232-
} else {
249+
} else if (kIntTypeSize == 32) {
233250
int32_t val;
234251
parsed = numbers_internal::safe_strto32_base(s, &val, base);
235252
*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);
236261
}
237262
} else {
238-
if (kUse64Bit) {
263+
if (kIntTypeSize == 64) {
239264
uint64_t val;
240265
parsed = numbers_internal::safe_strtou64_base(s, &val, base);
241266
*out = static_cast<int_type>(val);
242-
} else {
267+
} else if (kIntTypeSize == 32) {
243268
uint32_t val;
244269
parsed = numbers_internal::safe_strtou32_base(s, &val, base);
245270
*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);
246279
}
247280
}
248281
return parsed;

0 commit comments

Comments
 (0)