Initial Commit. Needs refactored to run tests in parallel. Needs to avoid copying objects into both unordered_maps and reference them instead.
This commit is contained in:
commit
50d7342551
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
run-tests
|
94
DualLookup.h
Normal file
94
DualLookup.h
Normal file
@ -0,0 +1,94 @@
|
||||
#ifndef DVEREB_DUALLOOKUP_H
|
||||
#define DVEREB_DUALLOOKUP_H
|
||||
|
||||
#include <unordered_map>
|
||||
template <class T>
|
||||
class DualLookup {
|
||||
public:
|
||||
DualLookup();
|
||||
|
||||
/* Add a mapped pair to the container
|
||||
* returns false if it already exists, regardless of direction
|
||||
* (i.e. value->equivilent is a duplicate of equivilent->value)
|
||||
*/
|
||||
bool add(T value, T equivilent);
|
||||
|
||||
/* If found, Set result to the mapped value and true is returned.
|
||||
* If not found, result remains unchanged and false is returned.
|
||||
*/
|
||||
bool get(T key, T &result);
|
||||
|
||||
/* If found, return true
|
||||
* else return false */
|
||||
bool contains(const T &key);
|
||||
|
||||
private:
|
||||
std::unordered_map<T, T> owner;
|
||||
std::unordered_map<T, T> mirror;
|
||||
|
||||
// NOTE(dev): These functions actually do the work:
|
||||
bool get_single(T key, T &result, const std::unordered_map<T, T> &umap);
|
||||
bool contains_single(const T &key, const std::unordered_map<T, T> &umap);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
DualLookup<T>::DualLookup()
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool DualLookup<T>::add(T value, T equivilent)
|
||||
{
|
||||
// already exists
|
||||
if(owner.find(value) != owner.end() || mirror.find(value) != mirror.end())
|
||||
return false;
|
||||
if(owner.find(equivilent) != owner.end() || mirror.find(equivilent) != mirror.end())
|
||||
return false;
|
||||
|
||||
owner.insert({value, equivilent});
|
||||
mirror.insert({equivilent, value});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool DualLookup<T>::get(T key, T &result)
|
||||
{
|
||||
if(get_single(key, result, owner))
|
||||
return true;
|
||||
if(get_single(key, result, mirror))
|
||||
return true;
|
||||
|
||||
return false; // didn't find it
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool DualLookup<T>::contains(const T &key)
|
||||
{
|
||||
if(contains_single(key, owner))
|
||||
return true;
|
||||
if(contains_single(key, mirror))
|
||||
return true;
|
||||
|
||||
return false; // didn't find it
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool DualLookup<T>::get_single(T key, T &result, const std::unordered_map<T, T> &umap)
|
||||
{
|
||||
auto i = umap.find(key);
|
||||
if(i == umap.end())
|
||||
return false;
|
||||
|
||||
result = i->second;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool DualLookup<T>::contains_single(const T &key, const std::unordered_map<T, T> &umap)
|
||||
{
|
||||
return umap.find(key) != umap.end();
|
||||
}
|
||||
|
||||
#endif
|
5
Makefile
Normal file
5
Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
test: run-tests
|
||||
./run-tests
|
||||
|
||||
run-tests: tests-main.cpp main.cpp DualLookup.h
|
||||
clang++ -std=c++11 tests-main.cpp main.cpp -o run-tests
|
60
main.cpp
Normal file
60
main.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include "DualLookup.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
TEST_CASE("all tests", "all") {
|
||||
DualLookup<int> container;
|
||||
DualLookup<std::string> string_container;
|
||||
|
||||
SECTION ("allow add") {
|
||||
REQUIRE(container.add(1, 2));
|
||||
REQUIRE(string_container.add("1", "2"));
|
||||
|
||||
SECTION ("no duplicates") {
|
||||
REQUIRE_FALSE(container.add(1, 2));
|
||||
REQUIRE_FALSE(container.add(2, 1));
|
||||
REQUIRE_FALSE(container.add(1, 3));
|
||||
REQUIRE_FALSE(container.add(2, 3));
|
||||
REQUIRE_FALSE(container.add(3, 1));
|
||||
REQUIRE_FALSE(container.add(3, 2));
|
||||
REQUIRE_FALSE(string_container.add("1", "2"));
|
||||
REQUIRE_FALSE(string_container.add("2", "1"));
|
||||
REQUIRE_FALSE(string_container.add("1", "3"));
|
||||
REQUIRE_FALSE(string_container.add("2", "3"));
|
||||
REQUIRE_FALSE(string_container.add("3", "1"));
|
||||
REQUIRE_FALSE(string_container.add("3", "2"));
|
||||
}
|
||||
|
||||
SECTION ("searches") {
|
||||
bool rtn;
|
||||
int container_result;
|
||||
std::string string_container_result;
|
||||
|
||||
SECTION ("found and not found") {
|
||||
REQUIRE(container.contains(1));
|
||||
REQUIRE(string_container.contains("1"));
|
||||
REQUIRE_FALSE(container.contains(10));
|
||||
REQUIRE_FALSE(string_container.contains("10"));
|
||||
}
|
||||
|
||||
SECTION ("not found in container and unedited") {
|
||||
container_result = 10;
|
||||
string_container_result = "10";
|
||||
REQUIRE_FALSE(container.get(20, container_result));
|
||||
REQUIRE(container_result == 10);
|
||||
REQUIRE_FALSE(string_container.get("20", string_container_result));
|
||||
REQUIRE(string_container_result == "10");
|
||||
}
|
||||
|
||||
SECTION ("in container and set") {
|
||||
container_result = 0;
|
||||
REQUIRE(container.get(1, container_result));
|
||||
REQUIRE(container_result == 2);
|
||||
REQUIRE(string_container.get("1", string_container_result));
|
||||
REQUIRE(string_container_result == "2");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
2
tests-main.cpp
Normal file
2
tests-main.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
Loading…
Reference in New Issue
Block a user