|
|
|
@ -213,7 +213,7 @@ struct TransparentSupport { |
|
|
|
|
// We hash all the scalars as uint64_t so that we can implement the same hash
|
|
|
|
|
// function for VariantKey. This way we can have MapKey provide the same hash
|
|
|
|
|
// as the underlying value would have.
|
|
|
|
|
using hash = std::hash< |
|
|
|
|
using hash = absl::Hash< |
|
|
|
|
std::conditional_t<std::is_scalar<key_type>::value, uint64_t, key_type>>; |
|
|
|
|
|
|
|
|
|
static bool Equals(const key_type& a, const key_type& b) { return a == b; } |
|
|
|
@ -227,7 +227,7 @@ struct TransparentSupport { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// We add transparent support for std::string keys. We use
|
|
|
|
|
// std::hash<absl::string_view> as it supports the input types we care about.
|
|
|
|
|
// absl::Hash<absl::string_view> as it supports the input types we care about.
|
|
|
|
|
// The lookup functions accept arbitrary `K`. This will include any key type
|
|
|
|
|
// that is convertible to absl::string_view.
|
|
|
|
|
template <> |
|
|
|
@ -350,12 +350,6 @@ struct VariantKey { |
|
|
|
|
if (data == nullptr) data = ""; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size_t Hash() const { |
|
|
|
|
return data == nullptr ? std::hash<uint64_t>{}(integral) |
|
|
|
|
: absl::Hash<absl::string_view>{}( |
|
|
|
|
absl::string_view(data, integral)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
friend bool operator<(const VariantKey& left, const VariantKey& right) { |
|
|
|
|
ABSL_DCHECK_EQ(left.data == nullptr, right.data == nullptr); |
|
|
|
|
if (left.integral != right.integral) { |
|
|
|
@ -378,6 +372,15 @@ struct RealKeyToVariantKey { |
|
|
|
|
VariantKey operator()(T value) const { return VariantKey(value); } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
template <typename T, typename = void> |
|
|
|
|
struct RealKeyToVariantKeyAlternative; |
|
|
|
|
|
|
|
|
|
template <typename T> |
|
|
|
|
struct RealKeyToVariantKeyAlternative< |
|
|
|
|
T, typename std::enable_if<std::is_integral<T>::value>::type> { |
|
|
|
|
uint64_t operator()(uint64_t value) const { return value; } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
template <> |
|
|
|
|
struct RealKeyToVariantKey<std::string> { |
|
|
|
|
template <typename T> |
|
|
|
@ -386,6 +389,11 @@ struct RealKeyToVariantKey<std::string> { |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
template <> |
|
|
|
|
struct RealKeyToVariantKeyAlternative<std::string> { |
|
|
|
|
absl::string_view operator()(absl::string_view value) const { return value; } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// We use a single kind of tree for all maps. This reduces code duplication.
|
|
|
|
|
using TreeForMap = |
|
|
|
|
absl::btree_map<VariantKey, NodeBase*, std::less<VariantKey>, |
|
|
|
@ -689,13 +697,21 @@ class PROTOBUF_EXPORT UntypedMapBase { |
|
|
|
|
TableEntryPtr ConvertToTree(NodeBase* node, GetKey get_key); |
|
|
|
|
void EraseFromTree(map_index_t b, typename Tree::iterator tree_it); |
|
|
|
|
|
|
|
|
|
map_index_t VariantBucketNumber(VariantKey key) const; |
|
|
|
|
map_index_t VariantBucketNumber(VariantKey key) const { |
|
|
|
|
return key.data == nullptr |
|
|
|
|
? VariantBucketNumber(key.integral) |
|
|
|
|
: VariantBucketNumber(absl::string_view( |
|
|
|
|
key.data, static_cast<size_t>(key.integral))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
map_index_t VariantBucketNumber(absl::string_view key) const { |
|
|
|
|
return static_cast<map_index_t>(absl::HashOf(seed_, key) & |
|
|
|
|
(num_buckets_ - 1)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
map_index_t BucketNumberFromHash(uint64_t h) const { |
|
|
|
|
// We xor the hash value against the random seed so that we effectively
|
|
|
|
|
// have a random hash function.
|
|
|
|
|
// We use absl::Hash to do bit mixing for uniform bucket selection.
|
|
|
|
|
return absl::HashOf(h ^ seed_) & (num_buckets_ - 1); |
|
|
|
|
map_index_t VariantBucketNumber(uint64_t key) const { |
|
|
|
|
return static_cast<map_index_t>(absl::HashOf(key ^ seed_) & |
|
|
|
|
(num_buckets_ - 1)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TableEntryPtr* CreateEmptyTable(map_index_t n) { |
|
|
|
@ -1106,9 +1122,10 @@ class KeyMapBase : public UntypedMapBase { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
map_index_t BucketNumber(typename TS::ViewType k) const { |
|
|
|
|
ABSL_DCHECK_EQ(BucketNumberFromHash(hash_function()(k)), |
|
|
|
|
VariantBucketNumber(RealKeyToVariantKey<Key>{}(k))); |
|
|
|
|
return BucketNumberFromHash(hash_function()(k)); |
|
|
|
|
ABSL_DCHECK_EQ( |
|
|
|
|
VariantBucketNumber(RealKeyToVariantKeyAlternative<Key>{}(k)), |
|
|
|
|
VariantBucketNumber(RealKeyToVariantKey<Key>{}(k))); |
|
|
|
|
return VariantBucketNumber(RealKeyToVariantKeyAlternative<Key>{}(k)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Assumes node_ and m_ are correct and non-null, but other fields may be
|
|
|
|
|