Loading...
Searching...
No Matches
intrusive_forward_list.h
Go to the documentation of this file.
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2016 John Wellbelove
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_INCLUDED
#define ETL_INTRUSIVE_FORWARD_LIST_INCLUDED
#include "platform.h"
#include "algorithm.h"
#include "error_handler.h"
#include "exception.h"
#include "functional.h"
#include "intrusive_links.h"
#include "iterator.h"
#include "nullptr.h"
#include "type_traits.h"
#include <stddef.h>
#include "private/minmax_push.h"
namespace etl
{
//***************************************************************************
//***************************************************************************
class intrusive_forward_list_exception : public exception
{
public:
intrusive_forward_list_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: exception(reason_, file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class intrusive_forward_list_empty : public intrusive_forward_list_exception
{
public:
intrusive_forward_list_empty(string_type file_name_, numeric_type line_number_)
: intrusive_forward_list_exception(ETL_ERROR_TEXT("intrusive_forward_list:empty", ETL_INTRUSIVE_FORWARD_LIST_FILE_ID"A"), file_name_,
line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class intrusive_forward_list_iterator_exception : public intrusive_forward_list_exception
{
public:
intrusive_forward_list_iterator_exception(string_type file_name_, numeric_type line_number_)
: intrusive_forward_list_exception(ETL_ERROR_TEXT("intrusive_forward_list:iterator", ETL_INTRUSIVE_FORWARD_LIST_FILE_ID"B"), file_name_,
line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class intrusive_forward_list_index_exception : public intrusive_forward_list_exception
{
public:
intrusive_forward_list_index_exception(string_type file_name_, numeric_type line_number_)
: intrusive_forward_list_exception(ETL_ERROR_TEXT("intrusive_forward_list:bounds", ETL_INTRUSIVE_FORWARD_LIST_FILE_ID"C"), file_name_,
line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class intrusive_forward_list_unsorted : public intrusive_forward_list_exception
{
public:
intrusive_forward_list_unsorted(string_type file_name_, numeric_type line_number_)
: intrusive_forward_list_exception(ETL_ERROR_TEXT("intrusive_forward_list:unsorted", ETL_INTRUSIVE_FORWARD_LIST_FILE_ID"D"), file_name_,
line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class intrusive_forward_list_value_is_already_linked : public intrusive_forward_list_exception
{
public:
intrusive_forward_list_value_is_already_linked(string_type file_name_, numeric_type line_number_)
: intrusive_forward_list_exception(ETL_ERROR_TEXT("intrusive_forward_list:value is already linked", ETL_INTRUSIVE_FORWARD_LIST_FILE_ID"E"),
file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
template <typename TLink>
class intrusive_forward_list_base
{
public:
// Node typedef.
typedef TLink link_type;
//*************************************************************************
//*************************************************************************
void clear()
{
// Unlink all of the items.
link_type* p_unlink = start.etl_next;
while (p_unlink != &terminator)
{
link_type* p_next = p_unlink->etl_next;
p_unlink->clear();
p_unlink = p_next;
}
initialise();
}
//*************************************************************************
//*************************************************************************
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#if ETL_IS_DEBUG_BUILD
intmax_t d = etl::distance(first, last);
ETL_ASSERT_OR_RETURN(d >= 0, ETL_ERROR(intrusive_forward_list_iterator_exception));
#endif
clear();
link_type* p_last = &start;
// Add all of the elements.
while (first != last)
{
link_type& value = *first++;
ETL_ASSERT_OR_RETURN(!value.is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked));
value.etl_next = p_last->etl_next;
p_last->etl_next = &value;
p_last = &value;
++current_size;
}
}
//*************************************************************************
//*************************************************************************
void push_front(link_type& value)
{
ETL_ASSERT_OR_RETURN(!value.is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked));
insert_link_after(start, value);
}
//*************************************************************************
//*************************************************************************
void pop_front()
{
ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!empty(), ETL_ERROR(intrusive_forward_list_empty));
disconnect_link_after(start);
}
//*************************************************************************
//*************************************************************************
void reverse()
{
if (is_trivial_list())
{
return;
}
link_type* previous = &terminator; // Point to the terminator of the linked list.
link_type* current = start.etl_next; // Point to the first item in the linked list (could be
// the terminator).
link_type* next = start.etl_next; // Point to the first item in the linked
// list (could be the terminator).
while (next != &terminator)
{
next = next->etl_next; // Point to next link.
current->etl_next = previous; // Reverse the current link.
previous = current; // Previous points to current.
current = next; // Current points to next.
}
etl::link<link_type>(start, previous);
}
//*************************************************************************
//*************************************************************************
bool empty() const
{
return (current_size == 0);
}
//*************************************************************************
//*************************************************************************
size_t size() const
{
return current_size;
}
//*************************************************************************
//*************************************************************************
bool contains_node(const link_type& search_link) const
{
return is_link_in_list(&search_link);
}
//*************************************************************************
//*************************************************************************
bool contains_node(const link_type* search_link) const
{
return is_link_in_list(search_link);
}
protected:
link_type start;
static link_type terminator;
size_t current_size;
//*************************************************************************
//*************************************************************************
intrusive_forward_list_base()
{
initialise();
}
//*************************************************************************
//*************************************************************************
~intrusive_forward_list_base()
{
clear();
}
//*************************************************************************
//*************************************************************************
bool is_trivial_list() const
{
return (size() <= 1U);
}
//*************************************************************************
//*************************************************************************
void insert_link_after(link_type& position, link_type& link)
{
// Connect to the intrusive_forward_list.
etl::link_splice<link_type>(position, link);
++current_size;
}
//*************************************************************************
//*************************************************************************
void disconnect_link_after(link_type& link)
{
link_type* p_next = link.etl_next;
if (p_next != &this->terminator)
{
link_type* p_unlinked = etl::unlink_after<link_type>(link);
if (p_unlinked != ETL_NULLPTR)
{
p_unlinked->clear();
}
--current_size;
}
}
//*************************************************************************
//*************************************************************************
link_type* get_head()
{
return start.etl_next;
}
//*************************************************************************
//*************************************************************************
const link_type* get_head() const
{
return start.etl_next;
}
//*************************************************************************
//*************************************************************************
void initialise()
{
start.etl_next = &terminator;
current_size = 0;
}
//*************************************************************************
//*************************************************************************
link_type* is_link_in_list(const link_type* search_link) const
{
link_type* p_link = start.etl_next;
link_type* p_previous = const_cast<link_type*>(&start);
while (p_link != ETL_NULLPTR)
{
if (search_link == p_link)
{
return p_previous;
}
p_previous = p_link;
p_link = p_link->link_type::etl_next;
}
return ETL_NULLPTR;
}
//*************************************************************************
//*************************************************************************
link_type* remove_link(link_type* link)
{
link_type* result = ETL_NULLPTR;
link_type* p_previous = is_link_in_list(link);
if (p_previous != ETL_NULLPTR)
{
link_type* p_next = link->etl_next;
disconnect_link_after(*p_previous);
if (p_next != &this->terminator)
{
result = p_next;
}
}
return result;
}
//*************************************************************************
//*************************************************************************
link_type* remove_link_range_after(link_type* p_first, link_type* p_last)
{
link_type* p_after = p_first->etl_next;
// Join the ends.
etl::link<link_type>(p_first, p_last);
// Unlink the erased range.
link_type* p_unlink = p_after;
while (p_unlink != p_last)
{
link_type* p_next = p_unlink->etl_next;
p_unlink->clear();
p_unlink = p_next;
}
if (p_after == &this->terminator)
{
return ETL_NULLPTR;
}
else
{
return p_last;
}
}
};
template <typename TLink>
TLink etl::intrusive_forward_list_base<TLink>::terminator;
//***************************************************************************
//***************************************************************************
template <typename TValue, typename TLink>
class intrusive_forward_list : public etl::intrusive_forward_list_base<TLink>
{
public:
// Node typedef.
typedef typename etl::intrusive_forward_list_base<TLink>::link_type link_type;
// STL style typedefs.
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;
typedef intrusive_forward_list<TValue, TLink> list_type;
typedef TValue node_type;
//*************************************************************************
//*************************************************************************
class iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, value_type>
{
public:
friend class intrusive_forward_list;
friend class const_iterator;
iterator()
: p_value(ETL_NULLPTR)
{
}
iterator(const iterator& other)
: p_value(other.p_value)
{
}
iterator& operator++()
{
// Read the appropriate 'etl_next'.
p_value = p_value->etl_next;
return *this;
}
iterator operator++(int)
{
iterator temp(*this);
// Read the appropriate 'etl_next'.
p_value = p_value->etl_next;
return temp;
}
iterator& operator=(const iterator& other)
{
p_value = other.p_value;
return *this;
}
reference operator*() const
{
#include "private/diagnostic_null_dereference_push.h"
return *static_cast<pointer>(p_value);
#include "private/diagnostic_pop.h"
}
pointer operator&() const
{
return static_cast<pointer>(p_value);
}
pointer operator->() const
{
return static_cast<pointer>(p_value);
}
friend bool operator==(const iterator& lhs, const iterator& rhs)
{
return lhs.p_value == rhs.p_value;
}
friend bool operator!=(const iterator& lhs, const iterator& rhs)
{
return !(lhs == rhs);
}
private:
iterator(link_type* value)
: p_value(value)
{
}
link_type* p_value;
};
//*************************************************************************
//*************************************************************************
class const_iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, const value_type>
{
public:
friend class intrusive_forward_list;
const_iterator()
: p_value(ETL_NULLPTR)
{
}
const_iterator(const typename intrusive_forward_list::iterator& other)
: p_value(other.p_value)
{
}
const_iterator(const const_iterator& other)
: p_value(other.p_value)
{
}
const_iterator& operator++()
{
// Read the appropriate 'etl_next'.
p_value = p_value->etl_next;
return *this;
}
const_iterator operator++(int)
{
const_iterator temp(*this);
// Read the appropriate 'etl_next'.
p_value = p_value->etl_next;
return temp;
}
const_iterator& operator=(const const_iterator& other)
{
p_value = other.p_value;
return *this;
}
const_reference operator*() const
{
return *static_cast<const value_type*>(p_value);
}
const_pointer operator&() const
{
return static_cast<const value_type*>(p_value);
}
const_pointer operator->() const
{
return static_cast<const value_type*>(p_value);
}
friend bool operator==(const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.p_value == rhs.p_value;
}
friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs == rhs);
}
private:
const_iterator(const link_type* value)
: p_value(value)
{
}
const link_type* p_value;
};
typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
//*************************************************************************
//*************************************************************************
intrusive_forward_list() {}
//*************************************************************************
//*************************************************************************
~intrusive_forward_list() {}
//*************************************************************************
//*************************************************************************
template <typename TIterator>
intrusive_forward_list(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
{
this->assign(first, last);
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
template <typename... TLinks>
intrusive_forward_list(link_type& first, TLinks&... links)
{
ETL_STATIC_ASSERT((etl::is_base_of_all<link_type, TLinks...>::value), "Mixed link types");
this->current_size = 0;
this->start.etl_next = &first;
link_type* last = make_linked_list(this->current_size, first, static_cast<link_type&>(links)...);
last->etl_next = &this->terminator;
}
#endif
//*************************************************************************
//*************************************************************************
iterator begin()
{
return iterator(this->get_head());
}
//*************************************************************************
//*************************************************************************
const_iterator begin() const
{
return const_iterator(this->get_head());
}
//*************************************************************************
//*************************************************************************
iterator before_begin()
{
return iterator(&this->start);
}
//*************************************************************************
//*************************************************************************
const_iterator before_begin() const
{
return const_iterator(&this->start);
}
//*************************************************************************
//*************************************************************************
const_iterator cbegin() const
{
return const_iterator(this->get_head());
}
//*************************************************************************
//*************************************************************************
iterator end()
{
return iterator(&this->terminator);
}
//*************************************************************************
//*************************************************************************
const_iterator end() const
{
return const_iterator(&this->terminator);
}
//*************************************************************************
//*************************************************************************
const_iterator cend() const
{
return const_iterator(&this->terminator);
}
//*************************************************************************
//*************************************************************************
reference front()
{
ETL_ASSERT_CHECK_EXTRA(!this->empty(), ETL_ERROR(intrusive_forward_list_empty));
return *static_cast<pointer>(this->get_head());
}
//*************************************************************************
//*************************************************************************
const_reference front() const
{
ETL_ASSERT_CHECK_EXTRA(!this->empty(), ETL_ERROR(intrusive_forward_list_empty));
return *static_cast<const value_type*>(this->get_head());
}
//*************************************************************************
//*************************************************************************
iterator insert_after(iterator position, value_type& value)
{
ETL_ASSERT_OR_RETURN_VALUE(!value.link_type::is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked), iterator(&value));
this->insert_link_after(*position.p_value, value);
return iterator(&value);
}
//*************************************************************************
//*************************************************************************
template <typename TIterator>
void insert_after(iterator position, TIterator first, TIterator last)
{
while (first != last)
{
// Set up the next free link.
ETL_ASSERT_OR_RETURN(!(*first).link_type::is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked));
this->insert_link_after(*position.p_value, *first);
++first;
++position;
}
}
//*************************************************************************
//*************************************************************************
iterator erase_after(iterator position)
{
iterator next(position);
if (next != end())
{
++next;
if (next != end())
{
++next;
this->disconnect_link_after(*position.p_value);
}
}
return next;
}
//*************************************************************************
//*************************************************************************
iterator erase_after(iterator first, iterator last)
{
if (first != end() && (first != last))
{
this->current_size -= static_cast<size_t>(etl::distance(first, last) - 1);
link_type* p_first = first.p_value;
link_type* p_last = last.p_value;
link_type* p_after = this->remove_link_range_after(p_first, p_last);
if (p_after == ETL_NULLPTR)
{
return end();
}
else
{
return last;
}
}
else
{
return last;
}
}
//*************************************************************************
//*************************************************************************
node_type* erase(const node_type& node)
{
return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(&node)));
}
//*************************************************************************
//*************************************************************************
node_type* erase(const node_type* p_node)
{
return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(p_node)));
}
//*************************************************************************
//*************************************************************************
template <typename TIsEqual>
void unique(TIsEqual isEqual)
{
if (this->empty())
{
return;
}
link_type* last = this->get_head();
link_type* current = last->etl_next;
while (current != &this->terminator)
{
// Is this value the same as the last?
if (isEqual(*static_cast<pointer>(current), *static_cast<pointer>(last)))
{
this->disconnect_link_after(*last);
}
else
{
// Move on one.
last = current;
}
current = last->etl_next;
}
}
//*************************************************************************
//*************************************************************************
void sort()
{
sort(etl::less<value_type>());
}
//*************************************************************************
//*************************************************************************
template <typename TCompare>
void sort(TCompare compare)
{
iterator i_left;
iterator i_right;
iterator i_link;
iterator i_head;
iterator i_tail;
int list_size = 1;
int number_of_merges;
int left_size;
int right_size;
if (this->is_trivial_list())
{
return;
}
while (true)
{
i_left = begin();
i_head = before_begin();
i_tail = before_begin();
number_of_merges = 0; // Count the number of merges we do in this pass.
while (i_left != end())
{
++number_of_merges; // There exists a merge to be done.
i_right = i_left;
left_size = 0;
// Step 'list_size' places along from left
for (int i = 0; i < list_size; ++i)
{
++left_size;
++i_right;
if (i_right == end())
{
break;
}
}
// If right hasn't fallen off end, we have two lists to merge.
right_size = list_size;
// Now we have two lists. Merge them.
while (left_size > 0 || (right_size > 0 && i_right != end()))
{
// Decide whether the next link of merge comes from left or right.
if (left_size == 0)
{
// 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 link must come from left.
i_link = i_left;
++i_left;
--left_size;
}
else if (!compare(*i_right, *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 link of right is lower. The link must come from right.
i_link = i_right;
++i_right;
--right_size;
}
// Add the next link to the merged head.
if (i_head == before_begin())
{
etl::link<link_type>(i_head.p_value, i_link.p_value);
i_head = i_link;
i_tail = i_link;
}
else
{
etl::link<link_type>(i_tail.p_value, i_link.p_value);
i_tail = i_link;
}
i_tail.p_value->etl_next = &this->terminator;
}
// Now left has stepped `list_size' places along, and right has too.
i_left = i_right;
}
// If we have done only one merge, we're finished.
if (number_of_merges <= 1) // Allow for number_of_merges == 0, the empty head case
{
return;
}
// Otherwise repeat, merging lists twice the size
list_size *= 2;
}
}
//*************************************************************************
// Removes the values specified.
//*************************************************************************
void remove(const_reference value)
{
iterator i_item = begin();
iterator i_last_item = before_begin();
while (i_item != end())
{
if (*i_item == value)
{
i_item = erase_after(i_last_item);
}
else
{
++i_item;
++i_last_item;
}
}
}
//*************************************************************************
//*************************************************************************
template <typename TPredicate>
void remove_if(TPredicate predicate)
{
iterator i_item = begin();
iterator i_last_item = before_begin();
while (i_item != end())
{
if (predicate(*i_item))
{
i_item = erase_after(i_last_item);
}
else
{
++i_item;
++i_last_item;
}
}
}
//*************************************************************************
//*************************************************************************
void splice_after(iterator position, etl::intrusive_forward_list<TValue, TLink>& other)
{
// No point splicing to ourself!
if (&other != this)
{
if (!other.empty())
{
link_type& first = *other.get_head();
if (&other != this)
{
this->current_size += other.size();
}
link_type& before = *position.p_value;
link_type& after = *position.p_value->etl_next;
etl::link<link_type>(before, first);
link_type* last = &before;
while (last->etl_next != &other.terminator)
{
last = last->etl_next;
}
etl::link<link_type>(last, after);
other.initialise();
}
}
}
//*************************************************************************
//*************************************************************************
void splice_after(iterator position, etl::intrusive_forward_list<TValue, TLink>& other, iterator isource)
{
link_type& before = *position.p_value;
etl::unlink<link_type>(*isource.p_value);
etl::link_splice<link_type>(before, *isource.p_value);
if (&other != this)
{
++this->current_size;
--other.current_size;
}
}
//*************************************************************************
//*************************************************************************
void splice_after(iterator position, etl::intrusive_forward_list<TValue, TLink>& other, iterator begin_, iterator end_)
{
if (!other.empty())
{
if (&other != this)
{
size_t n = static_cast<size_t>(etl::distance(begin_, end_) - 1);
this->current_size += n;
other.current_size -= n;
}
link_type* first = begin_.p_value;
link_type* last = first;
while (last->etl_next != end_.p_value)
{
last = last->etl_next;
}
// Unlink from the source list.
link_type* first_next = first->etl_next;
etl::unlink_after(*first, *last);
// Fix our links.
link_type* before = position.p_value;
etl::link_splice<link_type>(*before, *first_next, *last);
}
}
//*************************************************************************
//*************************************************************************
void merge(list_type& other)
{
merge(other, etl::less<value_type>());
}
//*************************************************************************
//*************************************************************************
template <typename TCompare>
void merge(list_type& other, TCompare compare)
{
if ((this != &other) && !other.empty())
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(intrusive_forward_list_unsorted));
ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(intrusive_forward_list_unsorted));
#endif
link_type* other_begin = other.get_head();
link_type* other_terminal = &other.terminator;
link_type* before = &this->start;
link_type* before_next = get_next(before);
link_type* terminal = &this->terminator;
while ((before->etl_next != terminal) && (other_begin != other_terminal))
{
// Find the place to insert.
while ((before_next != terminal) && !(compare(*static_cast<pointer>(other_begin), *static_cast<pointer>(before_next))))
{
before = before_next;
before_next = get_next(before_next);
}
// Insert.
if (before_next != terminal)
{
while ((other_begin != other_terminal) && (compare(*static_cast<pointer>(other_begin), *static_cast<pointer>(before_next))))
{
link_type* value = other_begin;
other_begin = get_next(other_begin);
etl::link_splice<link_type>(*before, *value);
before = get_next(before);
}
}
}
// Any left over?
if (before_next == terminal)
{
while (other_begin != other_terminal)
{
link_type* value = other_begin;
other_begin = get_next(other_begin);
etl::link_splice<link_type>(*before, *value);
before = get_next(before);
}
}
this->current_size += other.size();
other.initialise();
}
}
//*************************************************************************
//*************************************************************************
bool contains(const_reference value) const
{
const_iterator i_item = begin();
while (i_item != end())
{
if (*i_item == value)
{
return true;
}
++i_item;
}
return false;
}
private:
#if ETL_USING_CPP17
//***************************************************************************
//***************************************************************************
template <typename... TLinks>
link_type* make_linked_list(size_t& count, link_type& first, TLinks&... links)
{
link_type* current = &first;
++count;
((current->etl_next = &links, current = &links, ++count), ...);
return current;
}
#elif ETL_USING_CPP11
//***************************************************************************
//***************************************************************************
link_type* make_linked_list(size_t& count, link_type& first)
{
++count;
return &first;
}
//***************************************************************************
//***************************************************************************
template <typename... TLinks>
link_type* make_linked_list(size_t& count, link_type& first, link_type& next, TLinks&... links)
{
++count;
first.etl_next = &next;
return make_linked_list(count, next, static_cast<link_type&>(links)...);
}
#endif
//*************************************************************************
//*************************************************************************
link_type* get_next(link_type* link) const
{
return link->etl_next;
}
// Disabled.
intrusive_forward_list(const intrusive_forward_list& other);
intrusive_forward_list& operator=(const intrusive_forward_list& rhs);
};
} // namespace etl
#include "private/minmax_pop.h"
#endif
algorithm.h
etl::intrusive_forward_list::iterator
iterator.
Definition intrusive_forward_list.h:479
etl::intrusive_forward_list_base
Definition intrusive_forward_list.h:145
etl::intrusive_forward_list_base::contains_node
bool contains_node(const link_type &search_link) const
Definition intrusive_forward_list.h:267
etl::intrusive_forward_list_base::is_trivial_list
bool is_trivial_list() const
Is the intrusive_forward_list a trivial length?
Definition intrusive_forward_list.h:309
etl::link_type::start
link_type start
Definition intrusive_forward_list.h:283
etl::intrusive_forward_list_base::reverse
void reverse()
Reverses the intrusive_forward_list.
Definition intrusive_forward_list.h:223
etl::intrusive_forward_list_base::insert_link_after
void insert_link_after(link_type &position, link_type &link)
Insert a link.
Definition intrusive_forward_list.h:317
etl::intrusive_forward_list_base::~intrusive_forward_list_base
~intrusive_forward_list_base()
Destructor.
Definition intrusive_forward_list.h:301
etl::intrusive_forward_list_base::empty
bool empty() const
Returns true if the list has no elements.
Definition intrusive_forward_list.h:250
etl::link_type::terminator
static link_type terminator
Definition intrusive_forward_list.h:285
etl::link_type::current_size
size_t current_size
Definition intrusive_forward_list.h:288
etl::intrusive_forward_list_base::intrusive_forward_list_base
intrusive_forward_list_base()
Constructor.
Definition intrusive_forward_list.h:293
etl::intrusive_forward_list_base::remove_link
link_type * remove_link(link_type *link)
Definition intrusive_forward_list.h:395
etl::intrusive_forward_list_base::contains_node
bool contains_node(const link_type *search_link) const
Definition intrusive_forward_list.h:276
etl::intrusive_forward_list_base::initialise
void initialise()
Initialise the intrusive_forward_list.
Definition intrusive_forward_list.h:361
etl::intrusive_forward_list_base::pop_front
void pop_front()
Removes a value from the front of the intrusive_forward_list.
Definition intrusive_forward_list.h:213
etl::intrusive_forward_list_base::is_link_in_list
link_type * is_link_in_list(const link_type *search_link) const
Definition intrusive_forward_list.h:371
etl::intrusive_forward_list_base::get_head
link_type * get_head()
Get the head link.
Definition intrusive_forward_list.h:345
etl::intrusive_forward_list_base::get_head
const link_type * get_head() const
Get the head link.
Definition intrusive_forward_list.h:353
etl::intrusive_forward_list_base::disconnect_link_after
void disconnect_link_after(link_type &link)
Remove a link.
Definition intrusive_forward_list.h:327
etl::intrusive_forward_list_base::assign
void assign(TIterator first, TIterator last)
Definition intrusive_forward_list.h:175
etl::intrusive_forward_list_base::size
size_t size() const
Returns the number of elements.
Definition intrusive_forward_list.h:258
etl::intrusive_forward_list_base::push_front
void push_front(link_type &value)
Pushes a value to the front of the intrusive_forward_list.
Definition intrusive_forward_list.h:203
etl::intrusive_forward_list_base::clear
void clear()
Clears the intrusive_forward_list.
Definition intrusive_forward_list.h:154
etl::intrusive_forward_list_base::remove_link_range_after
link_type * remove_link_range_after(link_type *p_first, link_type *p_last)
Remove a range of elements.
Definition intrusive_forward_list.h:419
etl::intrusive_forward_list_empty
Definition intrusive_forward_list.h:69
etl::intrusive_forward_list_iterator_exception
Definition intrusive_forward_list.h:84
etl::intrusive_forward_list_unsorted
Definition intrusive_forward_list.h:114
etl::intrusive_forward_list_value_is_already_linked
Definition intrusive_forward_list.h:129
etl::intrusive_forward_list
Definition intrusive_forward_list.h:457
etl::intrusive_forward_list::before_begin
const_iterator before_begin() const
Gets before the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:697
etl::intrusive_forward_list::contains
bool contains(const_reference value) const
Definition intrusive_forward_list.h:1229
etl::intrusive_forward_list::erase_after
iterator erase_after(iterator first, iterator last)
Erases a range of elements.
Definition intrusive_forward_list.h:808
etl::intrusive_forward_list::sort
void sort(TCompare compare)
Definition intrusive_forward_list.h:915
etl::intrusive_forward_list::cbegin
const_iterator cbegin() const
Gets the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:705
etl::intrusive_forward_list::splice_after
void splice_after(iterator position, etl::intrusive_forward_list< TValue, TLink > &other)
Splice another list into this one.
Definition intrusive_forward_list.h:1075
etl::intrusive_forward_list::~intrusive_forward_list
~intrusive_forward_list()
Destructor.
Definition intrusive_forward_list.h:643
etl::intrusive_forward_list::unique
void unique(TIsEqual isEqual)
Definition intrusive_forward_list.h:854
etl::intrusive_forward_list::splice_after
void splice_after(iterator position, etl::intrusive_forward_list< TValue, TLink > &other, iterator begin_, iterator end_)
Splice a range of elements from another list into this one.
Definition intrusive_forward_list.h:1127
etl::intrusive_forward_list::splice_after
void splice_after(iterator position, etl::intrusive_forward_list< TValue, TLink > &other, iterator isource)
Splice an element from another list into this one.
Definition intrusive_forward_list.h:1110
etl::intrusive_forward_list::insert_after
void insert_after(iterator position, TIterator first, TIterator last)
Definition intrusive_forward_list.h:773
etl::intrusive_forward_list::intrusive_forward_list
intrusive_forward_list(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Constructor from range.
Definition intrusive_forward_list.h:649
etl::intrusive_forward_list::remove_if
void remove_if(TPredicate predicate)
Removes according to a predicate.
Definition intrusive_forward_list.h:1053
etl::intrusive_forward_list::erase_after
iterator erase_after(iterator position)
Erases the value at the specified position.
Definition intrusive_forward_list.h:789
etl::intrusive_forward_list::insert_after
iterator insert_after(iterator position, value_type &value)
Definition intrusive_forward_list.h:760
etl::intrusive_forward_list::begin
const_iterator begin() const
Gets the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:681
etl::intrusive_forward_list::merge
void merge(list_type &other, TCompare compare)
Merge another list into this one. Both lists should be sorted.
Definition intrusive_forward_list.h:1169
etl::intrusive_forward_list::end
iterator end()
Gets the end of the intrusive_forward_list.
Definition intrusive_forward_list.h:713
etl::intrusive_forward_list::before_begin
iterator before_begin()
Gets before the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:689
etl::intrusive_forward_list::end
const_iterator end() const
Gets the end of the intrusive_forward_list.
Definition intrusive_forward_list.h:721
etl::intrusive_forward_list::front
const_reference front() const
Definition intrusive_forward_list.h:750
etl::intrusive_forward_list::cend
const_iterator cend() const
Gets the end of the intrusive_forward_list.
Definition intrusive_forward_list.h:729
etl::intrusive_forward_list::merge
void merge(list_type &other)
Merge another list into this one. Both lists should be sorted.
Definition intrusive_forward_list.h:1160
etl::intrusive_forward_list::sort
void sort()
Sort using in-place merge sort algorithm.
Definition intrusive_forward_list.h:884
etl::intrusive_forward_list::intrusive_forward_list
intrusive_forward_list()
Constructor.
Definition intrusive_forward_list.h:638
etl::intrusive_forward_list::begin
iterator begin()
Gets the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:673
etl::intrusive_forward_list::erase
node_type * erase(const node_type *p_node)
Erases the specified node.
Definition intrusive_forward_list.h:844
etl::intrusive_forward_list::erase
node_type * erase(const node_type &node)
Erases the specified node.
Definition intrusive_forward_list.h:836
etl::intrusive_forward_list::front
reference front()
Definition intrusive_forward_list.h:739
diagnostic_null_dereference_push.h
diagnostic_pop.h
error_handler.h
exception.h
functional.h
etl::is_sorted
ETL_NODISCARD ETL_CONSTEXPR14 bool is_sorted(TIterator begin, TIterator end)
Definition algorithm.h:1669
etl::remove
ETL_CONSTEXPR14 TIterator remove(TIterator first, TIterator last, const T &value)
Definition algorithm.h:2381
ETL_ASSERT
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
etl::exception::exception
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
intrusive_links.h
iterator.h
minmax_pop.h
minmax_push.h
etl
Definition absolute.h:40
etl::operator*
ETL_CONSTEXPR14 enable_if<!etl::is_specialization< TRep2, etl::chrono::duration >::value, etl::chrono::duration< typenameetl::common_type< TRep1, TRep2 >::type, TPeriod1 > >::type operator*(const etl::chrono::duration< TRep1, TPeriod1 > &lhs, const TRep2 &rhs) ETL_NOEXCEPT
Operator *.
Definition duration.h:541
nullptr.h
platform.h
etl::compare
Definition compare.h:51
etl::iterator
iterator
Definition iterator.h:482
etl::less
Definition functional.h:201
etl::type
operator==
ETL_CONSTEXPR14 bool operator==(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Equality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:903
operator!=
ETL_CONSTEXPR14 bool operator!=(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Inequality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:937
type_traits.h