diff --git a/headers/Containers/Hashmap.hpp b/headers/Containers/Hashmap.hpp new file mode 100644 index 0000000..ae835f0 --- /dev/null +++ b/headers/Containers/Hashmap.hpp @@ -0,0 +1,110 @@ + +/* + * 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/. + */ +#include "../Concepts.hpp" +#include "../Systems/Logging.hpp" + +#include +#include + +#ifndef GUARD_TOURMALINE_HASHMAP_H +#define GUARD_TOURMALINE_HASHMAP_H +namespace Tourmaline::Containers { +template +class Hashmap { +public: + Hashmap() { storage.resize(baseBucketCount); } + ~Hashmap() { Clear(); } + + void 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(keyHash, key, std::move(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], + [key, keyHash](const hashStorage &hash) { + return hash.hash == keyHash && hash.key == key; + }); + } + + 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 (const 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; + } + } + +private: + struct hashStorage { + const std::size_t hash; + const Key key; + mutable Value value; + }; + + using bucket = std::vector; + std::vector storage; +}; +} // namespace Tourmaline::Containers +#endif