diff --git a/src/Collections/Dictionary.cpp b/src/Collections/Dictionary.cpp new file mode 100644 index 0000000..c86535c --- /dev/null +++ b/src/Collections/Dictionary.cpp @@ -0,0 +1 @@ +#include "Dictionary.hpp" diff --git a/src/Collections/Dictionary.hpp b/src/Collections/Dictionary.hpp new file mode 100644 index 0000000..1cfd742 --- /dev/null +++ b/src/Collections/Dictionary.hpp @@ -0,0 +1,64 @@ +#ifndef ARBUTILS_DICTIONARY_HPP +#define ARBUTILS_DICTIONARY_HPP +#include + +namespace Arbutils::Collections { + template class Dictionary { + private: + std::unordered_map _map; + + using iterator = typename std::unordered_map, std::equal_to, + std::allocator>>::iterator; + + public: + explicit Dictionary(size_t capacity) : _map(capacity) {} + + inline void Insert(KeyT key, ValueT value) { + auto v = _map.insert({key, value}); + if (!v.second) + throw std::logic_error("Key already exists"); + } + + inline void Set(KeyT key, ValueT value) { _map[key] = value; } + + [[nodiscard]] inline ValueT& Get(KeyT key) { + auto find = _map.find(key); + if (find == _map.end()) { + throw std::logic_error("Key not found"); + } + return find->second; + } + + [[nodiscard]] inline const ValueT& Get(KeyT key) const { + auto find = _map.find(key); + if (find == _map.end()) { + throw std::logic_error("Key not found"); + } + return find->second; + } + + inline bool TryGet(KeyT key, ValueT& out) const { + auto find = _map.find(key); + if (find == _map.end()) { + return false; + } + out = find->second; + return true; + } + + [[nodiscard]] inline size_t Count() const { return _map.size(); } + + inline bool Has(KeyT key) const noexcept { return _map.find(key) != _map.end(); } + + inline ValueT& operator[](KeyT key) { return Get(key); } + inline const ValueT& operator[](KeyT key) const { return Get(key); } + + iterator begin() { return _map.begin(); } + iterator begin() const { return _map.begin(); } + + iterator end() { return _map.end(); } + iterator end() const { return _map.end(); } + }; +} + +#endif // ARBUTILS_DICTIONARY_HPP diff --git a/tests/DictionaryTests.cpp b/tests/DictionaryTests.cpp new file mode 100644 index 0000000..7b26edb --- /dev/null +++ b/tests/DictionaryTests.cpp @@ -0,0 +1,105 @@ +#ifdef TESTS_BUILD +#include "../extern/catch.hpp" +#include "../src/Collections/Dictionary.hpp" +using namespace Arbutils::Collections; + +TEST_CASE("Create Dictionary, insert values", "[Utilities]") { + auto dic = Dictionary(5); + dic.Insert(10, 5); + dic.Insert(2, 100); + dic.Insert(9, 2000); +} + +TEST_CASE("Create Dictionary, insert values, get values", "[Utilities]") { + auto dic = Dictionary(5); + dic.Insert(10, 5); + dic.Insert(2, 100); + dic.Insert(9, 2000); + + CHECK(dic.Get(2) == 100); + CHECK(dic.Get(9) == 2000); + CHECK(dic.Get(10) == 5); +} + +TEST_CASE("Create Dictionary, insert values twice should throw", "[Utilities]") { + auto dic = Dictionary(5); + dic.Insert(10, 5); + CHECK_THROWS(dic.Insert(10, 100)); + + CHECK(dic.Get(10) == 5); +} + +TEST_CASE("Create Dictionary, insert value, then update value", "[Utilities]") { + auto dic = Dictionary(5); + dic.Insert(10, 5); + dic[10] = 200; + + CHECK(dic.Get(10) == 200); +} + +TEST_CASE("Create Dictionary, insert value, try get value", "[Utilities]") { + auto dic = Dictionary(5); + dic.Insert(10, 5); + int result = 0; + CHECK(dic.TryGet(10, result)); + CHECK(result == 5); +} + +TEST_CASE("Create Dictionary, insert value, try get non existing value", "[Utilities]") { + auto dic = Dictionary(5); + int result = 0; + CHECK_FALSE(dic.TryGet(10, result)); + CHECK(result == 0); +} + +TEST_CASE("Create Dictionary, insert value, Has", "[Utilities]") { + auto dic = Dictionary(5); + dic.Insert(10, 5); + CHECK(dic.Has(10)); +} + +TEST_CASE("Create Dictionary, set value", "[Utilities]") { + auto dic = Dictionary(5); + dic.Set(5, 100); + CHECK(dic.Has(5)); +} + +TEST_CASE("Create Dictionary, insert values, get count", "[Utilities]") { + auto dic = Dictionary(5); + dic.Insert(10, 5); + dic.Insert(2, 100); + dic.Insert(9, 2000); + + CHECK(dic.Count() == 3); +} + +TEST_CASE("Create Dictionary, insert values, iterate over keys", "[Utilities]") { + auto dic = Dictionary(5); + dic.Insert(10, 5); + dic.Insert(2, 100); + dic.Insert(9, 2000); + + size_t i = 0; + for (auto val: dic){ + CHECK(dic.Has(val.first)); + i++; + } + CHECK(i == 3); +} + +TEST_CASE("Create Dictionary with different types, insert values, iterate over keys", "[Utilities]") { + auto dic = Dictionary(5); + dic.Insert(10, 5); + dic.Insert(2, 100); + dic.Insert(9, 105); + + size_t i = 0; + for (auto val: dic){ + CHECK(dic.Has(val.first)); + i++; + } + CHECK(i == 3); +} + + +#endif \ No newline at end of file