aboutsummaryrefslogtreecommitdiffhomepage
path: root/absl/strings/numbers.h
diff options
context:
space:
mode:
Diffstat (limited to 'absl/strings/numbers.h')
-rw-r--r--absl/strings/numbers.h45
1 files changed, 43 insertions, 2 deletions
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index 100839b..745de67 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -24,6 +24,10 @@
#ifndef ABSL_STRINGS_NUMBERS_H_
#define ABSL_STRINGS_NUMBERS_H_
+#ifdef __SSE4_2__
+#include <x86intrin.h>
+#endif
+
#include <cstddef>
#include <cstdlib>
#include <cstring>
@@ -32,6 +36,8 @@
#include <string>
#include <type_traits>
+#include "absl/base/internal/bits.h"
+#include "absl/base/internal/endian.h"
#include "absl/base/macros.h"
#include "absl/base/port.h"
#include "absl/numeric/int128.h"
@@ -54,7 +60,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out);
// Converts the given string (optionally followed or preceded by ASCII
// whitespace) into a float, which may be rounded on overflow or underflow.
// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`. If any errors are encountered, this function
+// allowed formats for `str`, except SimpleAtof() is locale-indepdent and will
+// always use the "C" locale. If any errors are encountered, this function
// returns `false`, leaving `out` in an unspecified state.
ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out);
@@ -63,7 +70,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out);
// Converts the given string (optionally followed or preceded by ASCII
// whitespace) into a double, which may be rounded on overflow or underflow.
// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`. If any errors are encountered, this function
+// allowed formats for `str`, except SimpleAtod is locale-independent and will
+// always use the "C" locale. If any errors are encountered, this function
// returns `false`, leaving `out` in an unspecified state.
ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out);
@@ -84,6 +92,10 @@ ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out);
namespace absl {
namespace numbers_internal {
+// Digit conversion.
+extern const char kHexChar[17]; // 0123456789abcdef
+extern const char kHexTable[513]; // 000102030405060708090a0b0c0d0e0f1011...
+
// safe_strto?() functions for implementing SimpleAtoi()
bool safe_strto32_base(absl::string_view text, int32_t* value, int base);
bool safe_strto64_base(absl::string_view text, int64_t* value, int base);
@@ -170,6 +182,35 @@ ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s, int_type* out,
return parsed;
}
+// FastHexToBufferZeroPad16()
+//
+// Outputs `val` into `out` as if by `snprintf(out, 17, "%016x", val)` but
+// without the terminating null character. Thus `out` must be of length >= 16.
+// Returns the number of non-pad digits of the output (it can never be zero
+// since 0 has one digit).
+inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) {
+ uint64_t be = absl::big_endian::FromHost64(val);
+#ifdef __SSE4_2__
+ const auto kNibbleMask = _mm_set1_epi8(0xf);
+ const auto kHexDigits = _mm_setr_epi8('0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
+ auto v = _mm_loadu_si64(reinterpret_cast<__m128i*>(&be)); // load lo dword
+ auto v4 = _mm_srli_epi64(v, 4); // shift 4 right
+ auto il = _mm_unpacklo_epi8(v4, v); // interleave bytes
+ auto m = _mm_and_si128(il, kNibbleMask); // mask out nibbles
+ auto hexchars = _mm_shuffle_epi8(kHexDigits, m); // hex chars
+ _mm_storeu_si128(reinterpret_cast<__m128i*>(out), hexchars);
+#else
+ for (int i = 0; i < 8; ++i) {
+ auto byte = (be >> (8 * i)) & 0xFF;
+ auto* hex = &absl::numbers_internal::kHexTable[byte * 2];
+ std::memcpy(out + 2 * i, hex, 2);
+ }
+#endif
+ // | 0x1 so that even 0 has 1 digit.
+ return 16 - absl::base_internal::CountLeadingZeros64(val | 0x1) / 4;
+}
+
} // namespace numbers_internal
// SimpleAtoi()