/* * SPDX-FileCopyrightText: Dora "cat" * SPDX-License-Identifier: MPL-2.0 * * This Source Code Form is subject to the terms of the Mozilla Public License, * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef GUARD_TOURMALINE_HASHMAP_H #define GUARD_TOURMALINE_HASHMAP_H #include "../Concepts.hpp" #include "../Systems/Logging.hpp" #include #include namespace Tourmaline::Containers { template class Hashmap { public: Hashmap() { storage.resize(baseBucketCount); } ~Hashmap() { Clear(); } Value &Insert(Key key, Value value) { std::size_t keyHash = std::hash{}(key), keyHashPosition = keyHash % storage.size(); // Empty bucket if (storage[keyHashPosition] == nullptr) { storage[keyHashPosition] = new std::vector; storage[keyHashPosition]->emplace_back(key, std::move(value), keyHash); ++count; return storage[keyHashPosition]->back().value; } // Throws Systems::Logging::Log("Trying to inserting same key twice! Throwing...", "Hashmap", Systems::Logging::LogLevel::Error, Has(key)); storage[keyHashPosition]->emplace_back(key, std::move(value), keyHash); ++count; return storage[keyHashPosition]->back().value; } void Remove(const Key &key) { std::size_t keyHash = std::hash{}(key), keyHashPosition = keyHash % storage.size(); // Throws Systems::Logging::Log("Trying to remove a non-existant key! Throwing...", "Hashmap", Systems::Logging::LogLevel::Error, storage[keyHashPosition] == nullptr); std::erase_if(*storage[keyHashPosition], [keyHash, &key](const hashStorage &hash) { return hash.hash == keyHash && hash.key == key; }); --count; } bool Has(const Key &key) { std::size_t keyHash = std::hash{}(key), keyHashPosition = keyHash % storage.size(); // Empty bucket if (storage[keyHashPosition] == nullptr) { return false; } for (const hashStorage &hash : *storage[keyHashPosition]) { if (hash.hash == keyHash && hash.key == key) { return true; } } return false; } Value &Get(const Key &key) { std::size_t keyHash = std::hash{}(key), keyHashPosition = keyHash % storage.size(); Systems::Logging::Log( "Trying to access a non-existant bucket for a key! Throwing...", "Hashmap", Systems::Logging::LogLevel::Error, storage[keyHashPosition] == nullptr); for (hashStorage &hash : *storage[keyHashPosition]) { if (hash.hash == keyHash && hash.key == key) { return hash.value; } } Systems::Logging::Log("Trying to access a non-existant key! Throwing...", "Hashmap", Systems::Logging::LogLevel::Error); } void Clear() noexcept { for (bucket *entry : storage) { if (entry == nullptr) { continue; } entry->clear(); delete entry; } count = 0; } std::size_t Count() { return count; } private: struct hashStorage { Key key; Value value; std::size_t hash; }; using bucket = std::vector; std::vector storage; std::size_t count = 0; }; } // namespace Tourmaline::Containers #endif