File indexing completed on 2025-01-18 09:27:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #ifndef ABSL_HASH_INTERNAL_HASH_H_
0020 #define ABSL_HASH_INTERNAL_HASH_H_
0021
0022 #ifdef __APPLE__
0023 #include <Availability.h>
0024 #include <TargetConditionals.h>
0025 #endif
0026
0027 #include "absl/base/config.h"
0028
0029
0030 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
0031 #include <version>
0032 #else
0033 #include <ciso646>
0034 #endif
0035
0036 #include <algorithm>
0037 #include <array>
0038 #include <bitset>
0039 #include <cmath>
0040 #include <cstddef>
0041 #include <cstring>
0042 #include <deque>
0043 #include <forward_list>
0044 #include <functional>
0045 #include <iterator>
0046 #include <limits>
0047 #include <list>
0048 #include <map>
0049 #include <memory>
0050 #include <set>
0051 #include <string>
0052 #include <tuple>
0053 #include <type_traits>
0054 #include <unordered_map>
0055 #include <unordered_set>
0056 #include <utility>
0057 #include <vector>
0058
0059 #include "absl/base/internal/unaligned_access.h"
0060 #include "absl/base/port.h"
0061 #include "absl/container/fixed_array.h"
0062 #include "absl/hash/internal/city.h"
0063 #include "absl/hash/internal/low_level_hash.h"
0064 #include "absl/meta/type_traits.h"
0065 #include "absl/numeric/bits.h"
0066 #include "absl/numeric/int128.h"
0067 #include "absl/strings/string_view.h"
0068 #include "absl/types/optional.h"
0069 #include "absl/types/variant.h"
0070 #include "absl/utility/utility.h"
0071
0072 #if defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L && \
0073 !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
0074 #include <filesystem> // NOLINT
0075 #endif
0076
0077 #ifdef ABSL_HAVE_STD_STRING_VIEW
0078 #include <string_view>
0079 #endif
0080
0081 namespace absl {
0082 ABSL_NAMESPACE_BEGIN
0083
0084 class HashState;
0085
0086 namespace hash_internal {
0087
0088
0089
0090 constexpr size_t PiecewiseChunkSize() { return 1024; }
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 class PiecewiseCombiner {
0113 public:
0114 PiecewiseCombiner() : position_(0) {}
0115 PiecewiseCombiner(const PiecewiseCombiner&) = delete;
0116 PiecewiseCombiner& operator=(const PiecewiseCombiner&) = delete;
0117
0118
0119
0120
0121
0122 template <typename H>
0123 H add_buffer(H state, const unsigned char* data, size_t size);
0124 template <typename H>
0125 H add_buffer(H state, const char* data, size_t size) {
0126 return add_buffer(std::move(state),
0127 reinterpret_cast<const unsigned char*>(data), size);
0128 }
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 template <typename H>
0140 H finalize(H state);
0141
0142 private:
0143 unsigned char buf_[PiecewiseChunkSize()];
0144 size_t position_;
0145 };
0146
0147
0148
0149
0150
0151 template <typename T>
0152 struct is_hashable;
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220 template <typename H>
0221 class HashStateBase {
0222 public:
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240 template <typename T, typename... Ts>
0241 static H combine(H state, const T& value, const Ts&... values);
0242 static H combine(H state) { return state; }
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256 template <typename T>
0257 static H combine_contiguous(H state, const T* data, size_t size);
0258
0259 template <typename I>
0260 static H combine_unordered(H state, I begin, I end);
0261
0262 using AbslInternalPiecewiseCombiner = PiecewiseCombiner;
0263
0264 template <typename T>
0265 using is_hashable = absl::hash_internal::is_hashable<T>;
0266
0267 private:
0268
0269
0270 template <typename I>
0271 struct CombineUnorderedCallback {
0272 I begin;
0273 I end;
0274
0275 template <typename InnerH, typename ElementStateConsumer>
0276 void operator()(InnerH inner_state, ElementStateConsumer cb) {
0277 for (; begin != end; ++begin) {
0278 inner_state = H::combine(std::move(inner_state), *begin);
0279 cb(inner_state);
0280 }
0281 }
0282 };
0283 };
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318 template <typename T, typename Enable = void>
0319 struct is_uniquely_represented : std::false_type {};
0320
0321
0322
0323
0324
0325 template <>
0326 struct is_uniquely_represented<unsigned char> : std::true_type {};
0327
0328
0329
0330
0331
0332 template <typename Integral>
0333 struct is_uniquely_represented<
0334 Integral, typename std::enable_if<std::is_integral<Integral>::value>::type>
0335 : std::true_type {};
0336
0337
0338
0339
0340 template <>
0341 struct is_uniquely_represented<bool> : std::false_type {};
0342
0343
0344
0345
0346
0347 template <typename H, typename T>
0348 H hash_bytes(H hash_state, const T& value) {
0349 const unsigned char* start = reinterpret_cast<const unsigned char*>(&value);
0350 return H::combine_contiguous(std::move(hash_state), start, sizeof(value));
0351 }
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366 template <typename H, typename B>
0367 typename std::enable_if<std::is_same<B, bool>::value, H>::type AbslHashValue(
0368 H hash_state, B value) {
0369 return H::combine(std::move(hash_state),
0370 static_cast<unsigned char>(value ? 1 : 0));
0371 }
0372
0373
0374 template <typename H, typename Enum>
0375 typename std::enable_if<std::is_enum<Enum>::value, H>::type AbslHashValue(
0376 H hash_state, Enum e) {
0377
0378
0379
0380
0381
0382 return H::combine(std::move(hash_state),
0383 static_cast<typename std::underlying_type<Enum>::type>(e));
0384 }
0385
0386 template <typename H, typename Float>
0387 typename std::enable_if<std::is_same<Float, float>::value ||
0388 std::is_same<Float, double>::value,
0389 H>::type
0390 AbslHashValue(H hash_state, Float value) {
0391 return hash_internal::hash_bytes(std::move(hash_state),
0392 value == 0 ? 0 : value);
0393 }
0394
0395
0396
0397
0398
0399 template <typename H, typename LongDouble>
0400 typename std::enable_if<std::is_same<LongDouble, long double>::value, H>::type
0401 AbslHashValue(H hash_state, LongDouble value) {
0402 const int category = std::fpclassify(value);
0403 switch (category) {
0404 case FP_INFINITE:
0405
0406 hash_state = H::combine(std::move(hash_state), std::signbit(value));
0407 break;
0408
0409 case FP_NAN:
0410 case FP_ZERO:
0411 default:
0412
0413 break;
0414
0415 case FP_NORMAL:
0416 case FP_SUBNORMAL:
0417
0418
0419
0420
0421
0422 int exp;
0423 auto mantissa = static_cast<double>(std::frexp(value, &exp));
0424 hash_state = H::combine(std::move(hash_state), mantissa, exp);
0425 }
0426
0427 return H::combine(std::move(hash_state), category);
0428 }
0429
0430
0431
0432 template <typename H, typename T, size_t N>
0433 H AbslHashValue(H hash_state, T (&)[N]) {
0434 static_assert(
0435 sizeof(T) == -1,
0436 "Hashing C arrays is not allowed. For string literals, wrap the literal "
0437 "in absl::string_view(). To hash the array contents, use "
0438 "absl::MakeSpan() or make the array an std::array. To hash the array "
0439 "address, use &array[0].");
0440 return hash_state;
0441 }
0442
0443
0444 template <typename H, typename T>
0445 std::enable_if_t<std::is_pointer<T>::value, H> AbslHashValue(H hash_state,
0446 T ptr) {
0447 auto v = reinterpret_cast<uintptr_t>(ptr);
0448
0449
0450
0451
0452 return H::combine(std::move(hash_state), v, v);
0453 }
0454
0455
0456 template <typename H>
0457 H AbslHashValue(H hash_state, std::nullptr_t) {
0458 return H::combine(std::move(hash_state), static_cast<void*>(nullptr));
0459 }
0460
0461
0462 template <typename H, typename T, typename C>
0463 H AbslHashValue(H hash_state, T C::*ptr) {
0464 auto salient_ptm_size = [](std::size_t n) -> std::size_t {
0465 #if defined(_MSC_VER)
0466
0467
0468
0469
0470
0471 if (alignof(T C::*) == alignof(int)) {
0472
0473
0474 return n;
0475 } else {
0476
0477
0478 return n == 24 ? 20 : n == 16 ? 12 : n;
0479 }
0480 #else
0481
0482
0483 #ifdef __cpp_lib_has_unique_object_representations
0484 static_assert(std::has_unique_object_representations<T C::*>::value);
0485 #endif
0486 return n;
0487 #endif
0488 };
0489 return H::combine_contiguous(std::move(hash_state),
0490 reinterpret_cast<unsigned char*>(&ptr),
0491 salient_ptm_size(sizeof ptr));
0492 }
0493
0494
0495
0496
0497
0498
0499 template <typename H, typename T1, typename T2>
0500 typename std::enable_if<is_hashable<T1>::value && is_hashable<T2>::value,
0501 H>::type
0502 AbslHashValue(H hash_state, const std::pair<T1, T2>& p) {
0503 return H::combine(std::move(hash_state), p.first, p.second);
0504 }
0505
0506
0507
0508
0509
0510 template <typename H, typename Tuple, size_t... Is>
0511 H hash_tuple(H hash_state, const Tuple& t, absl::index_sequence<Is...>) {
0512 return H::combine(std::move(hash_state), std::get<Is>(t)...);
0513 }
0514
0515
0516 template <typename H, typename... Ts>
0517 #if defined(_MSC_VER)
0518
0519
0520 H
0521 #else
0522 typename std::enable_if<absl::conjunction<is_hashable<Ts>...>::value, H>::type
0523 #endif
0524 AbslHashValue(H hash_state, const std::tuple<Ts...>& t) {
0525 return hash_internal::hash_tuple(std::move(hash_state), t,
0526 absl::make_index_sequence<sizeof...(Ts)>());
0527 }
0528
0529
0530
0531
0532
0533
0534 template <typename H, typename T, typename D>
0535 H AbslHashValue(H hash_state, const std::unique_ptr<T, D>& ptr) {
0536 return H::combine(std::move(hash_state), ptr.get());
0537 }
0538
0539
0540 template <typename H, typename T>
0541 H AbslHashValue(H hash_state, const std::shared_ptr<T>& ptr) {
0542 return H::combine(std::move(hash_state), ptr.get());
0543 }
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564 template <typename H>
0565 H AbslHashValue(H hash_state, absl::string_view str) {
0566 return H::combine(
0567 H::combine_contiguous(std::move(hash_state), str.data(), str.size()),
0568 str.size());
0569 }
0570
0571
0572 template <typename Char, typename Alloc, typename H,
0573 typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value ||
0574 std::is_same<Char, char16_t>::value ||
0575 std::is_same<Char, char32_t>::value>>
0576 H AbslHashValue(
0577 H hash_state,
0578 const std::basic_string<Char, std::char_traits<Char>, Alloc>& str) {
0579 return H::combine(
0580 H::combine_contiguous(std::move(hash_state), str.data(), str.size()),
0581 str.size());
0582 }
0583
0584 #ifdef ABSL_HAVE_STD_STRING_VIEW
0585
0586
0587 template <typename Char, typename H,
0588 typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value ||
0589 std::is_same<Char, char16_t>::value ||
0590 std::is_same<Char, char32_t>::value>>
0591 H AbslHashValue(H hash_state, std::basic_string_view<Char> str) {
0592 return H::combine(
0593 H::combine_contiguous(std::move(hash_state), str.data(), str.size()),
0594 str.size());
0595 }
0596
0597 #endif
0598
0599 #if defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L && \
0600 !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) && \
0601 (!defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) || \
0602 __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 130000) && \
0603 (!defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \
0604 __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101500)
0605
0606 #define ABSL_INTERNAL_STD_FILESYSTEM_PATH_HASH_AVAILABLE 1
0607
0608
0609
0610 template <typename Path, typename H,
0611 typename = absl::enable_if_t<
0612 std::is_same_v<Path, std::filesystem::path>>>
0613 H AbslHashValue(H hash_state, const Path& path) {
0614
0615
0616
0617
0618
0619 return H::combine(std::move(hash_state), std::filesystem::hash_value(path));
0620 }
0621
0622 #endif
0623
0624
0625
0626
0627
0628
0629 template <typename H, typename T, size_t N>
0630 typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(
0631 H hash_state, const std::array<T, N>& array) {
0632 return H::combine_contiguous(std::move(hash_state), array.data(),
0633 array.size());
0634 }
0635
0636
0637 template <typename H, typename T, typename Allocator>
0638 typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(
0639 H hash_state, const std::deque<T, Allocator>& deque) {
0640
0641
0642 for (const auto& t : deque) {
0643 hash_state = H::combine(std::move(hash_state), t);
0644 }
0645 return H::combine(std::move(hash_state), deque.size());
0646 }
0647
0648
0649 template <typename H, typename T, typename Allocator>
0650 typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(
0651 H hash_state, const std::forward_list<T, Allocator>& list) {
0652 size_t size = 0;
0653 for (const T& t : list) {
0654 hash_state = H::combine(std::move(hash_state), t);
0655 ++size;
0656 }
0657 return H::combine(std::move(hash_state), size);
0658 }
0659
0660
0661 template <typename H, typename T, typename Allocator>
0662 typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(
0663 H hash_state, const std::list<T, Allocator>& list) {
0664 for (const auto& t : list) {
0665 hash_state = H::combine(std::move(hash_state), t);
0666 }
0667 return H::combine(std::move(hash_state), list.size());
0668 }
0669
0670
0671
0672
0673
0674
0675 template <typename H, typename T, typename Allocator>
0676 typename std::enable_if<is_hashable<T>::value && !std::is_same<T, bool>::value,
0677 H>::type
0678 AbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) {
0679 return H::combine(H::combine_contiguous(std::move(hash_state), vector.data(),
0680 vector.size()),
0681 vector.size());
0682 }
0683
0684
0685
0686 #if defined(ABSL_IS_BIG_ENDIAN) && \
0687 (defined(__GLIBCXX__) || defined(__GLIBCPP__))
0688
0689
0690
0691
0692
0693 template <typename H, typename T, typename Allocator>
0694 typename std::enable_if<is_hashable<T>::value && std::is_same<T, bool>::value,
0695 H>::type
0696 AbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) {
0697 typename H::AbslInternalPiecewiseCombiner combiner;
0698 for (const auto& i : vector) {
0699 unsigned char c = static_cast<unsigned char>(i);
0700 hash_state = combiner.add_buffer(std::move(hash_state), &c, sizeof(c));
0701 }
0702 return H::combine(combiner.finalize(std::move(hash_state)), vector.size());
0703 }
0704 #else
0705
0706
0707
0708
0709
0710
0711
0712 template <typename H, typename T, typename Allocator>
0713 typename std::enable_if<is_hashable<T>::value && std::is_same<T, bool>::value,
0714 H>::type
0715 AbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) {
0716 return H::combine(std::move(hash_state),
0717 std::hash<std::vector<T, Allocator>>{}(vector),
0718 vector.size());
0719 }
0720 #endif
0721
0722
0723
0724
0725
0726
0727 template <typename H, typename Key, typename T, typename Compare,
0728 typename Allocator>
0729 typename std::enable_if<is_hashable<Key>::value && is_hashable<T>::value,
0730 H>::type
0731 AbslHashValue(H hash_state, const std::map<Key, T, Compare, Allocator>& map) {
0732 for (const auto& t : map) {
0733 hash_state = H::combine(std::move(hash_state), t);
0734 }
0735 return H::combine(std::move(hash_state), map.size());
0736 }
0737
0738
0739 template <typename H, typename Key, typename T, typename Compare,
0740 typename Allocator>
0741 typename std::enable_if<is_hashable<Key>::value && is_hashable<T>::value,
0742 H>::type
0743 AbslHashValue(H hash_state,
0744 const std::multimap<Key, T, Compare, Allocator>& map) {
0745 for (const auto& t : map) {
0746 hash_state = H::combine(std::move(hash_state), t);
0747 }
0748 return H::combine(std::move(hash_state), map.size());
0749 }
0750
0751
0752 template <typename H, typename Key, typename Compare, typename Allocator>
0753 typename std::enable_if<is_hashable<Key>::value, H>::type AbslHashValue(
0754 H hash_state, const std::set<Key, Compare, Allocator>& set) {
0755 for (const auto& t : set) {
0756 hash_state = H::combine(std::move(hash_state), t);
0757 }
0758 return H::combine(std::move(hash_state), set.size());
0759 }
0760
0761
0762 template <typename H, typename Key, typename Compare, typename Allocator>
0763 typename std::enable_if<is_hashable<Key>::value, H>::type AbslHashValue(
0764 H hash_state, const std::multiset<Key, Compare, Allocator>& set) {
0765 for (const auto& t : set) {
0766 hash_state = H::combine(std::move(hash_state), t);
0767 }
0768 return H::combine(std::move(hash_state), set.size());
0769 }
0770
0771
0772
0773
0774
0775
0776 template <typename H, typename Key, typename Hash, typename KeyEqual,
0777 typename Alloc>
0778 typename std::enable_if<is_hashable<Key>::value, H>::type AbslHashValue(
0779 H hash_state, const std::unordered_set<Key, Hash, KeyEqual, Alloc>& s) {
0780 return H::combine(
0781 H::combine_unordered(std::move(hash_state), s.begin(), s.end()),
0782 s.size());
0783 }
0784
0785
0786 template <typename H, typename Key, typename Hash, typename KeyEqual,
0787 typename Alloc>
0788 typename std::enable_if<is_hashable<Key>::value, H>::type AbslHashValue(
0789 H hash_state,
0790 const std::unordered_multiset<Key, Hash, KeyEqual, Alloc>& s) {
0791 return H::combine(
0792 H::combine_unordered(std::move(hash_state), s.begin(), s.end()),
0793 s.size());
0794 }
0795
0796
0797 template <typename H, typename Key, typename T, typename Hash,
0798 typename KeyEqual, typename Alloc>
0799 typename std::enable_if<is_hashable<Key>::value && is_hashable<T>::value,
0800 H>::type
0801 AbslHashValue(H hash_state,
0802 const std::unordered_map<Key, T, Hash, KeyEqual, Alloc>& s) {
0803 return H::combine(
0804 H::combine_unordered(std::move(hash_state), s.begin(), s.end()),
0805 s.size());
0806 }
0807
0808
0809 template <typename H, typename Key, typename T, typename Hash,
0810 typename KeyEqual, typename Alloc>
0811 typename std::enable_if<is_hashable<Key>::value && is_hashable<T>::value,
0812 H>::type
0813 AbslHashValue(H hash_state,
0814 const std::unordered_multimap<Key, T, Hash, KeyEqual, Alloc>& s) {
0815 return H::combine(
0816 H::combine_unordered(std::move(hash_state), s.begin(), s.end()),
0817 s.size());
0818 }
0819
0820
0821
0822
0823
0824
0825 template <typename H, typename T>
0826 typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(
0827 H hash_state, std::reference_wrapper<T> opt) {
0828 return H::combine(std::move(hash_state), opt.get());
0829 }
0830
0831
0832 template <typename H, typename T>
0833 typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(
0834 H hash_state, const absl::optional<T>& opt) {
0835 if (opt) hash_state = H::combine(std::move(hash_state), *opt);
0836 return H::combine(std::move(hash_state), opt.has_value());
0837 }
0838
0839
0840 template <typename H>
0841 struct VariantVisitor {
0842 H&& hash_state;
0843 template <typename T>
0844 H operator()(const T& t) const {
0845 return H::combine(std::move(hash_state), t);
0846 }
0847 };
0848
0849
0850 template <typename H, typename... T>
0851 typename std::enable_if<conjunction<is_hashable<T>...>::value, H>::type
0852 AbslHashValue(H hash_state, const absl::variant<T...>& v) {
0853 if (!v.valueless_by_exception()) {
0854 hash_state = absl::visit(VariantVisitor<H>{std::move(hash_state)}, v);
0855 }
0856 return H::combine(std::move(hash_state), v.index());
0857 }
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868 #if defined(ABSL_IS_BIG_ENDIAN) && \
0869 (defined(__GLIBCXX__) || defined(__GLIBCPP__))
0870
0871
0872
0873
0874
0875 template <typename H, size_t N>
0876 H AbslHashValue(H hash_state, const std::bitset<N>& set) {
0877 typename H::AbslInternalPiecewiseCombiner combiner;
0878 for (size_t i = 0; i < N; i++) {
0879 unsigned char c = static_cast<unsigned char>(set[i]);
0880 hash_state = combiner.add_buffer(std::move(hash_state), &c, sizeof(c));
0881 }
0882 return H::combine(combiner.finalize(std::move(hash_state)), N);
0883 }
0884 #endif
0885
0886
0887
0888
0889
0890
0891
0892
0893 template <typename H, typename T>
0894 typename std::enable_if<is_uniquely_represented<T>::value, H>::type
0895 hash_range_or_bytes(H hash_state, const T* data, size_t size) {
0896 const auto* bytes = reinterpret_cast<const unsigned char*>(data);
0897 return H::combine_contiguous(std::move(hash_state), bytes, sizeof(T) * size);
0898 }
0899
0900
0901 template <typename H, typename T>
0902 typename std::enable_if<!is_uniquely_represented<T>::value, H>::type
0903 hash_range_or_bytes(H hash_state, const T* data, size_t size) {
0904 for (const auto end = data + size; data < end; ++data) {
0905 hash_state = H::combine(std::move(hash_state), *data);
0906 }
0907 return hash_state;
0908 }
0909
0910 #if defined(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE) && \
0911 ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
0912 #define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 1
0913 #else
0914 #define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 0
0915 #endif
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926 struct HashSelect {
0927 private:
0928 struct State : HashStateBase<State> {
0929 static State combine_contiguous(State hash_state, const unsigned char*,
0930 size_t);
0931 using State::HashStateBase::combine_contiguous;
0932 };
0933
0934 struct UniquelyRepresentedProbe {
0935 template <typename H, typename T>
0936 static auto Invoke(H state, const T& value)
0937 -> absl::enable_if_t<is_uniquely_represented<T>::value, H> {
0938 return hash_internal::hash_bytes(std::move(state), value);
0939 }
0940 };
0941
0942 struct HashValueProbe {
0943 template <typename H, typename T>
0944 static auto Invoke(H state, const T& value) -> absl::enable_if_t<
0945 std::is_same<H,
0946 decltype(AbslHashValue(std::move(state), value))>::value,
0947 H> {
0948 return AbslHashValue(std::move(state), value);
0949 }
0950 };
0951
0952 struct LegacyHashProbe {
0953 #if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
0954 template <typename H, typename T>
0955 static auto Invoke(H state, const T& value) -> absl::enable_if_t<
0956 std::is_convertible<
0957 decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>()(value)),
0958 size_t>::value,
0959 H> {
0960 return hash_internal::hash_bytes(
0961 std::move(state),
0962 ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>{}(value));
0963 }
0964 #endif
0965 };
0966
0967 struct StdHashProbe {
0968 template <typename H, typename T>
0969 static auto Invoke(H state, const T& value)
0970 -> absl::enable_if_t<type_traits_internal::IsHashable<T>::value, H> {
0971 return hash_internal::hash_bytes(std::move(state), std::hash<T>{}(value));
0972 }
0973 };
0974
0975 template <typename Hash, typename T>
0976 struct Probe : Hash {
0977 private:
0978 template <typename H, typename = decltype(H::Invoke(
0979 std::declval<State>(), std::declval<const T&>()))>
0980 static std::true_type Test(int);
0981 template <typename U>
0982 static std::false_type Test(char);
0983
0984 public:
0985 static constexpr bool value = decltype(Test<Hash>(0))::value;
0986 };
0987
0988 public:
0989
0990
0991 template <typename T>
0992 using Apply = absl::disjunction<
0993 Probe<UniquelyRepresentedProbe, T>,
0994 Probe<HashValueProbe, T>,
0995 Probe<LegacyHashProbe, T>,
0996 Probe<StdHashProbe, T>,
0997 std::false_type>;
0998 };
0999
1000 template <typename T>
1001 struct is_hashable
1002 : std::integral_constant<bool, HashSelect::template Apply<T>::value> {};
1003
1004
1005 class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
1006
1007
1008 #ifdef ABSL_HAVE_INTRINSIC_INT128
1009 using uint128 = __uint128_t;
1010 #else
1011 using uint128 = absl::uint128;
1012 #endif
1013
1014 static constexpr uint64_t kMul =
1015 sizeof(size_t) == 4 ? uint64_t{0xcc9e2d51}
1016 : uint64_t{0x9ddfea08eb382d69};
1017
1018 template <typename T>
1019 using IntegralFastPath =
1020 conjunction<std::is_integral<T>, is_uniquely_represented<T>>;
1021
1022 public:
1023
1024 MixingHashState(MixingHashState&&) = default;
1025 MixingHashState& operator=(MixingHashState&&) = default;
1026
1027
1028
1029
1030
1031 static MixingHashState combine_contiguous(MixingHashState hash_state,
1032 const unsigned char* first,
1033 size_t size) {
1034 return MixingHashState(
1035 CombineContiguousImpl(hash_state.state_, first, size,
1036 std::integral_constant<int, sizeof(size_t)>{}));
1037 }
1038 using MixingHashState::HashStateBase::combine_contiguous;
1039
1040
1041
1042
1043
1044
1045
1046
1047 template <typename T, absl::enable_if_t<IntegralFastPath<T>::value, int> = 0>
1048 static size_t hash(T value) {
1049 return static_cast<size_t>(
1050 Mix(Seed(), static_cast<std::make_unsigned_t<T>>(value)));
1051 }
1052
1053
1054 template <typename T, absl::enable_if_t<!IntegralFastPath<T>::value, int> = 0>
1055 static size_t hash(const T& value) {
1056 return static_cast<size_t>(combine(MixingHashState{}, value).state_);
1057 }
1058
1059 private:
1060
1061
1062 MixingHashState() : state_(Seed()) {}
1063
1064 friend class MixingHashState::HashStateBase;
1065
1066 template <typename CombinerT>
1067 static MixingHashState RunCombineUnordered(MixingHashState state,
1068 CombinerT combiner) {
1069 uint64_t unordered_state = 0;
1070 combiner(MixingHashState{}, [&](MixingHashState& inner_state) {
1071
1072
1073
1074
1075 auto element_state = inner_state.state_;
1076 unordered_state += element_state;
1077 if (unordered_state < element_state) {
1078 ++unordered_state;
1079 }
1080 inner_state = MixingHashState{};
1081 });
1082 return MixingHashState::combine(std::move(state), unordered_state);
1083 }
1084
1085
1086
1087 friend class absl::HashState;
1088
1089
1090
1091
1092
1093 MixingHashState(const MixingHashState&) = default;
1094
1095 explicit MixingHashState(uint64_t state) : state_(state) {}
1096
1097
1098
1099
1100
1101 static uint64_t CombineContiguousImpl(uint64_t state,
1102 const unsigned char* first, size_t len,
1103 std::integral_constant<int, 4>
1104 );
1105 static uint64_t CombineContiguousImpl(uint64_t state,
1106 const unsigned char* first, size_t len,
1107 std::integral_constant<int, 8>
1108 );
1109
1110
1111
1112
1113 static uint64_t CombineLargeContiguousImpl32(uint64_t state,
1114 const unsigned char* first,
1115 size_t len);
1116 static uint64_t CombineLargeContiguousImpl64(uint64_t state,
1117 const unsigned char* first,
1118 size_t len);
1119
1120
1121
1122
1123 static std::pair<uint64_t, uint64_t> Read9To16(const unsigned char* p,
1124 size_t len) {
1125 uint64_t low_mem = absl::base_internal::UnalignedLoad64(p);
1126 uint64_t high_mem = absl::base_internal::UnalignedLoad64(p + len - 8);
1127 #ifdef ABSL_IS_LITTLE_ENDIAN
1128 uint64_t most_significant = high_mem;
1129 uint64_t least_significant = low_mem;
1130 #else
1131 uint64_t most_significant = low_mem;
1132 uint64_t least_significant = high_mem;
1133 #endif
1134 return {least_significant, most_significant};
1135 }
1136
1137
1138 static uint64_t Read4To8(const unsigned char* p, size_t len) {
1139 uint32_t low_mem = absl::base_internal::UnalignedLoad32(p);
1140 uint32_t high_mem = absl::base_internal::UnalignedLoad32(p + len - 4);
1141 #ifdef ABSL_IS_LITTLE_ENDIAN
1142 uint32_t most_significant = high_mem;
1143 uint32_t least_significant = low_mem;
1144 #else
1145 uint32_t most_significant = low_mem;
1146 uint32_t least_significant = high_mem;
1147 #endif
1148 return (static_cast<uint64_t>(most_significant) << (len - 4) * 8) |
1149 least_significant;
1150 }
1151
1152
1153 static uint32_t Read1To3(const unsigned char* p, size_t len) {
1154
1155 unsigned char mem0 = p[0];
1156 unsigned char mem1 = p[len / 2];
1157 unsigned char mem2 = p[len - 1];
1158 #ifdef ABSL_IS_LITTLE_ENDIAN
1159 unsigned char significant2 = mem2;
1160 unsigned char significant1 = mem1;
1161 unsigned char significant0 = mem0;
1162 #else
1163 unsigned char significant2 = mem0;
1164 unsigned char significant1 = len == 2 ? mem0 : mem1;
1165 unsigned char significant0 = mem2;
1166 #endif
1167 return static_cast<uint32_t>(significant0 |
1168 (significant1 << (len / 2 * 8)) |
1169 (significant2 << ((len - 1) * 8)));
1170 }
1171
1172 ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Mix(uint64_t state, uint64_t v) {
1173
1174
1175 using MultType =
1176 absl::conditional_t<sizeof(size_t) == 4, uint64_t, uint128>;
1177
1178
1179
1180
1181 MultType m = state + v;
1182 m *= kMul;
1183 return static_cast<uint64_t>(m ^ (m >> (sizeof(m) * 8 / 2)));
1184 }
1185
1186
1187
1188 static uint64_t LowLevelHashImpl(const unsigned char* data, size_t len);
1189
1190 ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Hash64(const unsigned char* data,
1191 size_t len) {
1192 #ifdef ABSL_HAVE_INTRINSIC_INT128
1193 return LowLevelHashImpl(data, len);
1194 #else
1195 return hash_internal::CityHash64(reinterpret_cast<const char*>(data), len);
1196 #endif
1197 }
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215 ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Seed() {
1216 #if (!defined(__clang__) || __clang_major__ > 11) && \
1217 (!defined(__apple_build_version__) || \
1218 __apple_build_version__ >= 19558921)
1219 return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&kSeed));
1220 #else
1221
1222
1223 return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(kSeed));
1224 #endif
1225 }
1226 static const void* const kSeed;
1227
1228 uint64_t state_;
1229 };
1230
1231
1232 inline uint64_t MixingHashState::CombineContiguousImpl(
1233 uint64_t state, const unsigned char* first, size_t len,
1234 std::integral_constant<int, 4> ) {
1235
1236
1237 uint64_t v;
1238 if (len > 8) {
1239 if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) {
1240 return CombineLargeContiguousImpl32(state, first, len);
1241 }
1242 v = hash_internal::CityHash32(reinterpret_cast<const char*>(first), len);
1243 } else if (len >= 4) {
1244 v = Read4To8(first, len);
1245 } else if (len > 0) {
1246 v = Read1To3(first, len);
1247 } else {
1248
1249 return state;
1250 }
1251 return Mix(state, v);
1252 }
1253
1254
1255 inline uint64_t MixingHashState::CombineContiguousImpl(
1256 uint64_t state, const unsigned char* first, size_t len,
1257 std::integral_constant<int, 8> ) {
1258
1259
1260 uint64_t v;
1261 if (len > 16) {
1262 if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) {
1263 return CombineLargeContiguousImpl64(state, first, len);
1264 }
1265 v = Hash64(first, len);
1266 } else if (len > 8) {
1267
1268
1269
1270
1271 auto p = Read9To16(first, len);
1272 uint64_t lo = p.first;
1273 uint64_t hi = p.second;
1274
1275
1276 lo = absl::rotr(lo, 53);
1277 state += kMul;
1278 lo += state;
1279 state ^= hi;
1280 uint128 m = state;
1281 m *= lo;
1282 return static_cast<uint64_t>(m ^ (m >> 64));
1283 } else if (len >= 4) {
1284 v = Read4To8(first, len);
1285 } else if (len > 0) {
1286 v = Read1To3(first, len);
1287 } else {
1288
1289 return state;
1290 }
1291 return Mix(state, v);
1292 }
1293
1294 struct AggregateBarrier {};
1295
1296
1297
1298
1299
1300
1301 struct PoisonedHash : private AggregateBarrier {
1302 PoisonedHash() = delete;
1303 PoisonedHash(const PoisonedHash&) = delete;
1304 PoisonedHash& operator=(const PoisonedHash&) = delete;
1305 };
1306
1307 template <typename T>
1308 struct HashImpl {
1309 size_t operator()(const T& value) const {
1310 return MixingHashState::hash(value);
1311 }
1312 };
1313
1314 template <typename T>
1315 struct Hash
1316 : absl::conditional_t<is_hashable<T>::value, HashImpl<T>, PoisonedHash> {};
1317
1318 template <typename H>
1319 template <typename T, typename... Ts>
1320 H HashStateBase<H>::combine(H state, const T& value, const Ts&... values) {
1321 return H::combine(hash_internal::HashSelect::template Apply<T>::Invoke(
1322 std::move(state), value),
1323 values...);
1324 }
1325
1326
1327 template <typename H>
1328 template <typename T>
1329 H HashStateBase<H>::combine_contiguous(H state, const T* data, size_t size) {
1330 return hash_internal::hash_range_or_bytes(std::move(state), data, size);
1331 }
1332
1333
1334 template <typename H>
1335 template <typename I>
1336 H HashStateBase<H>::combine_unordered(H state, I begin, I end) {
1337 return H::RunCombineUnordered(std::move(state),
1338 CombineUnorderedCallback<I>{begin, end});
1339 }
1340
1341
1342 template <typename H>
1343 H PiecewiseCombiner::add_buffer(H state, const unsigned char* data,
1344 size_t size) {
1345 if (position_ + size < PiecewiseChunkSize()) {
1346
1347 memcpy(buf_ + position_, data, size);
1348 position_ += size;
1349 return state;
1350 }
1351
1352
1353
1354 if (position_ != 0) {
1355 const size_t bytes_needed = PiecewiseChunkSize() - position_;
1356 memcpy(buf_ + position_, data, bytes_needed);
1357 state = H::combine_contiguous(std::move(state), buf_, PiecewiseChunkSize());
1358 data += bytes_needed;
1359 size -= bytes_needed;
1360 }
1361
1362
1363 while (size >= PiecewiseChunkSize()) {
1364 state = H::combine_contiguous(std::move(state), data, PiecewiseChunkSize());
1365 data += PiecewiseChunkSize();
1366 size -= PiecewiseChunkSize();
1367 }
1368
1369 memcpy(buf_, data, size);
1370 position_ = size;
1371 return state;
1372 }
1373
1374
1375 template <typename H>
1376 H PiecewiseCombiner::finalize(H state) {
1377
1378 return H::combine_contiguous(std::move(state), buf_, position_);
1379 }
1380
1381 }
1382 ABSL_NAMESPACE_END
1383 }
1384
1385 #endif