Added unordered_set, unordered_multiset, unordered_multimap

This commit is contained in:
John Wellbelove 2016-02-21 21:11:46 +00:00
parent 3e283a5d33
commit 02aa427e6b
11 changed files with 5005 additions and 0 deletions

View File

@ -1047,6 +1047,48 @@ namespace etl
return end();
}
//*********************************************************************
/// Returns a range containing all elements with key key in the container.
/// The range is defined by two iterators, the first pointing to the first
/// element of the wanted range and the second pointing past the last
/// element of the range.
///\param key The key to search for.
///\return An iterator pair to the range of elements if the key exists, otherwise end().
//*********************************************************************
std::pair<iterator, iterator> equal_range(const key_value_parameter_t& key)
{
iterator first = find(key);
iterator last = first;
if (last != end())
{
++last;
}
return std::pair<iterator, iterator>(first, last);
}
//*********************************************************************
/// Returns a range containing all elements with key key in the container.
/// The range is defined by two iterators, the first pointing to the first
/// element of the wanted range and the second pointing past the last
/// element of the range.
///\param key The key to search for.
///\return A const iterator pair to the range of elements if the key exists, otherwise end().
//*********************************************************************
std::pair<const_iterator, const_iterator> equal_range(const key_value_parameter_t& key) const
{
const_iterator first = find(key);
const_iterator last = first;
if (last != end())
{
++last;
}
return std::pair<const_iterator, const_iterator>(first, last);
}
//*************************************************************************
/// Gets the size of the unordered_map.
//*************************************************************************

1191
iunordered_multimap.h Normal file

File diff suppressed because it is too large Load Diff

1183
iunordered_multiset.h Normal file

File diff suppressed because it is too large Load Diff

