From fdcff7d15e89297e94a0bfa33b51eebf6e55e96a Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 14 Aug 2019 11:47:38 +0200 Subject: [PATCH] AK: Make it possible to use HashMap::get() Add the concept of a PeekType to Traits. This is the type we'll return (wrapped in an Optional) from HashMap::get(). The PeekType for OwnPtr and NonnullOwnPtr is const T*, which means that HashMap::get() will return an Optional for maps-of-those. --- AK/HashMap.h | 2 +- AK/NonnullOwnPtr.h | 1 + AK/OwnPtr.h | 1 + AK/RefPtr.h | 6 ++++++ AK/Tests/TestHashMap.cpp | 29 +++++++++++++++++++++++++++++ AK/Traits.h | 3 ++- 6 files changed, 40 insertions(+), 2 deletions(-) diff --git a/AK/HashMap.h b/AK/HashMap.h index 5833515f76e..4060dee6b98 100644 --- a/AK/HashMap.h +++ b/AK/HashMap.h @@ -68,7 +68,7 @@ public: void dump() const { m_table.dump(); } - Optional get(const K& key) const + Optional::PeekType> get(const K& key) const { auto it = find(key); if (it == end()) diff --git a/AK/NonnullOwnPtr.h b/AK/NonnullOwnPtr.h index e9cc114be6a..a86349b60b4 100644 --- a/AK/NonnullOwnPtr.h +++ b/AK/NonnullOwnPtr.h @@ -142,6 +142,7 @@ make(Args&&... args) template struct Traits> : public GenericTraits> { + using PeekType = const T*; static unsigned hash(const NonnullOwnPtr& p) { return (unsigned)p.ptr(); } static void dump(const NonnullOwnPtr& p) { kprintf("%p", p.ptr()); } static bool equals(const NonnullOwnPtr& a, const NonnullOwnPtr& b) { return a.ptr() == b.ptr(); } diff --git a/AK/OwnPtr.h b/AK/OwnPtr.h index f52c17ecbd9..675b58c0f79 100644 --- a/AK/OwnPtr.h +++ b/AK/OwnPtr.h @@ -164,6 +164,7 @@ private: template struct Traits> : public GenericTraits> { + using PeekType = const T*; static unsigned hash(const OwnPtr& p) { return (unsigned)p.ptr(); } static void dump(const OwnPtr& p) { kprintf("%p", p.ptr()); } static bool equals(const OwnPtr& a, const OwnPtr& b) { return a.ptr() == b.ptr(); } diff --git a/AK/RefPtr.h b/AK/RefPtr.h index 2d34485e346..5ba8b6e4362 100644 --- a/AK/RefPtr.h +++ b/AK/RefPtr.h @@ -183,6 +183,12 @@ public: return exchange(m_ptr, nullptr); } + NonnullRefPtr release_nonnull() + { + ASSERT(m_ptr); + return NonnullRefPtr(NonnullRefPtr::Adopt, *leak_ref()); + } + T* ptr() { return m_ptr; } const T* ptr() const { return m_ptr; } diff --git a/AK/Tests/TestHashMap.cpp b/AK/Tests/TestHashMap.cpp index 9daa7e494cd..774e8e5a315 100644 --- a/AK/Tests/TestHashMap.cpp +++ b/AK/Tests/TestHashMap.cpp @@ -76,4 +76,33 @@ TEST_CASE(assert_on_iteration_during_clear) map.clear(); } +TEST_CASE(hashmap_of_nonnullownptr_get) +{ + struct Object { + Object(const String& s) : string(s) {} + String string; + }; + + HashMap> objects; + objects.set(1, make("One")); + objects.set(2, make("Two")); + objects.set(3, make("Three")); + + { + auto x = objects.get(2); + EXPECT_EQ(x.has_value(), true); + EXPECT_EQ(x.value()->string, "Two"); + } + + { + // Do it again to make sure that peeking into the map above didn't + // remove the value from the map. + auto x = objects.get(2); + EXPECT_EQ(x.has_value(), true); + EXPECT_EQ(x.value()->string, "Two"); + } + + EXPECT_EQ(objects.size(), 3); +} + TEST_MAIN(HashMap) diff --git a/AK/Traits.h b/AK/Traits.h index fb5ce773d36..f268e669403 100644 --- a/AK/Traits.h +++ b/AK/Traits.h @@ -7,6 +7,7 @@ namespace AK { template struct GenericTraits { + using PeekType = T; static constexpr bool is_trivial() { return false; } static bool equals(const T& a, const T& b) { return a == b; } }; @@ -44,7 +45,7 @@ struct Traits : public GenericTraits { }; template -struct Traits { +struct Traits : public GenericTraits { static unsigned hash(const T* p) { return int_hash((unsigned)(__PTRDIFF_TYPE__)p);