Implements Dictionary class, a wrapper for the unordered_map, with more safety.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
e07e07253d
commit
5de26d0866
|
@ -0,0 +1 @@
|
|||
#include "Dictionary.hpp"
|
|
@ -0,0 +1,64 @@
|
|||
#ifndef ARBUTILS_DICTIONARY_HPP
|
||||
#define ARBUTILS_DICTIONARY_HPP
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Arbutils::Collections {
|
||||
template <class KeyT, class ValueT> class Dictionary {
|
||||
private:
|
||||
std::unordered_map<KeyT, ValueT> _map;
|
||||
|
||||
using iterator = typename std::unordered_map<KeyT, ValueT, std::hash<KeyT>, std::equal_to<KeyT>,
|
||||
std::allocator<std::pair<const KeyT, ValueT>>>::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
|
|
@ -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<int, int>(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<int, int>(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<int, int>(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<int, int>(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<int, int>(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<int, int>(5);
|
||||
int result = 0;
|
||||
CHECK_FALSE(dic.TryGet(10, result));
|
||||
CHECK(result == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("Create Dictionary, insert value, Has", "[Utilities]") {
|
||||
auto dic = Dictionary<int, int>(5);
|
||||
dic.Insert(10, 5);
|
||||
CHECK(dic.Has(10));
|
||||
}
|
||||
|
||||
TEST_CASE("Create Dictionary, set value", "[Utilities]") {
|
||||
auto dic = Dictionary<int, int>(5);
|
||||
dic.Set(5, 100);
|
||||
CHECK(dic.Has(5));
|
||||
}
|
||||
|
||||
TEST_CASE("Create Dictionary, insert values, get count", "[Utilities]") {
|
||||
auto dic = Dictionary<int, int>(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<int, int>(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<char, char>(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
|
Loading…
Reference in New Issue