Merge remote-tracking branch 'origin/development'

This commit is contained in:
John Wellbelove 2016-02-25 20:36:41 +00:00
commit 09f311c160
20 changed files with 6259 additions and 112 deletions

272
ilist.h
View File

@ -72,9 +72,9 @@ namespace etl
//*************************************************************************
/// The data node element in the list.
//*************************************************************************
struct Data_Node : public Node
struct data_node_t : public node_t
{
explicit Data_Node(parameter_t value)
explicit data_node_t(parameter_t value)
: value(value)
{
}
@ -85,38 +85,38 @@ namespace etl
private:
/// The pool of data nodes used in the list.
etl::ipool<Data_Node>* p_node_pool;
etl::ipool<data_node_t>* p_node_pool;
//*************************************************************************
/// Downcast a Node* to a Data_Node*
/// Downcast a node_t* to a data_node_t*
//*************************************************************************
static Data_Node* data_cast(Node* p_node)
static data_node_t* data_cast(node_t* p_node)
{
return static_cast<Data_Node*>(p_node);
return static_cast<data_node_t*>(p_node);
}
//*************************************************************************
/// Downcast a Node& to a Data_Node&
/// Downcast a node_t& to a data_node_t&
//*************************************************************************
static Data_Node& data_cast(Node& node)
static data_node_t& data_cast(node_t& node)
{
return static_cast<Data_Node&>(node);
return static_cast<data_node_t&>(node);
}
//*************************************************************************
/// Downcast a const Node* to a const Data_Node*
/// Downcast a const node_t* to a const data_node_t*
//*************************************************************************
static const Data_Node* data_cast(const Node* p_node)
static const data_node_t* data_cast(const node_t* p_node)
{
return static_cast<const Data_Node*>(p_node);
return static_cast<const data_node_t*>(p_node);
}
//*************************************************************************
/// Downcast a const Node& to a const Data_Node&
/// Downcast a const node_t& to a const data_node_t&
//*************************************************************************
static const Data_Node& data_cast(const Node& node)
static const data_node_t& data_cast(const node_t& node)
{
return static_cast<const Data_Node&>(node);
return static_cast<const data_node_t&>(node);
}
public:
@ -135,7 +135,7 @@ namespace etl
{
}
iterator(Node& node)
iterator(node_t& node)
: p_node(&node)
{
}
@ -219,7 +219,7 @@ namespace etl
private:
Node* p_node;
node_t* p_node;
};
//*************************************************************************
@ -236,12 +236,12 @@ namespace etl
{
}
const_iterator(Node& node)
const_iterator(node_t& node)
: p_node(&node)
{
}
const_iterator(const Node& node)
const_iterator(const node_t& node)
: p_node(&node)
{
}
@ -298,7 +298,7 @@ namespace etl
return ilist::data_cast(p_node)->value;
}
const Data_Node* operator ->() const
const data_node_t* operator ->() const
{
return p_node;
}
@ -315,7 +315,7 @@ namespace etl
private:
const Node* p_node;
const node_t* p_node;
};
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
@ -352,7 +352,7 @@ namespace etl
//*************************************************************************
const_iterator end() const
{
return const_iterator(static_cast<const Data_Node&>(terminal_node));
return const_iterator(static_cast<const data_node_t&>(terminal_node));
}
//*************************************************************************
@ -368,7 +368,7 @@ namespace etl
//*************************************************************************
const_iterator cend() const
{
return const_iterator(static_cast<const Data_Node&>(terminal_node));
return const_iterator(static_cast<const data_node_t&>(terminal_node));
}
//*************************************************************************
@ -384,7 +384,7 @@ namespace etl
//*************************************************************************
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(static_cast<const Data_Node&>(terminal_node));
return const_reverse_iterator(static_cast<const data_node_t&>(terminal_node));
}
//*************************************************************************
@ -400,7 +400,7 @@ namespace etl
//*************************************************************************
const_reverse_iterator crbegin() const
{
return const_reverse_iterator(static_cast<const Data_Node&>(terminal_node));
return const_reverse_iterator(static_cast<const data_node_t&>(terminal_node));
}
//*************************************************************************
@ -461,7 +461,7 @@ namespace etl
// Add all of the elements.
while (first != last)
{
Data_Node& data_node = allocate_data_node(*first);
data_node_t& data_node = allocate_data_node(*first);
join(get_tail(), data_node);
join(data_node, terminal_node);
++first;
@ -483,7 +483,7 @@ namespace etl
// Add all of the elements.
while (current_size < n)
{
Data_Node& data_node = allocate_data_node(value);
data_node_t& data_node = allocate_data_node(value);
join(*terminal_node.previous, data_node);
join(data_node, terminal_node);
++current_size;
@ -498,7 +498,7 @@ namespace etl
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(list_full));
#endif
Data_Node& data_node = allocate_data_node(T());
data_node_t& data_node = allocate_data_node(T());
insert_node(get_head(), data_node);
}
@ -510,7 +510,7 @@ namespace etl
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(list_full));
#endif
Node& data_node = allocate_data_node(value);
node_t& data_node = allocate_data_node(value);
insert_node(get_head(), data_node);
}
@ -522,7 +522,7 @@ namespace etl
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!empty(), ETL_ERROR(list_empty));
#endif
Node& node = get_head();
node_t& node = get_head();
remove_node(node);
}
@ -534,7 +534,7 @@ namespace etl
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(list_full));
#endif
Data_Node& data_node = allocate_data_node(T());
data_node_t& data_node = allocate_data_node(T());
insert_node(terminal_node, data_node);
}
@ -546,7 +546,7 @@ namespace etl
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(list_full));
#endif
Data_Node& data_node = allocate_data_node(value);
data_node_t& data_node = allocate_data_node(value);
insert_node(terminal_node, data_node);
}
@ -558,7 +558,7 @@ namespace etl
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!empty(), ETL_ERROR(list_empty));
#endif
Node& node = get_tail();
node_t& node = get_tail();
remove_node(node);
}
@ -569,7 +569,7 @@ namespace etl
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
Data_Node& data_node = allocate_data_node(value);
data_node_t& data_node = allocate_data_node(value);
insert_node(*position.p_node, data_node);
return iterator(data_node);
@ -585,7 +585,7 @@ namespace etl
ETL_ASSERT(!full(), ETL_ERROR(list_full));
// Set up the next free node and insert.
Data_Node& data_node = allocate_data_node(value);
data_node_t& data_node = allocate_data_node(value);
insert_node(*position.p_node, data_node);
}
}
@ -601,7 +601,7 @@ namespace etl
ETL_ASSERT(!full(), ETL_ERROR(list_full));
// Set up the next free node and insert.
Data_Node& data_node = allocate_data_node(*first++);
data_node_t& data_node = allocate_data_node(*first++);
insert_node(*position.p_node, data_node);
}
}
@ -624,9 +624,9 @@ namespace etl
//*************************************************************************
iterator erase(iterator first, iterator last)
{
Node* p_first = first.p_node;
Node* p_last = last.p_node;
Node* p_next;
node_t* p_first = first.p_node;
node_t* p_last = last.p_node;
node_t* p_next;
// Join the ends.
join(*(p_first->previous), *p_last);
@ -638,7 +638,7 @@ namespace etl
--current_size;
p_next = p_first->next; // Remember the next node.
destroy_data_node(static_cast<Data_Node&>(*p_first)); // Destroy the current node.
destroy_data_node(static_cast<data_node_t&>(*p_first)); // Destroy the current node.
p_first = p_next; // Move to the next node.
}
@ -763,57 +763,113 @@ namespace etl
}
//*************************************************************************
/// Moves an element from one position to another within the list.
/// Moves the element at position 'from' to the position before 'to'.
/// Splices from another list to this.
//*************************************************************************
void move(const_iterator from, const_iterator to)
void splice(iterator to, ilist& other)
{
if (from == to)
if (&other != this)
{
return; // Can't more to before yourself!
insert(to, other.begin(), other.end());
other.erase(other.begin(), other.end());
}
Node& from_node = const_cast<Node&>(*from.p_node); // We're not changing the value, just it's position.
Node& to_node = const_cast<Node&>(*to.p_node); // We're not changing the value, just it's position.
// Disconnect the node from the list.
join(*from_node.previous, *from_node.next);
// Attach it to the new position.
join(*to_node.previous, from_node);
join(from_node, to_node);
}
//*************************************************************************
/// Moves a range from one position to another within the list.
/// Moves a range at position 'first'/'last' to the position before 'to'.
/// Splices an element from another list to this.
//*************************************************************************
void move(const_iterator first, const_iterator last, const_iterator to)
void splice(iterator to, ilist& other, iterator from)
{
if ((first == to) || (last == to))
if (&other == this)
{
return; // Can't more to before yourself!
if (from != to)
{
// Internal move.
move(to, from);
}
}
else
{
// From another list.
insert(to, *from);
other.erase(from);
}
}
#ifdef _DEBUG
// Check that we are not doing an illegal move!
for (const_iterator item = first; item != last; ++item)
//*************************************************************************
/// Splices a range of elements from another list to this.
//*************************************************************************
void splice(iterator to, ilist& other, iterator first, iterator last)
{
if (&other == this)
{
ETL_ASSERT(item != to, ETL_ERROR(list_iterator));
if (first != to)
{
// Internal move.
move(to, first, last);
}
}
else
{
// From another list.
insert(to, first, last);
other.erase(first, last);
}
}
//*************************************************************************
/// Merge another list into this one. Both lists should be sorted.
//*************************************************************************
void merge(ilist& other)
{
merge(other, std::less<value_type>());
}
//*************************************************************************
/// Merge another list into this one. Both lists should be sorted.
//*************************************************************************
template <typename TCompare>
void merge(ilist& other, TCompare compare)
{
if (!other.empty())
{
#if _DEBUG
ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(list_unsorted));
ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(list_unsorted));
#endif
Node& first_node = const_cast<Node&>(*first.p_node); // We're not changing the value, just it's position.
Node& last_node = const_cast<Node&>(*last.p_node); // We're not changing the value, just it's position.
Node& to_node = const_cast<Node&>(*to.p_node); // We're not changing the value, just it's position.
Node& final_node = *last_node.previous;
ilist::iterator other_begin = other.begin();
ilist::iterator other_end = other.end();
// Disconnect the range from the list.
join(*first_node.previous, last_node);
ilist::iterator this_begin = begin();
ilist::iterator this_end = end();
// Attach it to the new position.
join(*to_node.previous, first_node);
join(final_node, to_node);
while ((this_begin != this_end) && (other_begin != other_end))
{
// Find the place to insert.
while ((this_begin != this_end) && !(compare(*other_begin, *this_begin)))
{
++this_begin;
}
// Insert.
if (this_begin != this_end)
{
while ((other_begin != other_end) && (compare(*other_begin, *this_begin)))
{
insert(this_begin, *other_begin);
++other_begin;
}
}
}
// Any left over?
if ((this_begin == this_end) && (other_begin != other_end))
{
insert(this_end, other_begin, other_end);
}
other.clear();
}
}
//*************************************************************************
@ -956,7 +1012,7 @@ namespace etl
//*************************************************************************
/// Constructor.
//*************************************************************************
ilist(etl::ipool<Data_Node>& node_pool, size_t max_size_)
ilist(etl::ipool<data_node_t>& node_pool, size_t max_size_)
: list_base(max_size_),
p_node_pool(&node_pool)
{
@ -978,33 +1034,87 @@ namespace etl
private:
//*************************************************************************
/// Moves an element from one position to another within the list.
/// Moves the element at position 'from' to the position before 'to'.
//*************************************************************************
void move(iterator to, iterator from)
{
if (from == to)
{
return; // Can't more to before yourself!
}
node_t& from_node = *from.p_node;
node_t& to_node = *to.p_node;
// Disconnect the node from the list.
join(*from_node.previous, *from_node.next);
// Attach it to the new position.
join(*to_node.previous, from_node);
join(from_node, to_node);
}
//*************************************************************************
/// Moves a range from one position to another within the list.
/// Moves a range at position 'first'/'last' to the position before 'to'.
//*************************************************************************
void move(iterator to, iterator first, iterator last)
{
if ((first == to) || (last == to))
{
return; // Can't more to before yourself!
}
#ifdef _DEBUG
// Check that we are not doing an illegal move!
for (const_iterator item = first; item != last; ++item)
{
ETL_ASSERT(item != to, ETL_ERROR(list_iterator));
}
#endif
node_t& first_node = *first.p_node;
node_t& last_node = *last.p_node;
node_t& to_node = *to.p_node;
node_t& final_node = *last_node.previous;
// Disconnect the range from the list.
join(*first_node.previous, last_node);
// Attach it to the new position.
join(*to_node.previous, first_node);
join(final_node, to_node);
}
//*************************************************************************
/// Remove a node.
//*************************************************************************
void remove_node(Node& node)
void remove_node(node_t& node)
{
// Disconnect the node from the list.
join(*node.previous, *node.next);
// Destroy the pool object.
destroy_data_node(static_cast<Data_Node&>(node));
destroy_data_node(static_cast<data_node_t&>(node));
// One less.
--current_size;
}
//*************************************************************************
/// Allocate a Data_Node.
/// Allocate a data_node_t.
//*************************************************************************
Data_Node& allocate_data_node(parameter_t value) const
data_node_t& allocate_data_node(parameter_t value) const
{
return *(p_node_pool->allocate(Data_Node(value)));
return *(p_node_pool->allocate(data_node_t(value)));
}
//*************************************************************************
/// Destroy a Data_Node.
/// Destroy a data_node_t.
//*************************************************************************
void destroy_data_node(Data_Node& node) const
void destroy_data_node(data_node_t& node) const
{
p_node_pool->release(&node);
}

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

2
list.h
View File

@ -130,7 +130,7 @@ namespace etl
private:
/// The pool of nodes used in the list.
etl::pool<typename list::Data_Node, MAX_SIZE> node_pool;
etl::pool<typename list::data_node_t, MAX_SIZE> node_pool;
};
}

