From feb9beceb273d2b6446170a344209b02eb3c99ea Mon Sep 17 00:00:00 2001 From: cat Date: Sun, 25 Jan 2026 02:22:14 +0200 Subject: [PATCH] DKM operator[] (UNTESTED) --- headers/Containers/DualkeyMap.hpp | 66 ++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/headers/Containers/DualkeyMap.hpp b/headers/Containers/DualkeyMap.hpp index 7a2e992..2f128c2 100644 --- a/headers/Containers/DualkeyMap.hpp +++ b/headers/Containers/DualkeyMap.hpp @@ -8,10 +8,16 @@ */ #ifndef GUARD_TOURMALINE_DUALKEYMAP_H #define GUARD_TOURMALINE_DUALKEYMAP_H +#include "../Systems/Logging.hpp" #include "Hashing.hpp" #include #include +#include +#include +#include +#include +#include #include namespace Tourmaline::Containers { @@ -19,23 +25,62 @@ template class DualkeyMap { - DualkeyMap() { - ValueList.reserve(baseReservation); - HashList.reserve(baseReservation); - } + DualkeyMap() { HashList.reserve(baseReservation); } ~DualkeyMap() { // I'm sure there is a better way to do this - for (auto value : ValueList) { - delete value; - } - - for (auto hash : HashList) { + for (DualkeyHash hash : HashList) { delete hash.Apointer; delete hash.Bpointer; + delete hash.ValuePointer; } } + std::span, Value &>> + operator[](std::optional FirstKey, std::optional SecondKey) { + bool isFirstKeyGiven = FirstKey.has_value(); + bool isSecondKeyGiven = SecondKey.has_value(); + + if (!isFirstKeyGiven && !isSecondKeyGiven) [[unlikely]] { + Systems::Logging::Log("Failed to index! Dualkey maps require at least 1 " + "key to be given, returning an empty span.", + "Dualkey Map", Systems::Logging::LogLevel::Warning); + return {}; + } + std::size_t firstKeyHash = + isFirstKeyGiven ? std::hash{}(*FirstKey.value()) : 0; + std::size_t secondKeyHash = + isSecondKeyGiven ? std::hash{}(*SecondKey.value()) : 0; + + std::vector< + std::pair, Value &>> + finishedQuery{}; + + uint8_t stateOfIndexing = isFirstKeyGiven + (isSecondKeyGiven << 1); + for (DualkeyHash hash : HashList) { + switch (stateOfIndexing) { + case 1: // Only first key is given + if (firstKeyHash == hash.AKeyHash) { + finishedQuery.emplace_back(hash.BPointer, hash.ValuePointer); + } + continue; + case 2: // Only second key is given + if (secondKeyHash == hash.BKeyHash) { + finishedQuery.emplace_back(hash.APointer, hash.ValuePointer); + } + continue; + case 3: // Both are given + if (firstKeyHash == hash.AKeyHash && secondKeyHash == hash.BKeyHash) { + finishedQuery.emplace_back(std::monostate{}, hash.ValuePointer); + } + break; + } + break; + } + + return finishedQuery; + } + // No copying, No moving. Moving may be valid in the future. // However as of now it is not a wise way to use this map. DualkeyMap(const DualkeyMap &) = delete; @@ -53,8 +98,9 @@ private: std::size_t BKeyHash = 0; AKey *APointer; BKey *BPointer; + Value *ValuePointer; }; - std::vector ValueList; + std::vector HashList; }; } // namespace Tourmaline::Containers