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 {
127129ABSL_NAMESPACE_BEGIN
128130namespace 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.
131145ABSL_DLL extern const char kHexChar [17 ]; // 0123456789abcdef
132146ABSL_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);
145163bool safe_strto32_base (absl::string_view text, absl::Nonnull<int32_t *> value,
146164 int base);
147165bool safe_strto64_base (absl::string_view text, absl::Nonnull<int64_t *> value,
148166 int base);
149167bool 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);
151173bool safe_strtou32_base (absl::string_view text, absl::Nonnull<uint32_t *> value,
152174 int base);
153175bool 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>
213232ABSL_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