summaryrefslogtreecommitdiff
path: root/asl/hash_map.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'asl/hash_map.hpp')
-rw-r--r--asl/hash_map.hpp77
1 files changed, 68 insertions, 9 deletions
diff --git a/asl/hash_map.hpp b/asl/hash_map.hpp
index 310b532..300ffdb 100644
--- a/asl/hash_map.hpp
+++ b/asl/hash_map.hpp
@@ -1,12 +1,9 @@
#pragma once
-#include "asl/annotations.hpp"
#include "asl/meta.hpp"
#include "asl/utility.hpp"
-#include "asl/maybe_uninit.hpp"
#include "asl/hash.hpp"
#include "asl/allocator.hpp"
-#include "asl/memory.hpp"
#include "asl/hash_set.hpp"
namespace asl
@@ -59,7 +56,7 @@ template<
key_comparator<K> KeyComparator = default_key_comparator<K>
>
requires moveable<K> && moveable<V>
-class hash_map : hash_set<
+class hash_map : protected hash_set<
hash_map_internal::Slot<K, V>,
Allocator,
hash_map_internal::SlotHasher<K, V, KeyHasher>,
@@ -95,11 +92,73 @@ public:
using Base::size;
- // @Todo insert
- // @Todo contains
- // @Todo remove
- // @Todo get
- // @Todo tests
+ using Base::remove;
+
+ using Base::contains;
+
+ template<typename U, typename Arg0, typename... Args1>
+ requires
+ key_hasher<KeyHasher, U> &&
+ key_comparator<KeyComparator, K, U> &&
+ constructible_from<K, U&&> &&
+ constructible_from<V, Arg0&&, Args1&&...>
+ void insert(U&& key, Arg0&& arg0, Args1&&... args1)
+ {
+ Base::maybe_grow_to_fit_one_more();
+
+ auto result = Base::find_slot_insert(key);
+
+ // NOLINTBEGIN(*-pointer-arithmetic)
+
+ ASL_ASSERT(result.first_available_index >= 0);
+
+ if (result.already_present_index >= 0)
+ {
+ if (result.already_present_index != result.first_available_index)
+ {
+ ASL_ASSERT((Base::m_tags[result.first_available_index] & Base::kHasValue) == 0);
+
+ Base::m_values[result.first_available_index].construct_unsafe(ASL_MOVE(Base::m_values[result.already_present_index].as_init_unsafe()));
+ Base::m_values[result.already_present_index].destroy_unsafe();
+
+ Base::m_tags[result.first_available_index] = result.tag;
+ Base::m_tags[result.already_present_index] = Base::kTombstone;
+ }
+
+ ASL_ASSERT(Base::m_tags[result.first_available_index] == result.tag);
+
+ if constexpr (sizeof...(Args1) == 0 && assignable_from<V&, Arg0&&>)
+ {
+ Base::m_values[result.first_available_index].as_init_unsafe().value = ASL_FWD(arg0);
+ }
+ else
+ {
+ Base::m_values[result.first_available_index].as_init_unsafe().value = ASL_MOVE(V{ASL_FWD(arg0), ASL_FWD(args1)...});
+ }
+ }
+ else
+ {
+ ASL_ASSERT((Base::m_tags[result.first_available_index] & Base::kHasValue) == 0);
+ Base::m_values[result.first_available_index].construct_unsafe(ASL_FWD(key), V{ASL_FWD(arg0), ASL_FWD(args1)...});
+ Base::m_tags[result.first_available_index] = result.tag;
+ Base::m_size += 1;
+ }
+
+ // NOLINTEND(*-pointer-arithmetic)
+ }
+
+ template<typename U>
+ requires key_hasher<KeyHasher, U> && key_comparator<KeyComparator, K, U>
+ V* get(const U& value) const
+ {
+ isize_t index = Base::find_slot_lookup(value);
+ if (index >= 0)
+ {
+ // NOLINTNEXTLINE(*-pointer-arithmetic)
+ return &Base::m_values[index].as_init_unsafe().value;
+ }
+ return nullptr;
+ }
};
} // namespace asl