From 74082720c42c5d6b06b71cefbad4b794ff1b8c3c Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Sat, 18 Jan 2025 19:59:36 +0100 Subject: Finish the hash_map --- asl/hash_map.hpp | 77 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 9 deletions(-) (limited to 'asl/hash_map.hpp') 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 KeyComparator = default_key_comparator > requires moveable && moveable -class hash_map : hash_set< +class hash_map : protected hash_set< hash_map_internal::Slot, Allocator, hash_map_internal::SlotHasher, @@ -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 + requires + key_hasher && + key_comparator && + constructible_from && + constructible_from + 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) + { + 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 + requires key_hasher && key_comparator + 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 -- cgit