View File

@ -100,6 +100,20 @@ namespace etl
}
};
//***************************************************************************
/// Unsorted exception for the list.
///\ingroup list
//***************************************************************************
class list_unsorted : public list_exception
{
public:
list_unsorted(string_type file_name, numeric_type line_number)
: list_exception(ETL_ERROR_TEXT("list:unsorted", ETL_FILE"D"), file_name, line_number)
{
}
};
//***************************************************************************
/// The base class for all lists.
///\ingroup list
@ -113,12 +127,12 @@ namespace etl
//*************************************************************************
/// The node element in the list.
//*************************************************************************
struct Node
struct node_t
{
//***********************************************************************
/// Constructor
//***********************************************************************
Node()
node_t()
: previous(nullptr),
next(nullptr)
{
@ -132,8 +146,8 @@ namespace etl
std::swap(previous, next);
}
Node* previous;
Node* next;
node_t* previous;
node_t* next;
};
//*************************************************************************
@ -146,7 +160,7 @@ namespace etl
return;
}
Node* p_node = terminal_node.next;
node_t* p_node = terminal_node.next;
while (p_node != &terminal_node)
{
@ -204,7 +218,7 @@ namespace etl
//*************************************************************************
/// Get the head node.
//*************************************************************************
Node& get_head()
node_t& get_head()
{
return *terminal_node.next;
}
@ -212,7 +226,7 @@ namespace etl
//*************************************************************************
/// Get the head node.
//*************************************************************************
const Node& get_head() const
const node_t& get_head() const
{
return *terminal_node.next;
}
@ -220,7 +234,7 @@ namespace etl
//*************************************************************************
/// Get the tail node.
//*************************************************************************
Node& get_tail()
node_t& get_tail()
{
return *terminal_node.previous;
}
@ -228,7 +242,7 @@ namespace etl
//*************************************************************************
/// Get the tail node.
//*************************************************************************
const Node& get_tail() const
const node_t& get_tail() const
{
return *terminal_node.previous;
}
@ -236,7 +250,7 @@ namespace etl
//*************************************************************************
/// Insert a node before 'position'.
//*************************************************************************
void insert_node(Node& position, Node& node)
void insert_node(node_t& position, node_t& node)
{
// Connect to the list.
join(*position.previous, node);
@ -257,7 +271,7 @@ namespace etl
//*************************************************************************
/// Join two nodes.
//*************************************************************************
void join(Node& left, Node& right)
void join(node_t& left, node_t& right)
{
left.next = &right;
right.previous = &left;
@ -274,7 +288,7 @@ namespace etl
}
Node terminal_node; ///< The node that acts as the list start and end.
node_t terminal_node; ///< The node that acts as the list start and end.
size_type current_size; ///< The number of the used nodes.
const size_type MAX_SIZE; ///< The maximum size of the list.
};

View File

@ -54,6 +54,11 @@ public:
return value < other.value;
}
bool operator > (const TestDataDC& other) const
{
return value > other.value;
}
T value;
};
@ -97,6 +102,11 @@ public:
return value < other.value;
}
bool operator > (const TestDataNDC& other) const
{
return value > other.value;
}
T value;
};