1157
iunordered_set.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -517,6 +517,58 @@ namespace
CHECK_EQUAL(0, count);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_equal_range)
{
DataNDC data(initial_data.begin(), initial_data.end());
std::pair<DataNDC::iterator, DataNDC::iterator> result;
result = data.equal_range(K0);
CHECK(result.first == data.begin());
CHECK(result.second != data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(result.first->first, K0);
result = data.equal_range(K3);
CHECK(result.first != data.begin());
CHECK(result.second != data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(result.first->first, K3);
result = data.equal_range(K9);
CHECK(result.first != data.begin());
CHECK(result.second == data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(result.first->first, K9);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_equal_range_const)
{
const DataNDC data(initial_data.begin(), initial_data.end());
std::pair<DataNDC::const_iterator, DataNDC::const_iterator> result;
result = data.equal_range(K0);
CHECK(result.first == data.begin());
CHECK(result.second != data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(result.first->first, K0);
result = data.equal_range(K3);
CHECK(result.first != data.begin());
CHECK(result.second != data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(result.first->first, K3);
result = data.equal_range(K9);
CHECK(result.first != data.begin());
CHECK(result.second == data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(result.first->first, K9);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_equal)
{

View File

@ -0,0 +1,592 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2016 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#include <UnitTest++/UnitTest++.h>
#include <map>
#include <array>
#include <algorithm>
#include <utility>
#include <iterator>
#include <string>
#include <vector>
#include <numeric>
#include "data.h"
#include "../unordered_multimap.h"
namespace
{
//*************************************************************************
struct simple_hash
{
size_t operator ()(const std::string& text) const
{
return std::accumulate(text.begin(), text.end(), 0);
}
};
//*************************************************************************
template <typename T1, typename T2>
bool Check_Equal(T1 begin1, T1 end1, T2 begin2)
{
while (begin1 != end1)
{
if ((begin1->first != begin2->first) || (begin1->second != begin2->second))
{
return false;
}
++begin1;
++begin2;
}
return true;
}
SUITE(test_unordered_multimap)
{
static const size_t SIZE = 10;
typedef TestDataDC<std::string> DC;
typedef TestDataNDC<std::string> NDC;
typedef std::pair<std::string, DC> ElementDC;
typedef std::pair<std::string, NDC> ElementNDC;
typedef etl::unordered_multimap<std::string, DC, SIZE, simple_hash> DataDC;
typedef etl::unordered_multimap<std::string, NDC, SIZE, simple_hash> DataNDC;
typedef etl::iunordered_multimap<std::string, NDC, simple_hash> IDataNDC;
NDC N0 = NDC("A");
NDC N1 = NDC("B");
NDC N2 = NDC("C");
NDC N3 = NDC("D");
NDC N4 = NDC("E");
NDC N5 = NDC("F");
NDC N6 = NDC("G");
NDC N7 = NDC("H");
NDC N8 = NDC("I");
NDC N9 = NDC("J");
NDC N10 = NDC("K");
NDC N11 = NDC("L");
NDC N12 = NDC("M");
NDC N13 = NDC("N");
NDC N14 = NDC("O");
NDC N15 = NDC("P");
NDC N16 = NDC("Q");
NDC N17 = NDC("R");
NDC N18 = NDC("S");
NDC N19 = NDC("T");
const char* K0 = "FF"; // 0
const char* K1 = "FG"; // 1
const char* K2 = "FH"; // 2
const char* K3 = "FI"; // 3
const char* K4 = "FJ"; // 4
const char* K5 = "FK"; // 5
const char* K6 = "FL"; // 6
const char* K7 = "FM"; // 7
const char* K8 = "FN"; // 8
const char* K9 = "FO"; // 9
const char* K10 = "FP"; // 0
const char* K11 = "FQ"; // 1
const char* K12 = "FR"; // 2
const char* K13 = "FS"; // 3
const char* K14 = "FT"; // 4
const char* K15 = "FU"; // 5
const char* K16 = "FV"; // 6
const char* K17 = "FW"; // 7
const char* K18 = "FX"; // 8
const char* K19 = "FY"; // 9
std::string K[] = { K0, K1, K2, K3, K4, K5, K6, K7, K8, K9, K10, K11, K12, K13, K14, K15, K16, K17, K18, K19 };
std::vector<ElementNDC> initial_data;
std::vector<ElementNDC> excess_data;
std::vector<ElementNDC> different_data;
std::vector<ElementNDC> equal_data;
//*************************************************************************
template <typename T1, typename T2>
bool Check_Equal(T1 begin1, T1 end1, T2 begin2)
{
while (begin1 != end1)
{
if ((begin1->first != begin2->first) || (begin1->second != begin2->second))
{
return false;
}
++begin1;
++begin2;
}
return true;
}
//*************************************************************************
struct SetupFixture
{
SetupFixture()
{
ElementNDC n[] =
{
ElementNDC(K0, N0), ElementNDC(K1, N1), ElementNDC(K2, N2), ElementNDC(K3, N3), ElementNDC(K4, N4),
ElementNDC(K5, N5), ElementNDC(K6, N6), ElementNDC(K7, N7), ElementNDC(K8, N8), ElementNDC(K9, N9)
};
ElementNDC n2[] =
{
ElementNDC(K0, N0), ElementNDC(K1, N1), ElementNDC(K2, N2), ElementNDC(K3, N3), ElementNDC(K4, N4),
ElementNDC(K5, N5), ElementNDC(K6, N6), ElementNDC(K7, N7), ElementNDC(K8, N8), ElementNDC(K9, N9),
ElementNDC(K10, N10)
};
ElementNDC n3[] =
{
ElementNDC(K10, N10), ElementNDC(K11, N11), ElementNDC(K12, N12), ElementNDC(K13, N13), ElementNDC(K14, N14),
ElementNDC(K15, N15), ElementNDC(K16, N16), ElementNDC(K17, N17), ElementNDC(K18, N18), ElementNDC(K19, N19)
};
ElementNDC n4[] =
{
ElementNDC(K10, N10), ElementNDC(K11, N11), ElementNDC(K11, N12), ElementNDC(K11, N13), ElementNDC(K12, N14)
};
initial_data.assign(std::begin(n), std::end(n));
excess_data.assign(std::begin(n2), std::end(n2));
different_data.assign(std::begin(n3), std::end(n3));
equal_data.assign(std::begin(n4), std::end(n4));
}
};
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_default_constructor)
{
DataDC data;
CHECK_EQUAL(data.size(), size_t(0));
CHECK(data.empty());
CHECK_EQUAL(data.max_size(), SIZE);
CHECK(data.begin() == data.end());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_constructor_range)
{
DataNDC data(initial_data.begin(), initial_data.end());
CHECK(data.size() == SIZE);
CHECK(!data.empty());
CHECK(data.full());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_assignment)
{
DataNDC data(initial_data.begin(), initial_data.end());
DataNDC other_data;
other_data = data;
bool isEqual = std::equal(data.begin(),
data.end(),
other_data.begin());
CHECK(isEqual);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_assignment_interface)
{
DataNDC data1(initial_data.begin(), initial_data.end());
DataNDC data2;
IDataNDC& idata1 = data1;
IDataNDC& idata2 = data2;
idata2 = idata1;
bool isEqual = std::equal(data1.begin(),
data1.end(),
data2.begin());
CHECK(isEqual);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_self_assignment)
{
DataNDC data(initial_data.begin(), initial_data.end());
DataNDC other_data(data);
other_data = other_data;
bool isEqual = std::equal(data.begin(),
data.end(),
other_data.begin());
CHECK(isEqual);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_empty_full)
{
DataNDC data;
CHECK(!data.full());
CHECK(data.empty());
data.insert(initial_data.begin(), initial_data.end());
CHECK(data.full());
CHECK(!data.empty());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_assign_range)
{
DataNDC data;
data.assign(initial_data.begin(), initial_data.end());
DataNDC::iterator idata;
for (size_t i = 0; i < 10; ++i)
{
idata = data.find(K[i]);
CHECK(idata != data.end());
}
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_insert_value)
{
DataNDC data;
data.insert(DataNDC::value_type(K0, N0)); // Inserted
data.insert(DataNDC::value_type(K2, N2)); // Inserted
data.insert(DataNDC::value_type(K1, N1)); // Inserted
data.insert(DataNDC::value_type(K11, N1)); // Duplicate hash. Inserted
data.insert(DataNDC::value_type(K1, N3)); // Duplicate key. Inserted
CHECK_EQUAL(5U, data.size());
DataNDC::iterator idata;
idata = data.find(K0);
std::string k = idata->first;
NDC n = idata->second;
CHECK(idata != data.end());
CHECK(idata->first == K0);
CHECK(idata->second == N0);
idata = data.find(K1);
CHECK(idata != data.end());
CHECK(idata->first == K1);
CHECK(idata->second == N3);
// The other value with key == K1
++idata;
CHECK(idata != data.end());
CHECK(idata->first == K1);
CHECK(idata->second == N1);
idata = data.find(K2);
CHECK(idata != data.end());
CHECK(idata->first == K2);
CHECK(idata->second == N2);
idata = data.find(K11);
CHECK(idata != data.end());
CHECK(idata->first == K11);
CHECK(idata->second == N1);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_insert_value_excess)
{
DataNDC data(initial_data.begin(), initial_data.end());
CHECK_THROW(data.insert(std::make_pair(K10, N10)), etl::unordered_multimap_full);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_insert_range)
{
DataNDC data;
data.insert(initial_data.begin(), initial_data.end());
for (size_t i = 0; i < data.size(); ++i)
{
DataNDC::iterator idata = data.find(initial_data[i].first);
CHECK(idata != data.end());
}
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_insert_range_excess)
{
DataNDC data;
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::unordered_multimap_full);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_erase_key)
{
DataNDC data(equal_data.begin(), equal_data.end());
size_t count = data.erase(K10);
CHECK_EQUAL(1, count);
DataNDC::iterator idata = data.find(K10);
CHECK(idata == data.end());
count = data.erase(K11);
CHECK_EQUAL(3, count);
idata = data.find(K11);
CHECK(idata == data.end());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_erase_single)
{
DataNDC data(initial_data.begin(), initial_data.end());
DataNDC::const_iterator idata = data.find(K5);
DataNDC::const_iterator inext = idata;
++inext;
DataNDC::const_iterator iafter = data.erase(idata);
idata = data.find(K5);
CHECK(idata == data.end());
CHECK(inext == iafter);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_erase_range)
{
DataNDC data(initial_data.begin(), initial_data.end());
DataNDC::iterator idata = data.find(K5);
DataNDC::iterator idata_end = data.find(K8);
idata = data.erase(idata, idata_end); // Erase K5, K6, K7
CHECK(idata == data.find(K8));
idata = data.find(K0);
CHECK(idata != data.end());
idata = data.find(K1);
CHECK(idata != data.end());
idata = data.find(K2);
CHECK(idata != data.end());
idata = data.find(K3);
CHECK(idata != data.end());
idata = data.find(K4);
CHECK(idata != data.end());
idata = data.find(K5);
CHECK(idata == data.end());
idata = data.find(K6);
CHECK(idata == data.end());
idata = data.find(K7);
CHECK(idata == data.end());
idata = data.find(K8);
CHECK(idata != data.end());
idata = data.find(K9);
CHECK(idata != data.end());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_clear)
{
DataNDC data(initial_data.begin(), initial_data.end());
data.clear();
CHECK_EQUAL(data.size(), size_t(0));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_count_key)
{
DataNDC data(equal_data.begin(), equal_data.end());
size_t count = data.count(K10);
CHECK_EQUAL(1, count);
count = data.count(K11);
CHECK_EQUAL(3, count);
count = data.count(K1);
CHECK_EQUAL(0, count);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_find_const)
{
const DataNDC data(initial_data.begin(), initial_data.end());
DataNDC::const_iterator idata = data.find(K3);
CHECK(idata != data.end());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_equal_range)
{
DataNDC data(equal_data.begin(), equal_data.end());
std::pair<DataNDC::iterator, DataNDC::iterator> result;
result = data.equal_range(K10);
CHECK(result.first == data.begin());
CHECK(result.second != data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(result.first->first, K10);
result = data.equal_range(K11);
CHECK(result.first != data.begin());
CHECK(result.second != data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 3);
CHECK_EQUAL(result.first->first, K11);
result = data.equal_range(K12);
CHECK(result.first != data.begin());
CHECK(result.second == data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(result.first->first, K12);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_equal_range_const)
{
const DataNDC data(equal_data.begin(), equal_data.end());
std::pair<DataNDC::const_iterator, DataNDC::const_iterator> result;
result = data.equal_range(K10);
CHECK(result.first == data.begin());
CHECK(result.second != data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(result.first->first, K10);
result = data.equal_range(K11);
CHECK(result.first != data.begin());
CHECK(result.second != data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 3);
CHECK_EQUAL(result.first->first, K11);
result = data.equal_range(K12);
CHECK(result.first != data.begin());
CHECK(result.second == data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(result.first->first, K12);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_equal)
{
const DataNDC initial1(initial_data.begin(), initial_data.end());
const DataNDC initial2(initial_data.begin(), initial_data.end());
CHECK(initial1 == initial2);
const DataNDC different(different_data.begin(), different_data.end());
CHECK(!(initial1 == different));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_not_equal)
{
const DataNDC initial1(initial_data.begin(), initial_data.end());
const DataNDC initial2(initial_data.begin(), initial_data.end());
CHECK(!(initial1 != initial2));
const DataNDC different(different_data.begin(), different_data.end());
CHECK(initial1 != different);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_hash_function)
{
DataNDC data;
DataNDC::hasher hash_function = data.hash_function();
CHECK_EQUAL(simple_hash()(std::string("ABCDEF")), hash_function(std::string("ABCDEF")));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_key_eq_function)
{
DataNDC data;
DataNDC::key_equal key_eq = data.key_eq();
CHECK(key_eq(std::string("ABCDEF"), std::string("ABCDEF")));
CHECK(!key_eq(std::string("ABCDEF"), std::string("ABCDEG")));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_load_factor)
{
// Empty.
DataNDC data;
CHECK_CLOSE(0.0, data.load_factor(), 0.01);
// Half the buckets used.
data.assign(initial_data.begin(), initial_data.begin() + (initial_data.size() / 2));
CHECK_CLOSE(0.5, data.load_factor(), 0.01);
// All of the buckets used.
data.clear();
data.assign(initial_data.begin(), initial_data.end());
CHECK_CLOSE(1.0, data.load_factor(), 0.01);
}
};
}

View File

@ -0,0 +1,522 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2016 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#include <UnitTest++/UnitTest++.h>
#include <set>
#include <array>
#include <algorithm>
#include <utility>
#include <iterator>
#include <string>
#include <vector>
#include <numeric>
#include "data.h"
#include "../unordered_multiset.h"
#include "../checksum.h"
namespace
{
SUITE(test_unordered_multiset)
{
static const size_t SIZE = 10;
typedef TestDataDC<std::string> DC;
typedef TestDataNDC<std::string> NDC;
struct simple_hash
{
size_t operator ()(const NDC& value) const
{
return etl::checksum<size_t>(value.value.begin(), value.value.end());
}
};
typedef etl::unordered_multiset<DC, SIZE, simple_hash> DataDC;
typedef etl::unordered_multiset<NDC, SIZE, simple_hash> DataNDC;
typedef etl::iunordered_multiset<NDC, simple_hash> IDataNDC;
NDC N0 = NDC("FF");
NDC N1 = NDC("FG");
NDC N2 = NDC("FH");
NDC N3 = NDC("FI");
NDC N4 = NDC("FJ");
NDC N5 = NDC("FK");
NDC N6 = NDC("FL");
NDC N7 = NDC("FM");
NDC N8 = NDC("FN");
NDC N9 = NDC("FO");
NDC N10 = NDC("FP");
NDC N11 = NDC("FQ");
NDC N12 = NDC("FR");
NDC N13 = NDC("FS");
NDC N14 = NDC("FT");
NDC N15 = NDC("FU");
NDC N16 = NDC("FV");
NDC N17 = NDC("FW");
NDC N18 = NDC("FX");
NDC N19 = NDC("FY");
std::vector<NDC> initial_data;
std::vector<NDC> excess_data;
std::vector<NDC> different_data;
std::vector<NDC> equal_data;
//*************************************************************************
struct SetupFixture
{
SetupFixture()
{
NDC n[] =
{
N0, N1, N2, N3, N4, N5, N6, N7, N8, N9
};
NDC n2[] =
{
N0, N1, N2, N3, N4, N5, N6, N7, N8, N9, N10
};
NDC n3[] =
{
N10, N11, N12, N13, N14, N15, N16, N17, N18, N19
};
NDC n4[] =
{
N0, N1, N1, N1, N2
};
initial_data.assign(std::begin(n), std::end(n));
excess_data.assign(std::begin(n2), std::end(n2));
different_data.assign(std::begin(n3), std::end(n3));
equal_data.assign(std::begin(n4), std::end(n4));
}
};
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_default_constructor)
{
DataDC data;
CHECK_EQUAL(data.size(), size_t(0));
CHECK(data.empty());
CHECK_EQUAL(data.max_size(), SIZE);
CHECK(data.begin() == data.end());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_constructor_range)
{
DataNDC data(initial_data.begin(), initial_data.end());
CHECK(data.size() == SIZE);
CHECK(!data.empty());
CHECK(data.full());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_assignment)
{
DataNDC data(initial_data.begin(), initial_data.end());
DataNDC other_data;
other_data = data;
bool isEqual = std::equal(data.begin(),
data.end(),
other_data.begin());
CHECK(isEqual);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_assignment_interface)
{
DataNDC data1(initial_data.begin(), initial_data.end());
DataNDC data2;
IDataNDC& idata1 = data1;
IDataNDC& idata2 = data2;
idata2 = idata1;
bool isEqual = std::equal(data1.begin(),
data1.end(),
data2.begin());
CHECK(isEqual);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_self_assignment)
{
DataNDC data(initial_data.begin(), initial_data.end());
DataNDC other_data(data);
other_data = other_data;
bool isEqual = std::equal(data.begin(),
data.end(),
other_data.begin());
CHECK(isEqual);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_empty_full)
{
DataNDC data;
CHECK(!data.full());
CHECK(data.empty());
data.insert(initial_data.begin(), initial_data.end());
CHECK(data.full());
CHECK(!data.empty());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_assign_range)
{
DataNDC data;
data.assign(initial_data.begin(), initial_data.end());
DataNDC::iterator idata;
for (size_t i = 0; i < 10; ++i)
{
idata = data.find(initial_data[i]);
CHECK(idata != data.end());
}
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_insert_value)
{
DataNDC data;
data.insert(N0); // Inserted
data.insert(N2); // Inserted
data.insert(N1); // Inserted
data.insert(N11); // Duplicate hash. Inserted
data.insert(N1); // Duplicate. Inserted
CHECK_EQUAL(5U, data.size());
DataNDC::iterator idata;
idata = data.find(N0);
CHECK(idata != data.end());
CHECK(*idata == N0);
idata = data.find(N1);
CHECK(idata != data.end());
CHECK(*idata == N1);
// The other value with key == N1
++idata;
CHECK(idata != data.end());
CHECK(*idata == N1);
idata = data.find(N2);
CHECK(idata != data.end());
CHECK(*idata == N2);
idata = data.find(N11);
CHECK(idata != data.end());
CHECK(*idata == N11);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_insert_value_excess)
{
DataNDC data(initial_data.begin(), initial_data.end());
CHECK_THROW(data.insert(N10), etl::unordered_multiset_full);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_insert_range)
{
DataNDC data;
data.insert(initial_data.begin(), initial_data.end());
for (size_t i = 0; i < data.size(); ++i)
{
DataNDC::iterator idata = data.find(initial_data[i]);
CHECK(idata != data.end());
}
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_insert_range_excess)
{
DataNDC data;
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::unordered_multiset_full);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_erase_key)
{
DataNDC data(equal_data.begin(), equal_data.end());
size_t count = data.erase(N0);
CHECK_EQUAL(1, count);
DataNDC::iterator idata = data.find(N0);
CHECK(idata == data.end());
count = data.erase(N1);
CHECK_EQUAL(3, count);
idata = data.find(N1);
CHECK(idata == data.end());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_erase_single)
{
DataNDC data(initial_data.begin(), initial_data.end());
DataNDC::const_iterator idata = data.find(N5);
DataNDC::const_iterator inext = idata;
++inext;
DataNDC::const_iterator iafter = data.erase(idata);
idata = data.find(N5);
CHECK(idata == data.end());
CHECK(inext == iafter);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_erase_range)
{
DataNDC data(initial_data.begin(), initial_data.end());
DataNDC::iterator idata = data.find(N5);
DataNDC::iterator idata_end = data.find(N8);
std::vector<NDC> test;
test.assign(data.begin(), data.end());
idata = data.erase(idata, idata_end); // Erase N5, N6, N7
CHECK(idata == data.find(N8));
test.assign(data.begin(), data.end());
idata = data.find(N0);
CHECK(idata != data.end());
idata = data.find(N1);
CHECK(idata != data.end());
idata = data.find(N2);
CHECK(idata != data.end());
idata = data.find(N3);
CHECK(idata != data.end());
idata = data.find(N4);
CHECK(idata != data.end());
idata = data.find(N5);
CHECK(idata == data.end());
idata = data.find(N6);
CHECK(idata == data.end());
idata = data.find(N7);
CHECK(idata == data.end());
idata = data.find(N8);
CHECK(idata != data.end());
idata = data.find(N9);
CHECK(idata != data.end());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_clear)
{
DataNDC data(initial_data.begin(), initial_data.end());
data.clear();
CHECK_EQUAL(data.size(), size_t(0));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_count_key)
{
DataNDC data(equal_data.begin(), equal_data.end());
size_t count = data.count(N0);
CHECK_EQUAL(1, count);
count = data.count(N1);
CHECK_EQUAL(3, count);
count = data.count(N10);
CHECK_EQUAL(0, count);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_find_const)
{
const DataNDC data(initial_data.begin(), initial_data.end());
DataNDC::const_iterator idata = data.find(N3);
CHECK(idata != data.end());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_equal_range)
{
DataNDC data(equal_data.begin(), equal_data.end());
std::pair<DataNDC::iterator, DataNDC::iterator> result;
result = data.equal_range(N0);
CHECK(result.first == data.begin());
CHECK(result.second != data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(*result.first, N0);
result = data.equal_range(N1);
CHECK(result.first != data.begin());
CHECK(result.second != data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 3);
CHECK_EQUAL(*result.first, N1);
result = data.equal_range(N2);
CHECK(result.first != data.begin());
CHECK(result.second == data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(*result.first, N2);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_equal_range_const)
{
const DataNDC data(equal_data.begin(), equal_data.end());
std::pair<DataNDC::const_iterator, DataNDC::const_iterator> result;
result = data.equal_range(N0);
CHECK(result.first == data.begin());
CHECK(result.second != data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(*result.first, N0);
result = data.equal_range(N1);
CHECK(result.first != data.begin());
CHECK(result.second != data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 3);
CHECK_EQUAL(*result.first, N1);
result = data.equal_range(N2);
CHECK(result.first != data.begin());
CHECK(result.second == data.end());
CHECK_EQUAL(std::distance(result.first, result.second), 1);
CHECK_EQUAL(*result.first, N2);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_equal)
{
const DataNDC initial1(initial_data.begin(), initial_data.end());
const DataNDC initial2(initial_data.begin(), initial_data.end());
CHECK(initial1 == initial2);
const DataNDC different(different_data.begin(), different_data.end());
CHECK(!(initial1 == different));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_not_equal)
{
const DataNDC initial1(initial_data.begin(), initial_data.end());
const DataNDC initial2(initial_data.begin(), initial_data.end());
CHECK(!(initial1 != initial2));
const DataNDC different(different_data.begin(), different_data.end());
CHECK(initial1 != different);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_hash_function)
{
DataNDC data;
DataNDC::hasher hash_function = data.hash_function();
CHECK_EQUAL(simple_hash()(std::string("ABCDEF")), hash_function(std::string("ABCDEF")));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_key_eq_function)
{
DataNDC data;
DataNDC::key_equal key_eq = data.key_eq();
CHECK(key_eq(std::string("ABCDEF"), std::string("ABCDEF")));
CHECK(!key_eq(std::string("ABCDEF"), std::string("ABCDEG")));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_load_factor)
{
// Empty.
DataNDC data;
CHECK_CLOSE(0.0, data.load_factor(), 0.01);
// Half the buckets used.
data.assign(initial_data.begin(), initial_data.begin() + (initial_data.size() / 2));
CHECK_CLOSE(0.5, data.load_factor(), 0.01);
// All of the buckets used.
data.clear();
data.assign(initial_data.begin(), initial_data.end());
CHECK_CLOSE(1.0, data.load_factor(), 0.01);
}
};
}

View File

@ -215,6 +215,8 @@
<ClInclude Include="..\..\istack.h" />
<ClInclude Include="..\..\container.h" />
<ClInclude Include="..\..\iunordered_map.h" />
<ClInclude Include="..\..\iunordered_multimap.h" />
<ClInclude Include="..\..\iunordered_set.h" />
<ClInclude Include="..\..\ivector.h" />
<ClInclude Include="..\..\jenkins.h" />
<ClInclude Include="..\..\largest.h" />
@ -263,6 +265,7 @@
<ClInclude Include="..\..\static_assert.h" />
<ClInclude Include="..\..\type_traits.h" />
<ClInclude Include="..\..\unordered_map.h" />
<ClInclude Include="..\..\unordered_multiset.h" />
<ClInclude Include="..\..\unordered_set.h" />
<ClInclude Include="..\..\variant.h" />
<ClInclude Include="..\..\vector.h" />
@ -368,6 +371,8 @@
<ClCompile Include="..\test_stack.cpp" />
<ClCompile Include="..\test_type_traits.cpp" />
<ClCompile Include="..\test_unordered_map.cpp" />
<ClCompile Include="..\test_unordered_multimap.cpp" />
<ClCompile Include="..\test_unordered_multiset.cpp" />
<ClCompile Include="..\test_unordered_set.cpp" />
<ClCompile Include="..\test_variant.cpp" />
<ClCompile Include="..\test_vector.cpp" />

View File

@ -468,6 +468,15 @@
<ClInclude Include="..\..\unordered_set.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\iunordered_multimap.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\iunordered_set.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\unordered_multiset.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\unittest-cpp\UnitTest++\AssertException.cpp">
@ -725,6 +734,12 @@
<ClCompile Include="..\test_unordered_set.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\test_unordered_multimap.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\test_unordered_multiset.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\Doxyfile">

123
unordered_multimap.h Normal file
View File

@ -0,0 +1,123 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2016 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_UNORDERED_MULTIMAP__
#define __ETL_UNORDERED_MULTIMAP__
#include <stddef.h>
#include <iterator>
#include <functional>
#include "iunordered_multimap.h"
#include "container.h"
#include "pool.h"
#include "vector.h"
#include "intrusive_forward_list.h"
#include "hash.h"
//*****************************************************************************
///\defgroup unordered_multimap unordered_multimap
/// A unordered_multimap with the capacity defined at compile time.
///\ingroup containers
//*****************************************************************************
namespace etl
{
//*************************************************************************
/// A templated unordered_multimap implementation that uses a fixed size buffer.
//*************************************************************************
template <typename TKey, typename TValue, const size_t MAX_SIZE_, typename THash = etl::hash<TKey>, typename TKeyEqual = std::equal_to<TKey> >
class unordered_multimap : public iunordered_multimap<TKey, TValue, THash, TKeyEqual>
{
private:
typedef iunordered_multimap<TKey, TValue, THash, TKeyEqual> base;
public:
static const size_t MAX_SIZE = MAX_SIZE_;
//*************************************************************************
/// Default constructor.
//*************************************************************************
unordered_multimap()
: base(node_pool, buckets)
{
base::initialise();
}
//*************************************************************************
/// Copy constructor.
//*************************************************************************
unordered_multimap(const unordered_multimap& other)
: base(node_pool, buckets)
{
base::assign(other.cbegin(), other.cend());
}
//*************************************************************************
/// Constructor, from an iterator range.
///\tparam TIterator The iterator type.
///\param first The iterator to the first element.
///\param last The iterator to the last element + 1.
//*************************************************************************
template <typename TIterator>
unordered_multimap(TIterator first, TIterator last)
: base(node_pool, buckets)
{
base::assign(first, last);
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
unordered_multimap& operator = (const unordered_multimap& rhs)
{
// Skip if doing self assignment
if (this != &rhs)
{
base::assign(rhs.cbegin(), rhs.cend());
}
return *this;
}
private:
/// The pool of nodes used for the unordered_multimap.
etl::pool<typename base::node_t, MAX_SIZE> node_pool;
/// The buckets of node lists.
etl::vector<etl::intrusive_forward_list<typename base::node_t>, MAX_SIZE> buckets;
};
}
#endif

123
unordered_multiset.h Normal file
View File

@ -0,0 +1,123 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2016 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_UNORDERED_MULTISET__
#define __ETL_UNORDERED_MULTISET__
#include <stddef.h>
#include <iterator>
#include <functional>
#include "iunordered_multiset.h"
#include "container.h"
#include "pool.h"
#include "vector.h"
#include "intrusive_forward_list.h"
#include "hash.h"
//*****************************************************************************
///\defgroup unordered_multiset unordered_multiset
/// A unordered_multiset with the capacity defined at compile time.
///\ingroup containers
//*****************************************************************************
namespace etl
{
//*************************************************************************
/// A templated unordered_multiset implementation that uses a fixed size buffer.
//*************************************************************************
template <typename TKey, const size_t MAX_SIZE_, typename THash = etl::hash<TKey>, typename TKeyEqual = std::equal_to<TKey> >
class unordered_multiset : public iunordered_multiset<TKey, THash, TKeyEqual>
{
private:
typedef iunordered_multiset<TKey, THash, TKeyEqual> base;
public:
static const size_t MAX_SIZE = MAX_SIZE_;
//*************************************************************************
/// Default constructor.
//*************************************************************************
unordered_multiset()
: base(node_pool, buckets)
{
base::initialise();
}
//*************************************************************************
/// Copy constructor.
//*************************************************************************
unordered_multiset(const unordered_multiset& other)
: base(node_pool, buckets)
{
base::assign(other.cbegin(), other.cend());
}
//*************************************************************************
/// Constructor, from an iterator range.
///\tparam TIterator The iterator type.
///\param first The iterator to the first element.
///\param last The iterator to the last element + 1.
//*************************************************************************
template <typename TIterator>
unordered_multiset(TIterator first, TIterator last)
: base(node_pool, buckets)
{
base::assign(first, last);
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
unordered_multiset& operator = (const unordered_multiset& rhs)
{
// Skip if doing self assignment
if (this != &rhs)
{
base::assign(rhs.cbegin(), rhs.cend());
}
return *this;
}
private:
/// The pool of nodes used for the unordered_multiset.
etl::pool<typename base::node_t, MAX_SIZE> node_pool;
/// The buckets of node lists.
etl::vector<etl::intrusive_forward_list<typename base::node_t>, MAX_SIZE> buckets;
};
}
#endif