summaryrefslogtreecommitdiff
path: root/absl/hash/internal/hash.h
diff options
context:
space:
mode:
Diffstat (limited to 'absl/hash/internal/hash.h')
-rw-r--r--absl/hash/internal/hash.h53
1 files changed, 38 insertions, 15 deletions
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index ccf4cc1a..ef3f3664 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -56,6 +56,10 @@
#include "absl/types/variant.h"
#include "absl/utility/utility.h"
+#ifdef ABSL_HAVE_STD_STRING_VIEW
+#include <string_view>
+#endif
+
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -424,7 +428,7 @@ H AbslHashValue(H hash_state, std::nullptr_t) {
// AbslHashValue() for hashing pointers-to-member
template <typename H, typename T, typename C>
-H AbslHashValue(H hash_state, T C::* ptr) {
+H AbslHashValue(H hash_state, T C::*ptr) {
auto salient_ptm_size = [](std::size_t n) -> std::size_t {
#if defined(_MSC_VER)
// Pointers-to-member-function on MSVC consist of one pointer plus 0, 1, 2,
@@ -442,8 +446,8 @@ H AbslHashValue(H hash_state, T C::* ptr) {
return n == 24 ? 20 : n == 16 ? 12 : n;
}
#else
- // On other platforms, we assume that pointers-to-members do not have
- // padding.
+ // On other platforms, we assume that pointers-to-members do not have
+ // padding.
#ifdef __cpp_lib_has_unique_object_representations
static_assert(std::has_unique_object_representations<T C::*>::value);
#endif // __cpp_lib_has_unique_object_representations
@@ -516,14 +520,15 @@ H AbslHashValue(H hash_state, const std::shared_ptr<T>& ptr) {
// the same character sequence. These types are:
//
// - `absl::Cord`
-// - `std::string` (and std::basic_string<char, std::char_traits<char>, A> for
-// any allocator A)
-// - `absl::string_view` and `std::string_view`
+// - `std::string` (and std::basic_string<T, std::char_traits<T>, A> for
+// any allocator A and any T in {char, wchar_t, char16_t, char32_t})
+// - `absl::string_view`, `std::string_view`, `std::wstring_view`,
+// `std::u16string_view`, and `std::u32_string_view`.
//
-// For simplicity, we currently support only `char` strings. This support may
-// be broadened, if necessary, but with some caution - this overload would
-// misbehave in cases where the traits' `eq()` member isn't equivalent to `==`
-// on the underlying character type.
+// For simplicity, we currently support only strings built on `char`, `wchar_t`,
+// `char16_t`, or `char32_t`. This support may be broadened, if necessary, but
+// with some caution - this overload would misbehave in cases where the traits'
+// `eq()` member isn't equivalent to `==` on the underlying character type.
template <typename H>
H AbslHashValue(H hash_state, absl::string_view str) {
return H::combine(
@@ -544,6 +549,21 @@ H AbslHashValue(
str.size());
}
+#ifdef ABSL_HAVE_STD_STRING_VIEW
+
+// Support std::wstring_view, std::u16string_view and std::u32string_view.
+template <typename Char, typename H,
+ typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value ||
+ std::is_same<Char, char16_t>::value ||
+ std::is_same<Char, char32_t>::value>>
+H AbslHashValue(H hash_state, std::basic_string_view<Char> str) {
+ return H::combine(
+ H::combine_contiguous(std::move(hash_state), str.data(), str.size()),
+ str.size());
+}
+
+#endif // ABSL_HAVE_STD_STRING_VIEW
+
// -----------------------------------------------------------------------------
// AbslHashValue for Sequence Containers
// -----------------------------------------------------------------------------
@@ -935,8 +955,8 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
#endif // ABSL_HAVE_INTRINSIC_INT128
static constexpr uint64_t kMul =
- sizeof(size_t) == 4 ? uint64_t{0xcc9e2d51}
- : uint64_t{0x9ddfea08eb382d69};
+ sizeof(size_t) == 4 ? uint64_t{0xcc9e2d51}
+ : uint64_t{0x9ddfea08eb382d69};
template <typename T>
using IntegralFastPath =
@@ -969,7 +989,8 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
// The result should be the same as running the whole algorithm, but faster.
template <typename T, absl::enable_if_t<IntegralFastPath<T>::value, int> = 0>
static size_t hash(T value) {
- return static_cast<size_t>(Mix(Seed(), static_cast<uint64_t>(value)));
+ return static_cast<size_t>(
+ Mix(Seed(), static_cast<std::make_unsigned_t<T>>(value)));
}
// Overload of MixingHashState::hash()
@@ -1073,6 +1094,7 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
// Reads 1 to 3 bytes from p. Zero pads to fill uint32_t.
static uint32_t Read1To3(const unsigned char* p, size_t len) {
+ // The trick used by this implementation is to avoid branches if possible.
unsigned char mem0 = p[0];
unsigned char mem1 = p[len / 2];
unsigned char mem2 = p[len - 1];
@@ -1082,7 +1104,7 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
unsigned char significant0 = mem0;
#else
unsigned char significant2 = mem0;
- unsigned char significant1 = mem1;
+ unsigned char significant1 = len == 2 ? mem0 : mem1;
unsigned char significant0 = mem2;
#endif
return static_cast<uint32_t>(significant0 | //
@@ -1135,7 +1157,8 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
// probably per-build and not per-process.
ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Seed() {
#if (!defined(__clang__) || __clang_major__ > 11) && \
- !defined(__apple_build_version__)
+ (!defined(__apple_build_version__) || \
+ __apple_build_version__ >= 19558921) // Xcode 12
return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&kSeed));
#else
// Workaround the absence of