tint/utils: Add Hashmap equality and hashing
Allows Hashmaps to be used as keys to other hashmaps. Change-Id: I557d99515451c55e599dda847e15ce8e2b4500c5 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/112282 Kokoro: Ben Clayton <bclayton@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
parent
2d108ae5ed
commit
c158e845e6
|
@ -206,6 +206,31 @@ class Hashmap : public HashmapBase<KEY, VALUE, N, HASH, EQUAL> {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Equality operator
|
||||||
|
/// @param other the other Hashmap to compare this Hashmap to
|
||||||
|
/// @returns true if this Hashmap has the same key and value pairs as @p other
|
||||||
|
template <typename K, typename V, size_t N2>
|
||||||
|
bool operator==(const Hashmap<K, V, N2>& other) const {
|
||||||
|
if (this->Count() != other.Count()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (auto it : *this) {
|
||||||
|
auto other_val = other.Find(it.key);
|
||||||
|
if (!other_val || it.value != *other_val) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inequality operator
|
||||||
|
/// @param other the other Hashmap to compare this Hashmap to
|
||||||
|
/// @returns false if this Hashmap has the same key and value pairs as @p other
|
||||||
|
template <typename K, typename V, size_t N2>
|
||||||
|
bool operator!=(const Hashmap<K, V, N2>& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Value* Lookup(const Key& key) {
|
Value* Lookup(const Key& key) {
|
||||||
if (auto [found, index] = this->IndexOf(key); found) {
|
if (auto [found, index] = this->IndexOf(key); found) {
|
||||||
|
@ -222,6 +247,22 @@ class Hashmap : public HashmapBase<KEY, VALUE, N, HASH, EQUAL> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Hasher specialization for Hashmap
|
||||||
|
template <typename K, typename V, size_t N, typename HASH, typename EQUAL>
|
||||||
|
struct Hasher<Hashmap<K, V, N, HASH, EQUAL>> {
|
||||||
|
/// @param map the Hashmap to hash
|
||||||
|
/// @returns a hash of the map
|
||||||
|
size_t operator()(const Hashmap<K, V, N, HASH, EQUAL>& map) const {
|
||||||
|
auto hash = Hash(map.Count());
|
||||||
|
for (auto it : map) {
|
||||||
|
// Use an XOR to ensure that the non-deterministic ordering of the map still produces
|
||||||
|
// the same hash value for the same entries.
|
||||||
|
hash ^= Hash(it.key) * 31 + Hash(it.value);
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace tint::utils
|
} // namespace tint::utils
|
||||||
|
|
||||||
#endif // SRC_TINT_UTILS_HASHMAP_H_
|
#endif // SRC_TINT_UTILS_HASHMAP_H_
|
||||||
|
|
|
@ -355,5 +355,61 @@ TEST(Hashmap, Soak) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Hashmap, EqualitySameSize) {
|
||||||
|
Hashmap<int, std::string, 8> a;
|
||||||
|
Hashmap<int, std::string, 8> b;
|
||||||
|
EXPECT_EQ(a, b);
|
||||||
|
a.Add(1, "one");
|
||||||
|
EXPECT_NE(a, b);
|
||||||
|
b.Add(2, "two");
|
||||||
|
EXPECT_NE(a, b);
|
||||||
|
a.Add(2, "two");
|
||||||
|
EXPECT_NE(a, b);
|
||||||
|
b.Add(1, "one");
|
||||||
|
EXPECT_EQ(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Hashmap, EqualityDifferentSize) {
|
||||||
|
Hashmap<int, std::string, 8> a;
|
||||||
|
Hashmap<int, std::string, 4> b;
|
||||||
|
EXPECT_EQ(a, b);
|
||||||
|
a.Add(1, "one");
|
||||||
|
EXPECT_NE(a, b);
|
||||||
|
b.Add(2, "two");
|
||||||
|
EXPECT_NE(a, b);
|
||||||
|
a.Add(2, "two");
|
||||||
|
EXPECT_NE(a, b);
|
||||||
|
b.Add(1, "one");
|
||||||
|
EXPECT_EQ(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Hashmap, HashSameSize) {
|
||||||
|
Hashmap<int, std::string, 8> a;
|
||||||
|
Hashmap<int, std::string, 8> b;
|
||||||
|
EXPECT_EQ(Hash(a), Hash(b));
|
||||||
|
a.Add(1, "one");
|
||||||
|
EXPECT_NE(Hash(a), Hash(b));
|
||||||
|
b.Add(2, "two");
|
||||||
|
EXPECT_NE(Hash(a), Hash(b));
|
||||||
|
a.Add(2, "two");
|
||||||
|
EXPECT_NE(Hash(a), Hash(b));
|
||||||
|
b.Add(1, "one");
|
||||||
|
EXPECT_EQ(Hash(a), Hash(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Hashmap, HashDifferentSize) {
|
||||||
|
Hashmap<int, std::string, 8> a;
|
||||||
|
Hashmap<int, std::string, 4> b;
|
||||||
|
EXPECT_EQ(Hash(a), Hash(b));
|
||||||
|
a.Add(1, "one");
|
||||||
|
EXPECT_NE(Hash(a), Hash(b));
|
||||||
|
b.Add(2, "two");
|
||||||
|
EXPECT_NE(Hash(a), Hash(b));
|
||||||
|
a.Add(2, "two");
|
||||||
|
EXPECT_NE(Hash(a), Hash(b));
|
||||||
|
b.Add(1, "one");
|
||||||
|
EXPECT_EQ(Hash(a), Hash(b));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::utils
|
} // namespace tint::utils
|
||||||
|
|
Loading…
Reference in New Issue