summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2023-02-02 10:55:50 -0500
committerLinus Groh <mail@linusgroh.de>2023-02-02 19:14:00 +0000
commit2af7447dfd598bbcabf8666211b3d09173b3fe8f (patch)
tree3d245f3c91b4b756b77e53676ee34790e4ce97e0
parentf31bd190b0f746a8e304a4eeb79ce9c002e656d0 (diff)
downloadserenity-2af7447dfd598bbcabf8666211b3d09173b3fe8f.zip
AK: Define HashMap::take to find and remove a value from the map
-rw-r--r--AK/HashMap.h25
-rw-r--r--Tests/AK/TestHashMap.cpp32
2 files changed, 57 insertions, 0 deletions
diff --git a/AK/HashMap.h b/AK/HashMap.h
index ec8d946472..d3e1af9b63 100644
--- a/AK/HashMap.h
+++ b/AK/HashMap.h
@@ -199,6 +199,31 @@ public:
m_table.remove(it);
}
+ Optional<V> take(K const& key)
+ {
+ if (auto it = find(key); it != end()) {
+ auto value = move(it->value);
+ m_table.remove(it);
+
+ return value;
+ }
+
+ return {};
+ }
+
+ template<Concepts::HashCompatible<K> Key>
+ requires(IsSame<KeyTraits, Traits<K>>) Optional<V> take(Key const& key)
+ {
+ if (auto it = find(key); it != end()) {
+ auto value = move(it->value);
+ m_table.remove(it);
+
+ return value;
+ }
+
+ return {};
+ }
+
V& ensure(K const& key)
{
auto it = find(key);
diff --git a/Tests/AK/TestHashMap.cpp b/Tests/AK/TestHashMap.cpp
index bbb4876c5d..6e70540a9f 100644
--- a/Tests/AK/TestHashMap.cpp
+++ b/Tests/AK/TestHashMap.cpp
@@ -9,6 +9,7 @@
#include <AK/DeprecatedString.h>
#include <AK/HashMap.h>
#include <AK/OwnPtr.h>
+#include <AK/String.h>
TEST_CASE(construct)
{
@@ -219,3 +220,34 @@ TEST_CASE(in_place_rehashing_ordered_loop_bug)
map.set("yt.innertube::nextId", "");
VERIFY(map.keys().size() == 2);
}
+
+TEST_CASE(take)
+{
+ HashMap<String, int> map;
+
+ EXPECT(!map.take("foo"sv).has_value());
+ EXPECT(!map.take("bar"sv).has_value());
+ EXPECT(!map.take(String::from_utf8_short_string("baz"sv)).has_value());
+
+ map.set(String::from_utf8_short_string("foo"sv), 1);
+ map.set(String::from_utf8_short_string("bar"sv), 2);
+ map.set(String::from_utf8_short_string("baz"sv), 3);
+
+ auto foo = map.take("foo"sv);
+ EXPECT_EQ(foo, 1);
+
+ foo = map.take("foo"sv);
+ EXPECT(!foo.has_value());
+
+ auto bar = map.take("bar"sv);
+ EXPECT_EQ(bar, 2);
+
+ bar = map.take("bar"sv);
+ EXPECT(!bar.has_value());
+
+ auto baz = map.take(String::from_utf8_short_string("baz"sv));
+ EXPECT_EQ(baz, 3);
+
+ baz = map.take(String::from_utf8_short_string("baz"sv));
+ EXPECT(!baz.has_value());
+}