View File

@ -183,6 +183,9 @@ namespace
CHECK(data0.empty());
CHECK(data1.empty());
CHECK(data0.begin() == data0.end());
CHECK(data1.begin() == data1.end());
}
//*************************************************************************

View File

@ -180,6 +180,9 @@ namespace
CHECK(data0.empty());
CHECK(data1.empty());
CHECK(data0.begin() == data0.end());
CHECK(data1.begin() == data1.end());
}
//*************************************************************************

View File

@ -47,9 +47,10 @@ namespace
const size_t SIZE = 10;
typedef etl::list<ItemDC, SIZE> DataDC;
typedef etl::list<ItemNDC, SIZE> DataNDC;
typedef etl::ilist<ItemNDC> IDataNDC;
typedef etl::list<ItemDC, SIZE> DataDC;
typedef etl::list<ItemNDC, SIZE> DataNDC;
typedef etl::list<ItemNDC, 2 * SIZE> DataNDC2;
typedef etl::ilist<ItemNDC> IDataNDC;
typedef std::list<ItemNDC> CompareData;
typedef std::vector<ItemNDC> InitialData;
@ -59,6 +60,12 @@ namespace
InitialData non_unique_data;
InitialData small_data;
InitialData merge_data0;
InitialData merge_data1;
InitialData merge_data2;
InitialData merge_data3;
InitialData merge_data4;
bool are_equal;
//*************************************************************************
@ -70,6 +77,12 @@ namespace
sorted_data = { ItemNDC("0"), ItemNDC("1"), ItemNDC("2"), ItemNDC("3"), ItemNDC("4"), ItemNDC("5"), ItemNDC("6"), ItemNDC("7"), ItemNDC("8"), ItemNDC("9") };
non_unique_data = { ItemNDC("0"), ItemNDC("0"), ItemNDC("1"), ItemNDC("1"), ItemNDC("2"), ItemNDC("3"), ItemNDC("3"), ItemNDC("3"), ItemNDC("4"), ItemNDC("5") };
small_data = { ItemNDC("0"), ItemNDC("1"), ItemNDC("2"), ItemNDC("3"), ItemNDC("4"), ItemNDC("5") };
merge_data0 = { ItemNDC("1"), ItemNDC("1"), ItemNDC("3"), ItemNDC("3"), ItemNDC("5"), ItemNDC("7"), ItemNDC("8") };
merge_data1 = { ItemNDC("1"), ItemNDC("2"), ItemNDC("3"), ItemNDC("3"), ItemNDC("6"), ItemNDC("9"), ItemNDC("9") };
merge_data2 = { ItemNDC("0"), ItemNDC("2"), ItemNDC("3"), ItemNDC("3"), ItemNDC("6"), ItemNDC("7"), ItemNDC("7") };
merge_data3 = { ItemNDC("0"), ItemNDC("2"), ItemNDC("3"), ItemNDC("3"), ItemNDC("6"), ItemNDC("7") };
merge_data4 = { ItemNDC("0"), ItemNDC("2"), ItemNDC("3"), ItemNDC("3"), ItemNDC("6"), ItemNDC("7"), ItemNDC("8"), ItemNDC("9") };
}
};
@ -808,7 +821,7 @@ namespace
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_move)
TEST_FIXTURE(SetupFixture, test_splice_same)
{
CompareData compare_data(unsorted_data.begin(), unsorted_data.end());
DataNDC data(unsorted_data.begin(), unsorted_data.end());
@ -816,8 +829,8 @@ namespace
CompareData::iterator compare_from;
CompareData::iterator compare_to;
DataNDC::const_iterator from;
DataNDC::const_iterator to;
DataNDC::iterator from;
DataNDC::iterator to;
// Move to the beginning.
compare_from = compare_data.begin();
@ -828,7 +841,7 @@ namespace
from = data.begin();
std::advance(from, 4);
to = data.begin();
data.move(from, to);
data.splice(to, data, from);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
@ -842,7 +855,7 @@ namespace
from = data.begin();
std::advance(from, 4);
to = data.end();
data.move(from, to);
data.splice(to, data, from);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
@ -858,7 +871,7 @@ namespace
std::advance(from, 4);
to = data.begin();
std::advance(to, 6);
data.move(from, to);
data.splice(to, data, from);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
@ -874,14 +887,120 @@ namespace
std::advance(from, 4);
to = data.begin();
std::advance(to, 4);
data.move(from, to);
data.splice(to, data, from);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_move_range)
TEST_FIXTURE(SetupFixture, test_splice_different)
{
CompareData compare_data(unsorted_data.begin(), unsorted_data.end());
CompareData compare_data2(unsorted_data.begin(), unsorted_data.end());
DataNDC2 data(unsorted_data.begin(), unsorted_data.end());
DataNDC2 data2(unsorted_data.begin(), unsorted_data.end());
CompareData::iterator compare_from;
CompareData::iterator compare_to;
DataNDC2::iterator from;
DataNDC2::iterator to;
// Move to the beginning.
compare_from = compare_data2.begin();
std::advance(compare_from, 4);
compare_to = compare_data.begin();
compare_data.splice(compare_to, compare_data2, compare_from);
from = data2.begin();
std::advance(from, 4);
to = data.begin();
data.splice(to, data2, from);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
are_equal = std::equal(data2.begin(), data2.end(), compare_data2.begin());
CHECK(are_equal);
// Move to the end.
compare_data.assign(unsorted_data.begin(), unsorted_data.end());
compare_data2.assign(unsorted_data.begin(), unsorted_data.end());
data.assign(unsorted_data.begin(), unsorted_data.end());
data2.assign(unsorted_data.begin(), unsorted_data.end());
compare_from = compare_data2.begin();
std::advance(compare_from, 4);
compare_to = compare_data.end();
compare_data.splice(compare_to, compare_data2, compare_from);
from = data2.begin();
std::advance(from, 4);
to = data.end();
data.splice(to, data2, from);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
are_equal = std::equal(data2.begin(), data2.end(), compare_data2.begin());
CHECK(are_equal);
// Move nearby.
compare_data.assign(unsorted_data.begin(), unsorted_data.end());
compare_data2.assign(unsorted_data.begin(), unsorted_data.end());
data.assign(unsorted_data.begin(), unsorted_data.end());
data2.assign(unsorted_data.begin(), unsorted_data.end());
compare_from = compare_data2.begin();
std::advance(compare_from, 4);
compare_to = compare_data.begin();
std::advance(compare_to, 6);
compare_data.splice(compare_to, compare_data2, compare_from);
from = data2.begin();
std::advance(from, 4);
to = data.begin();
std::advance(to, 6);
data.splice(to, data2, from);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
are_equal = std::equal(data2.begin(), data2.end(), compare_data2.begin());
CHECK(are_equal);
// Move to same place.
compare_data.assign(unsorted_data.begin(), unsorted_data.end());
compare_data2.assign(unsorted_data.begin(), unsorted_data.end());
data.assign(unsorted_data.begin(), unsorted_data.end());
data2.assign(unsorted_data.begin(), unsorted_data.end());
compare_from = compare_data2.begin();
std::advance(compare_from, 4);
compare_to = compare_data.begin();
std::advance(compare_to, 4);
compare_data.splice(compare_to, compare_data2, compare_from);
from = data2.begin();
std::advance(from, 4);
to = data.begin();
std::advance(to, 4);
data.splice(to, data2, from);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
are_equal = std::equal(data2.begin(), data2.end(), compare_data2.begin());
CHECK(are_equal);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_splice_range_same)
{
CompareData compare_data(unsorted_data.begin(), unsorted_data.end());
DataNDC data(unsorted_data.begin(), unsorted_data.end());
@ -890,9 +1009,9 @@ namespace
CompareData::iterator compare_end;
CompareData::iterator compare_to;
DataNDC::const_iterator begin;
DataNDC::const_iterator end;
DataNDC::const_iterator to;
DataNDC::iterator begin;
DataNDC::iterator end;
DataNDC::iterator to;
// Move to the beginning.
compare_begin = compare_data.begin();
@ -907,7 +1026,7 @@ namespace
end = begin;
std::advance(end, 3);
to = data.begin();
data.move(begin, end, to);
data.splice(to, data, begin, end);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
@ -925,7 +1044,7 @@ namespace
end = begin;
std::advance(end, 3);
to = data.end();
data.move(begin, end, to);
data.splice(to, data, begin, end);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
@ -945,7 +1064,7 @@ namespace
std::advance(end, 3);
to = data.begin();
std::advance(to, 7);
data.move(begin, end, to);
data.splice(to, data, begin, end);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
@ -958,7 +1077,320 @@ namespace
to = data.begin();
std::advance(to, 4);
CHECK_THROW(data.move(begin, end, to), etl::list_iterator);
CHECK_THROW(data.splice(to, data, begin, end), etl::list_iterator);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_splice_range_different)
{
CompareData compare_data(unsorted_data.begin(), unsorted_data.end());
CompareData compare_data2(unsorted_data.begin(), unsorted_data.end());
DataNDC2 data(unsorted_data.begin(), unsorted_data.end());
DataNDC2 data2(unsorted_data.begin(), unsorted_data.end());
CompareData::iterator compare_begin;
CompareData::iterator compare_end;
CompareData::iterator compare_to;
DataNDC2::iterator begin;
DataNDC2::iterator end;
DataNDC2::iterator to;
// Move to the beginning.
compare_begin = compare_data2.begin();
std::advance(compare_begin, 3);
compare_end = compare_begin;
std::advance(compare_end, 3);
compare_to = compare_data.begin();
compare_data.splice(compare_to, compare_data2, compare_begin, compare_end);
begin = data2.begin();
std::advance(begin, 3);
end = begin;
std::advance(end, 3);
to = data.begin();
data.splice(to, data2, begin, end);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
are_equal = std::equal(data2.begin(), data2.end(), compare_data2.begin());
CHECK(are_equal);
// Move to the end.
compare_data.assign(unsorted_data.begin(), unsorted_data.end());
compare_data2.assign(unsorted_data.begin(), unsorted_data.end());
data.assign(unsorted_data.begin(), unsorted_data.end());
data2.assign(unsorted_data.begin(), unsorted_data.end());
compare_begin = compare_data2.begin();
std::advance(compare_begin, 3);
compare_end = compare_begin;
std::advance(compare_end, 3);
compare_to = compare_data.end();
compare_data.splice(compare_to, compare_data2, compare_begin, compare_end);
begin = data2.begin();
std::advance(begin, 3);
end = begin;
std::advance(end, 3);
to = data.end();
data.splice(to, data2, begin, end);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
are_equal = std::equal(data2.begin(), data2.end(), compare_data2.begin());
CHECK(are_equal);
// Move nearby.
compare_data.assign(unsorted_data.begin(), unsorted_data.end());
compare_data2.assign(unsorted_data.begin(), unsorted_data.end());
data.assign(unsorted_data.begin(), unsorted_data.end());
data2.assign(unsorted_data.begin(), unsorted_data.end());
compare_begin = compare_data2.begin();
std::advance(compare_begin, 2);
compare_end = compare_begin;
std::advance(compare_end, 3);
compare_to = compare_data.begin();
std::advance(compare_to, 7);
compare_data.splice(compare_to, compare_data2, compare_begin, compare_end);
begin = data2.begin();
std::advance(begin, 2);
end = begin;
std::advance(end, 3);
to = data.begin();
std::advance(to, 7);
data.splice(to, data2, begin, end);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
are_equal = std::equal(data2.begin(), data2.end(), compare_data2.begin());
CHECK(are_equal);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_splice_list_same)
{
CompareData compare_data(unsorted_data.begin(), unsorted_data.end());
DataNDC data(unsorted_data.begin(), unsorted_data.end());
CompareData::iterator compare_to;
DataNDC::iterator to;
// Move to the beginning.
compare_to = compare_data.begin();
compare_data.splice(compare_to, compare_data);
to = data.begin();
data.splice(to, data);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
// Move to the end.
compare_to = compare_data.end();
compare_data.splice(compare_to, compare_data);
to = data.end();
data.splice(to, data);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
// Move nearby.
compare_to = compare_data.begin();
std::advance(compare_to, 7);
compare_data.splice(compare_to, compare_data);
to = data.begin();
std::advance(to, 7);
data.splice(to, data);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_splice_list_different)
{
CompareData compare_data(unsorted_data.begin(), unsorted_data.end());
CompareData compare_data2(unsorted_data.begin(), unsorted_data.end());
DataNDC2 data(unsorted_data.begin(), unsorted_data.end());
DataNDC2 data2(unsorted_data.begin(), unsorted_data.end());
CompareData::iterator compare_to;
DataNDC2::iterator to;
// Move to the beginning.
compare_to = compare_data.begin();
compare_data.splice(compare_to, compare_data2);
to = data.begin();
data.splice(to, data2);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
are_equal = std::equal(data2.begin(), data2.end(), compare_data2.begin());
CHECK(are_equal);
// Move to the end.
compare_data.assign(unsorted_data.begin(), unsorted_data.end());
compare_data2.assign(unsorted_data.begin(), unsorted_data.end());
data.assign(unsorted_data.begin(), unsorted_data.end());
data2.assign(unsorted_data.begin(), unsorted_data.end());
compare_to = compare_data.end();
compare_data.splice(compare_to, compare_data2);
to = data.end();
data.splice(to, data2);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
are_equal = std::equal(data2.begin(), data2.end(), compare_data2.begin());
CHECK(are_equal);
// Move nearby.
compare_data.assign(unsorted_data.begin(), unsorted_data.end());
compare_data2.assign(unsorted_data.begin(), unsorted_data.end());
data.assign(unsorted_data.begin(), unsorted_data.end());
data2.assign(unsorted_data.begin(), unsorted_data.end());
compare_to = compare_data.begin();
std::advance(compare_to, 7);
compare_data.splice(compare_to, compare_data2);
to = data.begin();
std::advance(to, 7);
data.splice(to, data2);
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
are_equal = std::equal(data2.begin(), data2.end(), compare_data2.begin());
CHECK(are_equal);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_merge_0_1)
{
bool are_equal;
DataNDC2 data0(merge_data0.begin(), merge_data0.end());
DataNDC2 data1(merge_data1.begin(), merge_data1.end());
CompareData compare0(merge_data0.begin(), merge_data0.end());
CompareData compare1(merge_data1.begin(), merge_data1.end());
data0.merge(data1);
compare0.merge(compare1);
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
CHECK(are_equal);
CHECK_EQUAL(data0.size(), compare0.size());
CHECK_EQUAL(data1.size(), compare1.size());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_merge_0_2)
{
bool are_equal;
DataNDC2 data0(merge_data0.begin(), merge_data0.end());
DataNDC2 data2(merge_data2.begin(), merge_data2.end());
CompareData compare0(merge_data0.begin(), merge_data0.end());
CompareData compare2(merge_data2.begin(), merge_data2.end());
data0.merge(data2);
compare0.merge(compare2);
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
CHECK(are_equal);
CHECK_EQUAL(data0.size(), compare0.size());
CHECK_EQUAL(data2.size(), compare2.size());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_merge_0_3)
{
bool are_equal;
DataNDC2 data0(merge_data0.begin(), merge_data0.end());
DataNDC2 data3(merge_data3.begin(), merge_data3.end());
CompareData compare0(merge_data0.begin(), merge_data0.end());
CompareData compare3(merge_data3.begin(), merge_data3.end());
data0.merge(data3);
compare0.merge(compare3);
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
CHECK(are_equal);
CHECK_EQUAL(data0.size(), compare0.size());
CHECK_EQUAL(data3.size(), compare3.size());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_merge_0_4)
{
bool are_equal;
DataNDC2 data0(merge_data0.begin(), merge_data0.end());
DataNDC2 data4(merge_data4.begin(), merge_data4.end());
CompareData compare0(merge_data0.begin(), merge_data0.end());
CompareData compare4(merge_data4.begin(), merge_data4.end());
data0.merge(data4);
compare0.merge(compare4);
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
CHECK(are_equal);
CHECK_EQUAL(data0.size(), compare0.size());
CHECK_EQUAL(data4.size(), compare4.size());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_merge_0_1_reverse_order)
{
bool are_equal;
DataNDC2 data0(merge_data0.begin(), merge_data0.end());
DataNDC2 data1(merge_data1.begin(), merge_data1.end());
data0.reverse();
data1.reverse();
CompareData compare0(merge_data0.begin(), merge_data0.end());
CompareData compare1(merge_data1.begin(), merge_data1.end());
compare0.reverse();
compare1.reverse();
data0.merge(data1, std::greater<ItemNDC>());
compare0.merge(compare1, std::greater<ItemNDC>());
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
CHECK(are_equal);
CHECK_EQUAL(data0.size(), compare0.size());
CHECK_EQUAL(data1.size(), compare1.size());
}
};
}

