DKM operator[] (UNTESTED)

This commit is contained in:
2026-01-25 02:22:14 +02:00
parent 2556a473cc
commit feb9beceb2

View File

@@ -8,10 +8,16 @@
*/
#ifndef GUARD_TOURMALINE_DUALKEYMAP_H
#define GUARD_TOURMALINE_DUALKEYMAP_H
#include "../Systems/Logging.hpp"
#include "Hashing.hpp"
#include <cstddef>
#include <cstdint>
#include <functional>
#include <optional>
#include <span>
#include <utility>
#include <variant>
#include <vector>
namespace Tourmaline::Containers {
@@ -19,23 +25,62 @@ template <Hashable AKey, Hashable BKey, typename Value,
uint64_t baseReservation = 1024,
float reservationGrowthExponent = 1.5>
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<std::pair<std::variant<std::monostate, AKey &, BKey &>, Value &>>
operator[](std::optional<AKey> FirstKey, std::optional<BKey> 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<AKey>{}(*FirstKey.value()) : 0;
std::size_t secondKeyHash =
isSecondKeyGiven ? std::hash<BKey>{}(*SecondKey.value()) : 0;
std::vector<
std::pair<std::variant<std::monostate, AKey &, BKey &>, 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<Value *> ValueList;
std::vector<DualkeyHash> HashList;
};
} // namespace Tourmaline::Containers