mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Complete redesign of intrusive_forward_list using template parameter tags.
This commit is contained in:
parent
f5995420c1
commit
9ccc166022
@ -42,7 +42,7 @@ SOFTWARE.
|
||||
|
||||
#include "nullptr.h"
|
||||
#include "type_traits.h"
|
||||
#include "intrusive_forward_list_node.h"
|
||||
#include "intrusive_forward_list_link.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
@ -105,22 +105,23 @@ namespace etl
|
||||
//***************************************************************************
|
||||
/// An intrusive forward list.
|
||||
///\ingroup intrusive_forward_list
|
||||
///\note TLink must be a base of TValue.
|
||||
//***************************************************************************
|
||||
template <typename TValue>
|
||||
template <typename TValue, typename TLink = etl::intrusive_forward_list_link<0> >
|
||||
class intrusive_forward_list
|
||||
{
|
||||
public:
|
||||
|
||||
// Node typedef.
|
||||
typedef __private_intrusive_forward_list__::intrusive_forward_list_node_base node_t;
|
||||
typedef TLink link_type;
|
||||
|
||||
// STL style typedefs.
|
||||
typedef TValue value_type;
|
||||
typedef TValue* pointer;
|
||||
typedef const TValue* const_pointer;
|
||||
typedef TValue& reference;
|
||||
typedef const TValue& const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef TValue value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
typedef size_t size_type;
|
||||
|
||||
public:
|
||||
|
||||
@ -134,75 +135,74 @@ namespace etl
|
||||
friend class intrusive_forward_list;
|
||||
|
||||
iterator()
|
||||
: p_node(nullptr),
|
||||
index(0)
|
||||
: p_value(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
iterator(node_t& node, size_t index)
|
||||
: p_node(&node),
|
||||
index(index)
|
||||
iterator(value_type& value)
|
||||
: p_value(&value)
|
||||
{
|
||||
}
|
||||
|
||||
iterator(const iterator& other)
|
||||
: p_node(other.p_node),
|
||||
index(other.index)
|
||||
: p_value(other.p_value)
|
||||
{
|
||||
}
|
||||
|
||||
iterator& operator ++()
|
||||
{
|
||||
p_node = p_node->get_next(index);
|
||||
// Read the appropriate 'ifll_next'.
|
||||
p_value = static_cast<value_type*>(p_value->link_type::ifll_next);
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator ++(int)
|
||||
{
|
||||
iterator temp(*this);
|
||||
p_node = p_node->get_next(index);
|
||||
// Read the appropriate 'ifll_next'.
|
||||
p_value = static_cast<value_type*>(p_value->link_type::ifll_next);
|
||||
return temp;
|
||||
}
|
||||
|
||||
iterator operator =(const iterator& other)
|
||||
{
|
||||
p_node = other.p_node;
|
||||
p_value = other.p_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator *()
|
||||
{
|
||||
return static_cast<reference>(*p_node);
|
||||
return *p_value;
|
||||
}
|
||||
|
||||
const_reference operator *() const
|
||||
{
|
||||
return static_cast<const_reference>(*p_node);
|
||||
return *p_value;
|
||||
}
|
||||
|
||||
pointer operator &()
|
||||
{
|
||||
return static_cast<pointer>(p_node);
|
||||
return p_value;
|
||||
}
|
||||
|
||||
const_pointer operator &() const
|
||||
{
|
||||
return static_cast<const_pointer>(p_node);
|
||||
return p_value;
|
||||
}
|
||||
|
||||
pointer operator ->()
|
||||
{
|
||||
return static_cast<pointer>(p_node);
|
||||
return p_value;
|
||||
}
|
||||
|
||||
const_pointer operator ->() const
|
||||
{
|
||||
return static_cast<const_pointer>(p_node);
|
||||
return p_value;
|
||||
}
|
||||
|
||||
friend bool operator == (const iterator& lhs, const iterator& rhs)
|
||||
{
|
||||
return lhs.p_node == rhs.p_node;
|
||||
return lhs.p_value == rhs.p_value;
|
||||
}
|
||||
|
||||
friend bool operator != (const iterator& lhs, const iterator& rhs)
|
||||
@ -212,8 +212,7 @@ namespace etl
|
||||
|
||||
private:
|
||||
|
||||
node_t* p_node;
|
||||
size_t index;
|
||||
value_type* p_value;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
@ -226,72 +225,64 @@ namespace etl
|
||||
friend class intrusive_forward_list;
|
||||
|
||||
const_iterator()
|
||||
: p_node(nullptr),
|
||||
index(0)
|
||||
: p_value(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator(node_t& node, size_t index)
|
||||
: p_node(&node),
|
||||
index(index)
|
||||
const_iterator(const value_type& value)
|
||||
: p_value(&value)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator(const node_t& node, size_t index)
|
||||
: p_node(&node),
|
||||
index(index)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator(const typename intrusive_forward_list<TValue>::iterator& other)
|
||||
: p_node(other.p_node),
|
||||
index(other.index)
|
||||
const_iterator(const typename intrusive_forward_list<value_type, link_type>::iterator& other)
|
||||
: p_value(other.p_value)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator(const const_iterator& other)
|
||||
: p_node(other.p_node),
|
||||
index(other.index)
|
||||
: p_value(other.p_value)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator& operator ++()
|
||||
{
|
||||
p_node = p_node->get_next(index);
|
||||
// Read the appropriate 'ifll_next'.
|
||||
p_value = static_cast<value_type*>(p_value->link_type::ifll_next);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator operator ++(int)
|
||||
{
|
||||
const_iterator temp(*this);
|
||||
p_node = p_node->get_next(index);
|
||||
// Read the appropriate 'ifll_next'.
|
||||
p_value = static_cast<value_type*>(p_value->link_type::ifll_next);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator operator =(const const_iterator& other)
|
||||
{
|
||||
p_node = other.p_node;
|
||||
p_value = other.p_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_reference operator *() const
|
||||
{
|
||||
return static_cast<const_reference>(*p_node);
|
||||
return *p_value;
|
||||
}
|
||||
|
||||
const_pointer operator &() const
|
||||
{
|
||||
return static_cast<const_pointer>(p_node);
|
||||
return p_value;
|
||||
}
|
||||
|
||||
const_pointer operator ->() const
|
||||
{
|
||||
return static_cast<const_pointer>(p_node);
|
||||
return p_value;
|
||||
}
|
||||
|
||||
friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
|
||||
{
|
||||
return lhs.p_node == rhs.p_node;
|
||||
return lhs.p_value == rhs.p_value;
|
||||
}
|
||||
|
||||
friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
|
||||
@ -301,8 +292,7 @@ namespace etl
|
||||
|
||||
private:
|
||||
|
||||
const node_t* p_node;
|
||||
size_t index;
|
||||
const value_type* p_value;
|
||||
};
|
||||
|
||||
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
|
||||
@ -310,8 +300,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Constructor.
|
||||
//*************************************************************************
|
||||
intrusive_forward_list(size_t index)
|
||||
: index(index)
|
||||
intrusive_forward_list()
|
||||
{
|
||||
initialise();
|
||||
}
|
||||
@ -320,8 +309,7 @@ namespace etl
|
||||
/// Constructor from range
|
||||
//*************************************************************************
|
||||
template <typename TIterator>
|
||||
intrusive_forward_list(size_t index, TIterator first, TIterator last)
|
||||
: index(index)
|
||||
intrusive_forward_list(TIterator first, TIterator last)
|
||||
{
|
||||
assign(first, last);
|
||||
}
|
||||
@ -331,7 +319,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(get_head(), index);
|
||||
return iterator(static_cast<value_type&>(get_head()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -339,7 +327,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(get_head(), index);
|
||||
return const_iterator(static_cast<const value_type&>(get_head()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -347,7 +335,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
iterator before_begin()
|
||||
{
|
||||
return iterator(start_node, index);
|
||||
return iterator(static_cast<value_type&>(start_link));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -355,7 +343,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
const_iterator before_begin() const
|
||||
{
|
||||
return const_iterator(start_node, index);
|
||||
return const_iterator(static_cast<const value_type&>(start_link));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -363,7 +351,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return const_iterator(get_head(), index);
|
||||
return const_iterator(static_cast<const value_type&>(get_head()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -403,7 +391,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
reference front()
|
||||
{
|
||||
return static_cast<reference>(get_head());
|
||||
return static_cast<value_type&>(get_head());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -411,7 +399,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
const_reference front() const
|
||||
{
|
||||
return get_head();
|
||||
return static_cast<const value_type&>(get_head());;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -428,15 +416,15 @@ namespace etl
|
||||
|
||||
initialise();
|
||||
|
||||
node_t* p_last_node = &start_node;
|
||||
link_type* p_last_link = &start_link;
|
||||
|
||||
// Add all of the elements.
|
||||
while (first != last)
|
||||
{
|
||||
node_t& node = *first++;
|
||||
join(p_last_node, &node);
|
||||
join(&node, nullptr);
|
||||
p_last_node = &node;
|
||||
link_type& link = *first++;
|
||||
join(p_last_link, &link);
|
||||
join(&link, nullptr);
|
||||
p_last_link = &link;
|
||||
++current_size;
|
||||
}
|
||||
}
|
||||
@ -444,9 +432,9 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Pushes a value to the front of the intrusive_forward_list.
|
||||
//*************************************************************************
|
||||
void push_front(node_t& value)
|
||||
void push_front(link_type& value)
|
||||
{
|
||||
insert_node_after(start_node, value);
|
||||
insert_link_after(start_link, value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -457,7 +445,7 @@ namespace etl
|
||||
#if defined(ETL_CHECK_PUSH_POP)
|
||||
ETL_ASSERT(!empty(), ETL_ERROR(intrusive_forward_list_empty));
|
||||
#endif
|
||||
remove_node_after(start_node);
|
||||
remove_link_after(start_link);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -470,29 +458,29 @@ namespace etl
|
||||
return;
|
||||
}
|
||||
|
||||
node_t* first = nullptr; // To keep first node
|
||||
node_t* second = start_node.get_next(index); // To keep second node
|
||||
node_t* track = start_node.get_next(index); // Track the list
|
||||
link_type* first = nullptr; // To keep first link
|
||||
link_type* second = start_link.ifll_next; // To keep second link
|
||||
link_type* track = start_link.ifll_next; // Track the list
|
||||
|
||||
while (track != NULL)
|
||||
{
|
||||
track = track->get_next(index); // Track point to next node;
|
||||
second->set_next(index, first); // Second node point to first
|
||||
first = second; // Move first node to next
|
||||
second = track; // Move second node to next
|
||||
track = track->ifll_next; // Track point to next link;
|
||||
second->ifll_next = first; // Second link point to first
|
||||
first = second; // Move first link to next
|
||||
second = track; // Move second link to next
|
||||
}
|
||||
|
||||
join(&start_node, first);
|
||||
join(&start_link, first);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Inserts a value to the intrusive_forward_list after the specified position.
|
||||
//*************************************************************************
|
||||
iterator insert_after(iterator position, node_t& value)
|
||||
iterator insert_after(iterator position, value_type& value)
|
||||
{
|
||||
insert_node_after(*position.p_node, value);
|
||||
insert_link_after(*position.p_value, value);
|
||||
|
||||
return iterator(value, index);
|
||||
return iterator(value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -503,8 +491,8 @@ namespace etl
|
||||
{
|
||||
while (first != last)
|
||||
{
|
||||
// Set up the next free node.
|
||||
insert_node_after(*position.p_node, *first++);
|
||||
// Set up the next free link.
|
||||
insert_link_after(*position.p_value, *first++);
|
||||
++position;
|
||||
}
|
||||
}
|
||||
@ -518,7 +506,7 @@ namespace etl
|
||||
++next;
|
||||
++next;
|
||||
|
||||
remove_node_after(*position.p_node);
|
||||
remove_link_after(*position.p_value);
|
||||
|
||||
return next;
|
||||
}
|
||||
@ -528,9 +516,9 @@ namespace etl
|
||||
//*************************************************************************
|
||||
iterator erase_after(iterator first, iterator last)
|
||||
{
|
||||
node_t* p_first = first.p_node;
|
||||
node_t* p_last = last.p_node;
|
||||
node_t* p_next = p_first->get_next(index);
|
||||
link_type* p_first = first.p_value;
|
||||
link_type* p_last = last.p_value;
|
||||
link_type* p_next = p_first->ifll_next;
|
||||
|
||||
// Join the ends.
|
||||
join(p_first, p_last);
|
||||
@ -543,8 +531,8 @@ namespace etl
|
||||
// One less.
|
||||
--current_size;
|
||||
|
||||
p_next = p_first->get_next(index); // Remember the next node.
|
||||
p_first = p_next; // Move to the next node.
|
||||
p_next = p_first->ifll_next; // Remember the next link.
|
||||
p_first = p_next; // Move to the next link.
|
||||
}
|
||||
|
||||
if (p_next == nullptr)
|
||||
@ -553,7 +541,7 @@ namespace etl
|
||||
}
|
||||
else
|
||||
{
|
||||
return iterator(*p_last, index);
|
||||
return iterator(*static_cast<value_type*>(p_last));
|
||||
}
|
||||
}
|
||||
|
||||
@ -569,15 +557,15 @@ namespace etl
|
||||
return;
|
||||
}
|
||||
|
||||
node_t* last = &get_head();
|
||||
node_t* current = last->get_next(index);
|
||||
link_type* last = &get_head();
|
||||
link_type* current = last->ifll_next;
|
||||
|
||||
while (current != nullptr)
|
||||
{
|
||||
// Is this value the same as the last?
|
||||
if (isEqual(static_cast<reference>(*current), static_cast<reference>(*last)))
|
||||
if (isEqual(*static_cast<value_type*>(current), *static_cast<value_type*>(last)))
|
||||
{
|
||||
remove_node_after(*last);
|
||||
remove_link_after(*last);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -585,7 +573,7 @@ namespace etl
|
||||
last = current;
|
||||
}
|
||||
|
||||
current = last->get_next(index);
|
||||
current = last->ifll_next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -594,7 +582,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
void sort()
|
||||
{
|
||||
sort(std::less<TValue>());
|
||||
sort(std::less<value_type>());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -607,7 +595,7 @@ namespace etl
|
||||
{
|
||||
iterator i_left;
|
||||
iterator i_right;
|
||||
iterator i_node;
|
||||
iterator i_link;
|
||||
iterator i_head;
|
||||
iterator i_tail;
|
||||
int list_size = 1;
|
||||
@ -653,50 +641,50 @@ namespace etl
|
||||
// Now we have two lists. Merge them.
|
||||
while (left_size > 0 || (right_size > 0 && i_right != end()))
|
||||
{
|
||||
// Decide whether the next node of merge comes from left or right.
|
||||
// Decide whether the next link of merge comes from left or right.
|
||||
if (left_size == 0)
|
||||
{
|
||||
// Left is empty. The node must come from right.
|
||||
i_node = i_right;
|
||||
// Left is empty. The link must come from right.
|
||||
i_link = i_right;
|
||||
++i_right;
|
||||
--right_size;
|
||||
}
|
||||
else if (right_size == 0 || i_right == end())
|
||||
{
|
||||
// Right is empty. The node must come from left.
|
||||
i_node = i_left;
|
||||
// Right is empty. The link must come from left.
|
||||
i_link = i_left;
|
||||
++i_left;
|
||||
--left_size;
|
||||
}
|
||||
else if (compare(*i_left, *i_right))
|
||||
{
|
||||
// First node of left is lower or same. The node must come from left.
|
||||
i_node = i_left;
|
||||
// First link of left is lower or same. The link must come from left.
|
||||
i_link = i_left;
|
||||
++i_left;
|
||||
--left_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// First node of right is lower. The node must come from right.
|
||||
i_node = i_right;
|
||||
// First link of right is lower. The link must come from right.
|
||||
i_link = i_right;
|
||||
++i_right;
|
||||
--right_size;
|
||||
}
|
||||
|
||||
// Add the next node to the merged head.
|
||||
// Add the next link to the merged head.
|
||||
if (i_head == before_begin())
|
||||
{
|
||||
join(i_head.p_node, i_node.p_node);
|
||||
i_head = i_node;
|
||||
i_tail = i_node;
|
||||
join(i_head.p_value, i_link.p_value);
|
||||
i_head = i_link;
|
||||
i_tail = i_link;
|
||||
}
|
||||
else
|
||||
{
|
||||
join(i_tail.p_node, i_node.p_node);
|
||||
i_tail = i_node;
|
||||
join(i_tail.p_value, i_link.p_value);
|
||||
i_tail = i_link;
|
||||
}
|
||||
|
||||
i_tail.p_node->set_next(index, nullptr);
|
||||
i_tail.p_value->link_type::ifll_next = nullptr;
|
||||
}
|
||||
|
||||
// Now left has stepped `list_size' places along, and right has too.
|
||||
@ -717,14 +705,14 @@ namespace etl
|
||||
//*************************************************************************
|
||||
// Removes the values specified.
|
||||
//*************************************************************************
|
||||
void remove(node_t& value)
|
||||
void remove(const_reference value)
|
||||
{
|
||||
iterator i_item = begin();
|
||||
iterator i_last_item = before_begin();
|
||||
|
||||
while (i_item != end())
|
||||
{
|
||||
if (static_cast<reference>(*i_item) == static_cast<reference>(value))
|
||||
if (*i_item == value)
|
||||
{
|
||||
i_item = erase_after(i_last_item);
|
||||
}
|
||||
@ -777,16 +765,16 @@ namespace etl
|
||||
|
||||
private:
|
||||
|
||||
node_t start_node; ///< The node that acts as the intrusive_forward_list start.
|
||||
size_t current_size; ///< The number of elements in the list.
|
||||
size_t index; ///< The index level of the node that this list operates on.
|
||||
link_type start_link; ///< The link that acts as the intrusive_forward_list start.
|
||||
size_t current_size; ///< The number of elements in the list.
|
||||
size_t index; ///< The index level of the link that this list operates on.
|
||||
|
||||
//*************************************************************************
|
||||
/// Join two nodes.
|
||||
/// Join two links.
|
||||
//*************************************************************************
|
||||
void join(node_t* left, node_t* right)
|
||||
void join(link_type* left, link_type* right)
|
||||
{
|
||||
left->set_next(index, right);
|
||||
left->ifll_next = right;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -798,46 +786,46 @@ namespace etl
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Insert a node.
|
||||
/// Insert a link.
|
||||
//*************************************************************************
|
||||
void insert_node_after(node_t& position, node_t& node)
|
||||
void insert_link_after(link_type& position, link_type& link)
|
||||
{
|
||||
// Connect to the intrusive_forward_list.
|
||||
join(&node, position.get_next(index));
|
||||
join(&position, &node);
|
||||
join(&link, position.ifll_next);
|
||||
join(&position, &link);
|
||||
++current_size;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Remove a node.
|
||||
/// Remove a link.
|
||||
//*************************************************************************
|
||||
void remove_node_after(node_t& node)
|
||||
void remove_link_after(link_type& link)
|
||||
{
|
||||
// The node to erase.
|
||||
node_t* p_node = node.get_next(index);
|
||||
// The link to erase.
|
||||
link_type* p_link = link.ifll_next;
|
||||
|
||||
if (p_node != nullptr)
|
||||
if (p_link != nullptr)
|
||||
{
|
||||
// Disconnect the node from the intrusive_forward_list.
|
||||
join(&node, p_node->get_next(index));
|
||||
// Disconnect the link from the intrusive_forward_list.
|
||||
join(&link, p_link->ifll_next);
|
||||
--current_size;
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Get the head node.
|
||||
/// Get the head link.
|
||||
//*************************************************************************
|
||||
node_t& get_head()
|
||||
link_type& get_head()
|
||||
{
|
||||
return *start_node.get_next(index);
|
||||
return *start_link.ifll_next;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Get the head node.
|
||||
/// Get the head link.
|
||||
//*************************************************************************
|
||||
const node_t& get_head() const
|
||||
const link_type& get_head() const
|
||||
{
|
||||
return *start_node.get_next(index);
|
||||
return *start_link.ifll_next;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -845,7 +833,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
void initialise()
|
||||
{
|
||||
start_node.set_next(index, nullptr);
|
||||
start_link.ifll_next = nullptr;
|
||||
current_size = 0;
|
||||
}
|
||||
|
||||
|
||||
49
intrusive_forward_list_link.h
Normal file
49
intrusive_forward_list_link.h
Normal file
@ -0,0 +1,49 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
http://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2015 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_INTRUSIVE_FORWARD_LIST_LINK__
|
||||
#define __ETL_INTRUSIVE_FORWARD_LIST_LINK__
|
||||
|
||||
#include "error_handler.h"
|
||||
#include "array.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// The link element in the intrusive_forward_list.
|
||||
//***************************************************************************
|
||||
template <const size_t ID>
|
||||
struct intrusive_forward_list_link
|
||||
{
|
||||
intrusive_forward_list_link<ID>* ifll_next;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -42,9 +42,14 @@ SOFTWARE.
|
||||
|
||||
typedef TestDataDC<std::string> ItemDC;
|
||||
typedef TestDataNDC<std::string> ItemNDC;
|
||||
|
||||
namespace
|
||||
{
|
||||
class ItemDCNode : public etl::intrusive_forward_list_node<2>
|
||||
typedef etl::intrusive_forward_list_link<0> FirstLink;
|
||||
typedef etl::intrusive_forward_list_link<1> SecondLink;
|
||||
|
||||
//***************************************************************************
|
||||
class ItemDCNode : public FirstLink, public SecondLink
|
||||
{
|
||||
public:
|
||||
|
||||
@ -56,9 +61,8 @@ namespace
|
||||
ItemDC data;
|
||||
};
|
||||
|
||||
const size_t INDEXES = 2;
|
||||
|
||||
class ItemNDCNode : public etl::intrusive_forward_list_node<INDEXES>
|
||||
//***************************************************************************
|
||||
class ItemNDCNode : public FirstLink, public SecondLink
|
||||
{
|
||||
public:
|
||||
|
||||
@ -75,6 +79,7 @@ namespace
|
||||
ItemNDC data;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
bool operator ==(const ItemDCNode& lhs, const ItemDCNode& rhs)
|
||||
{
|
||||
return lhs.data == rhs.data;
|
||||
@ -85,12 +90,23 @@ namespace
|
||||
return lhs.data == rhs.data;
|
||||
}
|
||||
|
||||
bool operator !=(const ItemDCNode& lhs, const ItemDCNode& rhs)
|
||||
{
|
||||
return lhs.data != rhs.data;
|
||||
}
|
||||
|
||||
bool operator !=(const ItemNDCNode& lhs, const ItemNDCNode& rhs)
|
||||
{
|
||||
return lhs.data != rhs.data;
|
||||
}
|
||||
|
||||
std::ostream& operator << (std::ostream& os, const ItemNDCNode& node)
|
||||
{
|
||||
os << node.data;
|
||||
return os;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
struct CompareItemNDCNode
|
||||
{
|
||||
bool operator ()(const ItemNDCNode& lhs, const ItemNDCNode& rhs) const
|
||||
@ -106,17 +122,39 @@ namespace
|
||||
return lhs.data == rhs.data;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
typedef etl::intrusive_forward_list<ItemDCNode, FirstLink> DataDC0;
|
||||
typedef etl::intrusive_forward_list<ItemDCNode, SecondLink> DataDC1;
|
||||
typedef etl::intrusive_forward_list<ItemNDCNode, FirstLink> DataNDC0;
|
||||
typedef etl::intrusive_forward_list<ItemNDCNode, SecondLink> DataNDC1;
|
||||
|
||||
typedef std::vector<ItemNDCNode> InitialDataNDC;
|
||||
|
||||
template <typename TIterator1, typename TIterator2>
|
||||
bool Equal(TIterator1 begin1,
|
||||
TIterator1 end1,
|
||||
TIterator2 begin2)
|
||||
{
|
||||
while (begin1 != end1)
|
||||
{
|
||||
if (*begin1 != *begin2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
++begin1;
|
||||
++begin2;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
SUITE(test_forward_list)
|
||||
{
|
||||
typedef etl::intrusive_forward_list<ItemDCNode> DataDC;
|
||||
typedef etl::intrusive_forward_list<ItemNDCNode> DataNDC;
|
||||
|
||||
typedef std::vector<ItemNDCNode> InitialDataNDC;
|
||||
|
||||
InitialDataNDC unsorted_data;
|
||||
InitialDataNDC sorted_data;
|
||||
InitialDataNDC non_unique_data;
|
||||
@ -141,8 +179,8 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_default_constructor)
|
||||
{
|
||||
DataNDC data0(0);
|
||||
DataNDC data1(1);
|
||||
DataNDC0 data0;
|
||||
DataNDC1 data1;
|
||||
|
||||
CHECK(data0.empty());
|
||||
CHECK(data1.empty());
|
||||
@ -151,7 +189,7 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_constructor_range)
|
||||
{
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
CHECK(!data0.empty());
|
||||
CHECK_EQUAL(sorted_data.size(), data0.size());
|
||||
@ -160,7 +198,7 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_iterator)
|
||||
{
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), sorted_data.begin());
|
||||
|
||||
@ -170,7 +208,7 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_const_iterator)
|
||||
{
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
are_equal = std::equal(data0.cbegin(), data0.cend(), sorted_data.begin());
|
||||
|
||||
@ -180,7 +218,7 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_clear)
|
||||
{
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
data0.clear();
|
||||
|
||||
CHECK(data0.empty());
|
||||
@ -189,7 +227,7 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_assign_range)
|
||||
{
|
||||
DataNDC data0(0);
|
||||
DataNDC0 data0;
|
||||
|
||||
// Do it twice. We should only get one copy.
|
||||
data0.assign(sorted_data.begin(), sorted_data.end());
|
||||
@ -203,8 +241,8 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_assign_range_two_lists_same)
|
||||
{
|
||||
DataNDC data0(0);
|
||||
DataNDC data1(1);
|
||||
DataNDC0 data0;
|
||||
DataNDC0 data1;
|
||||
|
||||
data0.assign(sorted_data.begin(), sorted_data.end());
|
||||
data1.assign(sorted_data.begin(), sorted_data.end());
|
||||
@ -216,14 +254,14 @@ namespace
|
||||
CHECK(are_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
////*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_two_lists_different)
|
||||
{
|
||||
std::list<ItemNDCNode> compare0;
|
||||
std::list<ItemNDCNode> compare1;
|
||||
|
||||
DataNDC data0(0);
|
||||
DataNDC data1(1);
|
||||
DataNDC0 data0;
|
||||
DataNDC1 data1;
|
||||
|
||||
ItemNDCNode node0("0");
|
||||
ItemNDCNode node1("1");
|
||||
@ -280,12 +318,12 @@ namespace
|
||||
ItemNDCNode INSERT_VALUE2 = ItemNDCNode("2");
|
||||
|
||||
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data1(1, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
size_t offset = 2;
|
||||
|
||||
DataNDC::iterator i_data = data0.begin();
|
||||
DataNDC0::iterator i_data = data0.begin();
|
||||
std::advance(i_data, offset);
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_data = compare_data.begin();
|
||||
@ -338,8 +376,8 @@ namespace
|
||||
std::vector<ItemNDCNode> compare(test2);
|
||||
compare.insert(compare.end(), test1.begin(), test1.end());
|
||||
|
||||
DataNDC data0(0, test1.begin(), test1.end());
|
||||
DataNDC data1(1, test1.begin(), test1.end());
|
||||
DataNDC0 data0(test1.begin(), test1.end());
|
||||
DataNDC1 data1(test1.begin(), test1.end());
|
||||
|
||||
data0.insert_after(data0.before_begin(), test2.begin(), test2.end());
|
||||
|
||||
@ -355,7 +393,7 @@ namespace
|
||||
data0.assign(test1.begin(), test1.end());
|
||||
|
||||
std::vector<ItemNDCNode>::iterator icd = compare.begin();
|
||||
DataNDC::iterator id = data0.begin();
|
||||
DataNDC0::iterator id = data0.begin();
|
||||
|
||||
std::advance(icd, 4);
|
||||
std::advance(id, 3);
|
||||
@ -378,7 +416,7 @@ namespace
|
||||
TEST_FIXTURE(SetupFixture, test_push_front)
|
||||
{
|
||||
std::list<ItemNDCNode> compare_data;
|
||||
DataNDC data0(0);
|
||||
DataNDC0 data0;
|
||||
|
||||
ItemNDCNode node1("1");
|
||||
ItemNDCNode node2("2");
|
||||
@ -410,8 +448,8 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_push_front_pop_front)
|
||||
{
|
||||
DataNDC data0(0);
|
||||
DataNDC data1(1);
|
||||
DataNDC0 data0;
|
||||
DataNDC1 data1;
|
||||
|
||||
ItemNDCNode node1("1");
|
||||
ItemNDCNode node2("2");
|
||||
@ -463,10 +501,10 @@ namespace
|
||||
TEST_FIXTURE(SetupFixture, test_erase_after_single)
|
||||
{
|
||||
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data1(1, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
DataNDC::iterator i_data = data0.begin();
|
||||
DataNDC0::iterator i_data = data0.begin();
|
||||
std::advance(i_data, 2);
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_data = compare_data.begin();
|
||||
@ -523,13 +561,13 @@ namespace
|
||||
TEST_FIXTURE(SetupFixture, test_erase_after_range)
|
||||
{
|
||||
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data1(1, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
DataNDC::iterator i_data_1 = data0.begin();
|
||||
DataNDC0::iterator i_data_1 = data0.begin();
|
||||
std::advance(i_data_1, 2);
|
||||
|
||||
DataNDC::iterator i_data_2 = data0.begin();
|
||||
DataNDC0::iterator i_data_2 = data0.begin();
|
||||
std::advance(i_data_2, 4);
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_data_1 = compare_data.begin();
|
||||
@ -540,7 +578,7 @@ namespace
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_result = compare_data.erase(i_compare_data_1, i_compare_data_2);
|
||||
|
||||
DataNDC::iterator i_result = data0.erase_after(i_data_1, i_data_2);
|
||||
DataNDC0::iterator i_result = data0.erase_after(i_data_1, i_data_2);
|
||||
|
||||
CHECK_EQUAL(*i_compare_result, *i_result);
|
||||
|
||||
@ -559,10 +597,10 @@ namespace
|
||||
TEST_FIXTURE(SetupFixture, test_erase_after_range_end)
|
||||
{
|
||||
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data1(1, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
DataNDC::iterator i_data = data0.begin();
|
||||
DataNDC0::iterator i_data = data0.begin();
|
||||
std::advance(i_data, 4);
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_data = compare_data.begin();
|
||||
@ -570,7 +608,7 @@ namespace
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_result = compare_data.erase(i_compare_data, compare_data.end());
|
||||
|
||||
DataNDC::iterator i_result = data0.erase_after(i_data, data0.end());
|
||||
DataNDC0::iterator i_result = data0.erase_after(i_data, data0.end());
|
||||
|
||||
CHECK(i_result == data0.end());
|
||||
|
||||
@ -588,7 +626,7 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_after_all)
|
||||
{
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
data0.erase_after(data0.before_begin(), data0.end());
|
||||
|
||||
@ -598,7 +636,7 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_front)
|
||||
{
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
CHECK_EQUAL(sorted_data.front(), data0.front());
|
||||
}
|
||||
@ -606,8 +644,8 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_unique)
|
||||
{
|
||||
DataNDC data0(0, non_unique_data.begin(), non_unique_data.end());
|
||||
DataNDC data1(1, non_unique_data.begin(), non_unique_data.end());
|
||||
DataNDC0 data0(non_unique_data.begin(), non_unique_data.end());
|
||||
DataNDC1 data1(non_unique_data.begin(), non_unique_data.end());
|
||||
|
||||
data0.unique(EqualItemNDCNode());
|
||||
|
||||
@ -628,8 +666,8 @@ namespace
|
||||
TEST_FIXTURE(SetupFixture, test_remove)
|
||||
{
|
||||
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data1(1, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_item = std::find(compare_data.begin(), compare_data.end(), ItemNDCNode("7"));
|
||||
compare_data.erase(i_item);
|
||||
@ -651,8 +689,8 @@ namespace
|
||||
TEST_FIXTURE(SetupFixture, test_remove_if)
|
||||
{
|
||||
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data1(1, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_item = std::find(compare_data.begin(), compare_data.end(), ItemNDCNode("7"));
|
||||
compare_data.erase(i_item);
|
||||
@ -673,8 +711,8 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_reverse)
|
||||
{
|
||||
DataNDC data0(0, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data1(1, sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
data0.reverse(); // Just reverse one of them.
|
||||
|
||||
@ -688,8 +726,8 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_sort)
|
||||
{
|
||||
DataNDC data0(0, unsorted_data.begin(), unsorted_data.end());
|
||||
DataNDC data1(1, unsorted_data.begin(), unsorted_data.end());
|
||||
DataNDC0 data0(unsorted_data.begin(), unsorted_data.end());
|
||||
DataNDC1 data1(unsorted_data.begin(), unsorted_data.end());
|
||||
|
||||
data0.sort(); // Just sort one of them.
|
||||
|
||||
@ -703,8 +741,8 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_sort_compare)
|
||||
{
|
||||
DataNDC data0(0, unsorted_data.begin(), unsorted_data.end());
|
||||
DataNDC data1(1, unsorted_data.begin(), unsorted_data.end());
|
||||
DataNDC0 data0(unsorted_data.begin(), unsorted_data.end());
|
||||
DataNDC1 data1(unsorted_data.begin(), unsorted_data.end());
|
||||
|
||||
data0.sort(CompareItemNDCNode()); // Just sort one of them.
|
||||
|
||||
|
||||
@ -223,7 +223,9 @@
|
||||
<ClInclude Include="..\..\list.h" />
|
||||
<ClInclude Include="..\..\log.h" />
|
||||
<ClInclude Include="..\..\flat_map.h" />
|
||||
<ClInclude Include="..\..\lru_cache.h" />
|
||||
<ClInclude Include="..\..\lru_cache.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug No Unit Tests|Win32'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\map.h" />
|
||||
<ClInclude Include="..\..\mru_cache.h" />
|
||||
<ClInclude Include="..\..\multimap.h" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user