View File

@ -188,6 +188,7 @@ namespace
CHECK_EQUAL(data.size(), size_t(0));
CHECK(data.empty());
CHECK_EQUAL(data.max_size(), SIZE);
CHECK(data.begin() == data.end());
}
//*************************************************************************
@ -516,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);
}
};
}

438
test/test_unordered_set.cpp Normal file
View File

@ -0,0 +1,438 @@
/******************************************************************************
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_set.h"
#include "../checksum.h"
namespace
{
SUITE(test_unordered_set)
{
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_set<DC, SIZE, simple_hash> DataDC;
typedef etl::unordered_set<NDC, SIZE, simple_hash> DataNDC;
typedef etl::iunordered_set<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;
//*************************************************************************
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
};
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));
}
};
//*************************************************************************
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(N3); // 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);
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_set_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_set_full);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_erase_key)
{
DataNDC data(initial_data.begin(), initial_data.end());
size_t count = data.erase(N5);
CHECK_EQUAL(1, count);
DataNDC::iterator idata = data.find(N5);
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(initial_data.begin(), initial_data.end());
size_t count = data.count(N5);
CHECK_EQUAL(1, count);
count = data.count(N12);
CHECK_EQUAL(0, count);
}
//*************************************************************************
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,8 @@
<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" />
<ClInclude Include="..\..\visitor.h" />
@ -367,6 +371,9 @@
<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" />
<ClCompile Include="..\test_visitor.cpp" />

View File

@ -465,6 +465,18 @@
<ClInclude Include="..\..\intrusive_list.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<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">
@ -719,6 +731,15 @@
<ClCompile Include="..\test_xor_checksum.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<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

123
unordered_set.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_SET__
#define __ETL_UNORDERED_SET__
#include <stddef.h>
#include <iterator>
#include <functional>
#include "iunordered_set.h"
#include "container.h"
#include "pool.h"
#include "vector.h"
#include "intrusive_forward_list.h"
#include "hash.h"
//*****************************************************************************
///\defgroup unordered_set unordered_set
/// A unordered_set with the capacity defined at compile time.
///\ingroup containers
//*****************************************************************************
namespace etl
{
//*************************************************************************
/// A templated unordered_set 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_set : public iunordered_set<TKey, THash, TKeyEqual>
{
private:
typedef iunordered_set<TKey, THash, TKeyEqual> base;
public:
static const size_t MAX_SIZE = MAX_SIZE_;
//*************************************************************************
/// Default constructor.
//*************************************************************************
unordered_set()
: base(node_pool, buckets)
{
base::initialise();
}
//*************************************************************************
/// Copy constructor.
//*************************************************************************
unordered_set(const unordered_set& 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_set(TIterator first, TIterator last)
: base(node_pool, buckets)
{
base::assign(first, last);
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
unordered_set& operator = (const unordered_set& 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_set.
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