diff --git a/headers/Containers/DualkeyMap.hpp b/headers/Containers/DualkeyMap.hpp index 2fcbb35..c93e06c 100644 --- a/headers/Containers/DualkeyMap.hpp +++ b/headers/Containers/DualkeyMap.hpp @@ -183,76 +183,7 @@ public: requires(std::same_as || std::same_as) [[nodiscard("Discarding a very expensive query!")]] int QueryWithAll(const Key (&keys)[keyCount]) { - constexpr bool searchingInFirstKey = std::is_same_v; - - // I really can't wait for C++26 contracts - if constexpr (keyCount == 0) { - Systems::Logging::Log("Failed to Query! QueryWithAll require at least 2 " - "key to be given, zero was given! Terminating", - "Dualkey Map", - Systems::Logging::LogLevel::Critical); - } - - // Hoping this never ever gets triggered :sigh: - if constexpr (keyCount == 1) { - Systems::Logging::Log("QueryWithAll should not be used for single key " - "entry! Please use Query for this instead.", - "Dualkey Map", Systems::Logging::LogLevel::Error); - } - - // While we don't necessary need the hashes, - // it just helps us tremendously benefit from short circuit checks - std::array keyHashes; - for (uint64_t index = 0; index < keyCount; index++) { - keyHashes[index] = std::hash{}(keys[index]); - } - - std::vector, keyCount>> - queryResults; - uint64_t hashToCompare; - Key *keyToCompare; - std::conditional_t resultKey; - for (DualkeyHash *hash : hashList) { - // The hell of doing 2 conditions with similar logics in - // the same logical block - if constexpr (searchingInFirstKey) { - hashToCompare = hash->firstKeyHash; - keyToCompare = const_cast(&hash->firstKey); - resultKey = const_cast(&hash->secondKey); - } else { - hashToCompare = hash->secondKeyHash; - keyToCompare = const_cast(&hash->secondKey); - resultKey = const_cast(&hash->firstKey); - } - - // The code above was done to make this code more uniform - for (uint64_t index = 0; index < keyCount; index++) { - if (keyHashes[index] == hashToCompare && keys[index] == *keyToCompare) { - - bool doesExist = false; - for (auto &queryRecord : queryResults) { - if (*queryRecord.resultKey == *resultKey) { - queryRecord.valueQueryResults[index] = &hash->value; - ++queryRecord.howManyFound; - doesExist = true; - break; - } - } - - if (doesExist) { - break; - } - - // Since the result record is not present - // we have to make it - queryResults.emplace_back(); - auto &newRecord = queryResults.back(); - newRecord.resultKey = resultKey; - newRecord.valueQueryResults[index] = &hash->value; - } - } - } + auto queryResults = queryWithMany(keys); for (const auto &queryRecord : queryResults) { Systems::Logging::Log( @@ -324,6 +255,84 @@ private: mutable Value value; }; + template + inline std::vector, BKey, AKey>, keyCount>> + queryWithMany(const Key (&keys)[keyCount]) { + constexpr bool searchingInFirstKey = std::is_same_v; + + // I really can't wait for C++26 contracts + if constexpr (keyCount == 0) { + Systems::Logging::Log("Failed to Query! QueryWithAll require at least 2 " + "key to be given, zero was given! Terminating", + "Dualkey Map", + Systems::Logging::LogLevel::Critical); + } + + // Hoping this never ever gets triggered :sigh: + if constexpr (keyCount == 1) { + Systems::Logging::Log("QueryWithAll should not be used for single key " + "entry! Please use Query for this instead.", + "Dualkey Map", Systems::Logging::LogLevel::Error); + } + + // While we don't necessary need the hashes, + // it just helps us tremendously benefit from short circuit checks + std::array keyHashes; + for (uint64_t index = 0; index < keyCount; index++) { + keyHashes[index] = std::hash{}(keys[index]); + } + + uint64_t hashToCompare; + Key *keyToCompare; + std::conditional_t resultKey; + std::vector, keyCount>> + queryResults; + for (DualkeyHash *hash : hashList) { + // The hell of doing 2 conditions with similar logics in + // the same logical block + if constexpr (searchingInFirstKey) { + hashToCompare = hash->firstKeyHash; + keyToCompare = const_cast(&hash->firstKey); + resultKey = const_cast(&hash->secondKey); + } else { + hashToCompare = hash->secondKeyHash; + keyToCompare = const_cast(&hash->secondKey); + resultKey = const_cast(&hash->firstKey); + } + + // The code above was done to make this code more uniform + for (uint64_t index = 0; index < keyCount; index++) { + if (keyHashes[index] == hashToCompare && keys[index] == *keyToCompare) { + + bool doesExist = false; + for (auto &queryRecord : queryResults) { + if (*queryRecord.resultKey == *resultKey) { + queryRecord.valueQueryResults[index] = &hash->value; + ++queryRecord.howManyFound; + doesExist = true; + break; + } + } + + if (doesExist) { + break; + } + + // Since the result record is not present + // we have to make it + queryResults.emplace_back(); + auto &newRecord = queryResults.back(); + newRecord.resultKey = resultKey; + newRecord.valueQueryResults[index] = &hash->value; + } + } + } + + return queryResults; + } + // It makes more sense to store the individual hash std::vector hashList; std::stack graveyard;