19 #ifndef ABSL_HASH_INTERNAL_HASH_H_
20 #define ABSL_HASH_INTERNAL_HASH_H_
29 #include <forward_list>
39 #include <type_traits>
40 #include <unordered_map>
41 #include <unordered_set>
45 #include "absl/base/config.h"
46 #include "absl/base/internal/unaligned_access.h"
47 #include "absl/base/port.h"
48 #include "absl/container/fixed_array.h"
49 #include "absl/hash/internal/city.h"
51 #include "absl/meta/type_traits.h"
52 #include "absl/numeric/int128.h"
53 #include "absl/strings/string_view.h"
54 #include "absl/types/optional.h"
55 #include "absl/types/variant.h"
56 #include "absl/utility/utility.h"
63 namespace hash_internal {
101 template <
typename H>
104 reinterpret_cast<const unsigned char*
>(
data),
size);
116 template <
typename H>
128 template <
typename T>
197 template <
typename H>
217 template <
typename T,
typename... Ts>
233 template <
typename T>
236 template <
typename I>
241 template <
typename T>
247 template <
typename I>
252 template <
typename InnerH,
typename ElementStateConsumer>
295 template <
typename T,
typename Enable =
void>
309 template <
typename Integral>
311 Integral, typename
std::enable_if<std::is_integral<Integral>::value>
::type>
324 template <
typename H,
typename T>
326 const unsigned char*
start =
reinterpret_cast<const unsigned char*
>(&
value);
343 template <
typename H,
typename B>
347 static_cast<unsigned char>(
value ? 1 : 0));
351 template <
typename H,
typename Enum>
353 H hash_state,
Enum e) {
363 template <
typename H,
typename Float>
376 template <
typename H,
typename LongDouble>
379 const int category = std::fpclassify(
value);
383 hash_state = H::combine(
std::move(hash_state), std::signbit(
value));
400 auto mantissa =
static_cast<double>(std::frexp(
value, &exp));
404 return H::combine(
std::move(hash_state), category);
408 template <
typename H,
typename T>
419 template <
typename H>
421 return H::combine(
std::move(hash_state),
static_cast<void*
>(
nullptr));
425 template <
typename H,
typename T,
typename C>
427 auto salient_ptm_size = [](std::size_t
n) -> std::size_t {
428 #if defined(_MSC_VER)
434 if (
alignof(
T C::*) ==
alignof(
int)) {
441 return n == 24 ? 20 :
n == 16 ? 12 :
n;
446 #ifdef __cpp_lib_has_unique_object_representations
447 static_assert(std::has_unique_object_representations_v<T C::*>);
448 #endif // __cpp_lib_has_unique_object_representations
452 return H::combine_contiguous(
std::move(hash_state),
453 reinterpret_cast<unsigned char*
>(&
ptr),
454 salient_ptm_size(
sizeof ptr));
462 template <
typename H,
typename T1,
typename T2>
466 return H::combine(
std::move(hash_state), p.first, p.second);
473 template <
typename H,
typename Tuple,
size_t... Is>
475 return H::combine(
std::move(hash_state), std::get<Is>(t)...);
479 template <
typename H,
typename... Ts>
480 #if defined(_MSC_VER)
485 typename std::enable_if<absl::conjunction<is_hashable<Ts>...>
::value,
H>
::type
497 template <
typename H,
typename T,
typename D>
503 template <
typename H,
typename T>
526 template <
typename H>
534 template <
typename Char,
typename Alloc,
typename H,
540 const std::basic_string<
Char, std::char_traits<Char>,
Alloc>&
str) {
551 template <
typename H,
typename T,
size_t N>
553 H hash_state,
const std::array<T, N>&
array) {
559 template <
typename H,
typename T,
typename Allocator>
561 H hash_state,
const std::deque<T, Allocator>& deque) {
564 for (
const auto& t : deque) {
565 hash_state = H::combine(
std::move(hash_state), t);
567 return H::combine(
std::move(hash_state), deque.size());
571 template <
typename H,
typename T,
typename Allocator>
573 H hash_state,
const std::forward_list<T, Allocator>& list) {
575 for (
const T& t : list) {
576 hash_state = H::combine(
std::move(hash_state), t);
583 template <
typename H,
typename T,
typename Allocator>
585 H hash_state,
const std::list<T, Allocator>& list) {
586 for (
const auto& t : list) {
587 hash_state = H::combine(
std::move(hash_state), t);
589 return H::combine(
std::move(hash_state), list.size());
597 template <
typename H,
typename T,
typename Allocator>
601 return H::combine(H::combine_contiguous(
std::move(hash_state), vector.data(),
608 #if defined(ABSL_IS_BIG_ENDIAN) && \
609 (defined(__GLIBCXX__) || defined(__GLIBCPP__))
615 template <
typename H,
typename T,
typename Allocator>
618 AbslHashValue(
H hash_state,
const std::vector<T, Allocator>& vector) {
619 typename H::AbslInternalPiecewiseCombiner combiner;
620 for (
const auto& i : vector) {
621 unsigned char c =
static_cast<unsigned char>(
i);
622 hash_state = combiner.add_buffer(
std::move(hash_state), &c,
sizeof(c));
624 return H::combine(combiner.finalize(
std::move(hash_state)), vector.size());
634 template <
typename H,
typename T,
typename Allocator>
639 std::hash<std::vector<T, Allocator>>{}(vector),
649 template <
typename H,
typename Key,
typename T,
typename Compare,
654 for (
const auto& t :
map) {
655 hash_state = H::combine(
std::move(hash_state), t);
661 template <
typename H,
typename Key,
typename T,
typename Compare,
666 const std::multimap<Key, T, Compare, Allocator>&
map) {
667 for (
const auto& t :
map) {
668 hash_state = H::combine(
std::move(hash_state), t);
674 template <
typename H,
typename Key,
typename Compare,
typename Allocator>
676 H hash_state,
const std::set<Key, Compare, Allocator>&
set) {
677 for (
const auto& t :
set) {
678 hash_state = H::combine(
std::move(hash_state), t);
684 template <
typename H,
typename Key,
typename Compare,
typename Allocator>
686 H hash_state,
const std::multiset<Key, Compare, Allocator>&
set) {
687 for (
const auto& t :
set) {
688 hash_state = H::combine(
std::move(hash_state), t);
698 template <
typename H,
typename Key,
typename Hash,
typename KeyEqual,
701 H hash_state,
const std::unordered_set<Key, Hash, KeyEqual, Alloc>& s) {
703 H::combine_unordered(
std::move(hash_state),
s.begin(),
s.end()),
708 template <
typename H,
typename Key,
typename Hash,
typename KeyEqual,
712 const std::unordered_multiset<Key, Hash, KeyEqual, Alloc>& s) {
714 H::combine_unordered(
std::move(hash_state),
s.begin(),
s.end()),
719 template <
typename H,
typename Key,
typename T,
typename Hash,
720 typename KeyEqual,
typename Alloc>
724 const std::unordered_map<Key, T, Hash, KeyEqual, Alloc>& s) {
726 H::combine_unordered(
std::move(hash_state),
s.begin(),
s.end()),
731 template <
typename H,
typename Key,
typename T,
typename Hash,
732 typename KeyEqual,
typename Alloc>
736 const std::unordered_multimap<Key, T, Hash, KeyEqual, Alloc>& s) {
738 H::combine_unordered(
std::move(hash_state),
s.begin(),
s.end()),
747 template <
typename H,
typename T>
749 H hash_state, std::reference_wrapper<T> opt) {
750 return H::combine(
std::move(hash_state), opt.get());
754 template <
typename H,
typename T>
757 if (opt) hash_state = H::combine(
std::move(hash_state), *opt);
762 template <
typename H>
765 template <
typename T>
772 template <
typename H,
typename...
T>
773 typename std::enable_if<conjunction<is_hashable<T>...>
::value,
H>
::type
775 if (!
v.valueless_by_exception()) {
778 return H::combine(
std::move(hash_state),
v.index());
790 #if defined(ABSL_IS_BIG_ENDIAN) && \
791 (defined(__GLIBCXX__) || defined(__GLIBCPP__))
797 template <
typename H,
size_t N>
799 typename H::AbslInternalPiecewiseCombiner combiner;
800 for (
int i = 0;
i <
N;
i++) {
801 unsigned char c =
static_cast<unsigned char>(
set[
i]);
802 hash_state = combiner.add_buffer(
std::move(hash_state), &c,
sizeof(c));
804 return H::combine(combiner.finalize(
std::move(hash_state)),
N);
815 template <
typename H,
typename T>
818 const auto*
bytes =
reinterpret_cast<const unsigned char*
>(
data);
823 template <
typename H,
typename T>
832 #if defined(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE) && \
833 ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
834 #define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 1
836 #define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 0
853 using State::HashStateBase::combine_contiguous;
857 template <
typename H,
typename T>
865 template <
typename H,
typename T>
875 #if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
876 template <
typename H,
typename T>
879 decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>()(
value)),
884 ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>{}(
value));
886 #endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
890 template <
typename H,
typename T>
897 template <
typename Hash,
typename T>
900 template <
typename H,
typename = decltype(
H::Invoke(
901 std::declval<State>(), std::declval<const T&>()))>
903 template <
typename U>
913 template <
typename T>
922 template <
typename T>
924 : std::integral_constant<bool, HashSelect::template Apply<T>::value> {};
930 #ifdef ABSL_HAVE_INTRINSIC_INT128
932 #else // ABSL_HAVE_INTRINSIC_INT128
934 #endif // ABSL_HAVE_INTRINSIC_INT128
937 sizeof(size_t) == 4 ?
uint64_t{0xcc9e2d51}
940 template <
typename T>
941 using IntegralFastPath =
954 const unsigned char*
first,
958 std::integral_constant<
int,
sizeof(
size_t)>{}));
960 using MixingHashState::HashStateBase::combine_contiguous;
985 friend class MixingHashState::HashStateBase;
987 template <
typename CombinerT>
989 CombinerT combiner) {
996 auto element_state = inner_state.
state_;
997 unordered_state += element_state;
998 if (unordered_state < element_state) {
1023 const unsigned char*
first,
size_t len,
1024 std::integral_constant<int, 4>
1027 const unsigned char*
first,
size_t len,
1028 std::integral_constant<int, 8>
1035 const unsigned char*
first,
1038 const unsigned char*
first,
1044 static std::pair<uint64_t, uint64_t>
Read9To16(
const unsigned char* p,
1048 #ifdef ABSL_IS_LITTLE_ENDIAN
1049 uint64_t most_significant = high_mem;
1050 uint64_t least_significant = low_mem;
1052 uint64_t most_significant = low_mem;
1053 uint64_t least_significant = high_mem;
1055 return {least_significant, most_significant >> (128 -
len * 8)};
1062 #ifdef ABSL_IS_LITTLE_ENDIAN
1063 uint32_t most_significant = high_mem;
1064 uint32_t least_significant = low_mem;
1066 uint32_t most_significant = low_mem;
1067 uint32_t least_significant = high_mem;
1069 return (
static_cast<uint64_t>(most_significant) << (
len - 4) * 8) |
1075 unsigned char mem0 = p[0];
1076 unsigned char mem1 = p[
len / 2];
1077 unsigned char mem2 = p[
len - 1];
1078 #ifdef ABSL_IS_LITTLE_ENDIAN
1079 unsigned char significant2 = mem2;
1080 unsigned char significant1 = mem1;
1081 unsigned char significant0 = mem0;
1083 unsigned char significant2 = mem0;
1084 unsigned char significant1 = mem1;
1085 unsigned char significant0 = mem2;
1087 return static_cast<uint32_t>(significant0 |
1088 (significant1 << (
len / 2 * 8)) |
1089 (significant2 << ((
len - 1) * 8)));
1103 return static_cast<uint64_t>(
m ^ (
m >> (
sizeof(
m) * 8 / 2)));
1108 static uint64_t LowLevelHashImpl(
const unsigned char*
data,
size_t len);
1112 #ifdef ABSL_HAVE_INTRINSIC_INT128
1113 return LowLevelHashImpl(
data,
len);
1136 #if (!defined(__clang__) || __clang_major__ > 11) && \
1137 !defined(__apple_build_version__)
1153 std::integral_constant<int, 4> ) {
1162 }
else if (
len >= 4) {
1164 }
else if (
len > 0) {
1176 std::integral_constant<int, 8> ) {
1185 }
else if (
len > 8) {
1189 }
else if (
len >= 4) {
1191 }
else if (
len > 0) {
1213 template <
typename T>
1220 template <
typename T>
1224 template <
typename H>
1225 template <
typename T,
typename... Ts>
1233 template <
typename H>
1234 template <
typename T>
1240 template <
typename H>
1241 template <
typename I>
1244 CombineUnorderedCallback<I>{
begin,
end});
1248 template <
typename H>
1264 data += bytes_needed;
1265 size -= bytes_needed;
1281 template <
typename H>
1291 #endif // ABSL_HASH_INTERNAL_HASH_H_