diff --git a/AK/HashTable.h b/AK/HashTable.h index cacd4bda42..bb4d08e341 100644 --- a/AK/HashTable.h +++ b/AK/HashTable.h @@ -384,7 +384,7 @@ public: return false; } - void remove(Iterator iterator) + Iterator remove(Iterator iterator) { VERIFY(iterator.m_bucket); auto& bucket = *iterator.m_bucket; @@ -394,6 +394,9 @@ public: if constexpr (!IsOrdered) VERIFY(!bucket.end); + auto next_iterator = iterator; + ++next_iterator; + bucket.slot()->~T(); bucket.used = false; bucket.deleted = true; @@ -411,6 +414,19 @@ public: else m_collection_data.tail = bucket.previous; } + + return next_iterator; + } + + template + void remove_all_matching(TUnaryPredicate predicate) + { + for (auto it = begin(); it != end();) { + if (predicate(*it)) + it = remove(it); + else + ++it; + } } private: diff --git a/Tests/AK/TestHashTable.cpp b/Tests/AK/TestHashTable.cpp index 9729eac9a3..a5eb34d97c 100644 --- a/Tests/AK/TestHashTable.cpp +++ b/Tests/AK/TestHashTable.cpp @@ -84,6 +84,26 @@ TEST_CASE(table_remove) EXPECT(strings.find("Two") != strings.end()); } +TEST_CASE(table_remove_all_matching) +{ + HashTable ints; + + ints.set(1); + ints.set(2); + ints.set(3); + ints.set(4); + + EXPECT_EQ(ints.size(), 4u); + + ints.remove_all_matching([&](int value) { return value > 2; }); + + EXPECT_EQ(ints.size(), 2u); + + ints.remove_all_matching([&](int) { return true; }); + + EXPECT(ints.is_empty()); +} + TEST_CASE(case_insensitive) { HashTable casetable;