Loading...
Searching...
No Matches
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) 2014 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_LIST_INCLUDED
#define ETL_LIST_INCLUDED
#include "platform.h"
#include "algorithm.h"
#include "debug_count.h"
#include "error_handler.h"
#include "exception.h"
#include "functional.h"
#include "initializer_list.h"
#include "iterator.h"
#include "memory.h"
#include "nullptr.h"
#include "parameter_type.h"
#include "placement_new.h"
#include "pool.h"
#include "static_assert.h"
#include "type_traits.h"
#include <stddef.h>
#include "private/minmax_push.h"
//*****************************************************************************
//*****************************************************************************
namespace etl
{
//***************************************************************************
//***************************************************************************
class list_exception : public exception
{
public:
list_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: exception(reason_, file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class list_full : public list_exception
{
public:
list_full(string_type file_name_, numeric_type line_number_)
: list_exception(ETL_ERROR_TEXT("list:full", ETL_LIST_FILE_ID"A"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class list_empty : public list_exception
{
public:
list_empty(string_type file_name_, numeric_type line_number_)
: list_exception(ETL_ERROR_TEXT("list:empty", ETL_LIST_FILE_ID"B"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class list_iterator : public list_exception
{
public:
list_iterator(string_type file_name_, numeric_type line_number_)
: list_exception(ETL_ERROR_TEXT("list:iterator", ETL_LIST_FILE_ID"C"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
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_LIST_FILE_ID"D"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class list_no_pool : public list_exception
{
public:
list_no_pool(string_type file_name_, numeric_type line_number_)
: list_exception(ETL_ERROR_TEXT("list:no pool", ETL_LIST_FILE_ID"E"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class list_base
{
public:
typedef size_t size_type;
//*************************************************************************
//*************************************************************************
struct node_t
{
//***********************************************************************
//***********************************************************************
node_t()
: previous(ETL_NULLPTR)
, next(ETL_NULLPTR)
{
}
//***********************************************************************
//***********************************************************************
void reverse()
{
using ETL_OR_STD::swap; // Allow ADL
swap(previous, next);
}
node_t* previous;
node_t* next;
};
//*************************************************************************
//*************************************************************************
bool has_shared_pool() const
{
return pool_is_shared;
}
//*************************************************************************
//*************************************************************************
void reverse()
{
if (is_trivial_list())
{
return;
}
node_t* p_node = terminal_node.next;
while (p_node != &terminal_node)
{
node_t* p_temp = p_node->previous;
p_node->previous = p_node->next;
p_node->next = p_temp;
p_node = p_node->previous;
}
// Terminal node.
node_t* p_temp = p_node->previous;
p_node->previous = p_node->next;
p_node->next = p_temp;
}
//*************************************************************************
//*************************************************************************
size_type max_size() const
{
return MAX_SIZE;
}
//*************************************************************************
//*************************************************************************
size_type capacity() const
{
return MAX_SIZE;
}
//*************************************************************************
//*************************************************************************
size_type size() const
{
if (has_shared_pool())
{
// We have to count what we actually own.
size_type count = 0U;
node_t* p_node = terminal_node.next;
while (p_node != &terminal_node)
{
++count;
p_node = p_node->next;
}
return count;
}
else
{
return p_node_pool->size();
}
}
//*************************************************************************
//*************************************************************************
bool empty() const
{
return (terminal_node.next == &terminal_node);
}
//*************************************************************************
//*************************************************************************
bool full() const
{
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
return p_node_pool->full();
}
//*************************************************************************
//*************************************************************************
size_type available() const
{
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
return p_node_pool->available();
}
protected:
//*************************************************************************
//*************************************************************************
bool is_trivial_list() const
{
return (size() < 2);
}
//*************************************************************************
//*************************************************************************
node_t& get_head()
{
return *terminal_node.next;
}
//*************************************************************************
//*************************************************************************
const node_t& get_head() const
{
return *terminal_node.next;
}
//*************************************************************************
//*************************************************************************
node_t& get_tail()
{
return *terminal_node.previous;
}
//*************************************************************************
//*************************************************************************
const node_t& get_tail() const
{
return *terminal_node.previous;
}
//*************************************************************************
//*************************************************************************
void insert_node(node_t& position, node_t& node)
{
// Connect to the list.
join(*position.previous, node);
join(node, position);
}
//*************************************************************************
//*************************************************************************
void join(node_t& left, node_t& right)
{
left.next = &right;
right.previous = &left;
}
//*************************************************************************
//*************************************************************************
explicit list_base(bool pool_is_shared_)
: p_node_pool(ETL_NULLPTR)
, MAX_SIZE(0)
, pool_is_shared(pool_is_shared_)
{
join(terminal_node, terminal_node);
}
//*************************************************************************
//*************************************************************************
list_base(etl::ipool& node_pool_, size_type max_size_, bool pool_is_shared_)
: p_node_pool(&node_pool_)
, MAX_SIZE(max_size_)
, pool_is_shared(pool_is_shared_)
{
join(terminal_node, terminal_node);
}
//*************************************************************************
//*************************************************************************
void set_node_pool(etl::ipool& node_pool_)
{
p_node_pool = &node_pool_;
MAX_SIZE = p_node_pool->max_size();
}
//*************************************************************************
//*************************************************************************
etl::ipool* get_node_pool()
{
return p_node_pool;
}
//*************************************************************************
//*************************************************************************
~list_base() {}
etl::ipool* p_node_pool;
node_t terminal_node;
size_type MAX_SIZE;
bool pool_is_shared;
ETL_DECLARE_DEBUG_COUNT;
};
//***************************************************************************
//***************************************************************************
template <typename T>
class ilist : public etl::list_base
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
#if ETL_USING_CPP11
typedef T&& rvalue_reference;
#endif
typedef size_t size_type;
protected:
typedef typename etl::parameter_type<T>::type parameter_t;
//*************************************************************************
//*************************************************************************
struct data_node_t : public node_t
{
explicit data_node_t(const T& value_)
: value(value_)
{
}
T value;
};
private:
//*************************************************************************
//*************************************************************************
static data_node_t* data_cast(node_t* p_node)
{
return reinterpret_cast<data_node_t*>(p_node);
}
//*************************************************************************
//*************************************************************************
static data_node_t& data_cast(node_t& node)
{
return reinterpret_cast<data_node_t&>(node);
}
//*************************************************************************
//*************************************************************************
static const data_node_t* data_cast(const node_t* p_node)
{
return reinterpret_cast<const data_node_t*>(p_node);
}
//*************************************************************************
//*************************************************************************
static const data_node_t& data_cast(const node_t& node)
{
return reinterpret_cast<const data_node_t&>(node);
}
public:
//*************************************************************************
//*************************************************************************
class iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, T>
{
public:
friend class ilist;
friend class const_iterator;
iterator()
: p_node(ETL_NULLPTR)
{
}
iterator(node_t& node)
: p_node(&node)
{
}
iterator(const iterator& other)
: p_node(other.p_node)
{
}
iterator& operator++()
{
p_node = p_node->next;
return *this;
}
iterator operator++(int)
{
iterator temp(*this);
p_node = p_node->next;
return temp;
}
iterator& operator--()
{
p_node = p_node->previous;
return *this;
}
iterator operator--(int)
{
iterator temp(*this);
p_node = p_node->previous;
return temp;
}
iterator& operator=(const iterator& other)
{
p_node = other.p_node;
return *this;
}
reference operator*() const
{
return ilist::data_cast(p_node)->value;
}
pointer operator&() const
{
return &(ilist::data_cast(p_node)->value);
}
pointer operator->() const
{
return &(ilist::data_cast(p_node)->value);
}
friend bool operator==(const iterator& lhs, const iterator& rhs)
{
return lhs.p_node == rhs.p_node;
}
friend bool operator!=(const iterator& lhs, const iterator& rhs)
{
return !(lhs == rhs);
}
private:
node_t* p_node;
};
//*************************************************************************
//*************************************************************************
class const_iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, const T>
{
public:
friend class ilist;
const_iterator()
: p_node(ETL_NULLPTR)
{
}
const_iterator(node_t& node)
: p_node(&node)
{
}
const_iterator(const node_t& node)
: p_node(&node)
{
}
const_iterator(const typename ilist::iterator& other)
: p_node(other.p_node)
{
}
const_iterator(const const_iterator& other)
: p_node(other.p_node)
{
}
const_iterator& operator++()
{
p_node = p_node->next;
return *this;
}
const_iterator operator++(int)
{
const_iterator temp(*this);
p_node = p_node->next;
return temp;
}
const_iterator& operator--()
{
p_node = p_node->previous;
return *this;
}
const_iterator operator--(int)
{
const_iterator temp(*this);
p_node = p_node->previous;
return temp;
}
const_iterator& operator=(const const_iterator& other)
{
p_node = other.p_node;
return *this;
}
const_reference operator*() const
{
return ilist::data_cast(p_node)->value;
}
const_pointer operator&() const
{
return &(ilist::data_cast(p_node)->value);
}
const_pointer operator->() const
{
return &(ilist::data_cast(p_node)->value);
}
friend bool operator==(const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.p_node == rhs.p_node;
}
friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs == rhs);
}
private:
const node_t* p_node;
};
typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
//*************************************************************************
//*************************************************************************
iterator begin()
{
return iterator(get_head());
}
//*************************************************************************
//*************************************************************************
const_iterator begin() const
{
return const_iterator(get_head());
}
//*************************************************************************
//*************************************************************************
iterator end()
{
return iterator(terminal_node);
}
//*************************************************************************
//*************************************************************************
const_iterator end() const
{
return const_iterator(terminal_node);
}
//*************************************************************************
//*************************************************************************
const_iterator cbegin() const
{
return const_iterator(get_head());
}
//*************************************************************************
//*************************************************************************
const_iterator cend() const
{
return const_iterator(terminal_node);
}
//*************************************************************************
//*************************************************************************
reverse_iterator rbegin()
{
return reverse_iterator(terminal_node);
}
//*************************************************************************
//*************************************************************************
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(terminal_node);
}
//*************************************************************************
//*************************************************************************
reverse_iterator rend()
{
return reverse_iterator(get_head());
}
//*************************************************************************
//*************************************************************************
const_reverse_iterator rend() const
{
return const_reverse_iterator(get_head());
}
//*************************************************************************
//*************************************************************************
const_reverse_iterator crbegin() const
{
return const_reverse_iterator(terminal_node);
}
//*************************************************************************
//*************************************************************************
const_reverse_iterator crend() const
{
return const_reverse_iterator(get_head());
}
//*************************************************************************
//*************************************************************************
reference front()
{
ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(list_empty));
return data_cast(get_head()).value;
}
//*************************************************************************
//*************************************************************************
const_reference front() const
{
ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(list_empty));
return data_cast(get_head()).value;
}
//*************************************************************************
//*************************************************************************
reference back()
{
ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(list_empty));
return data_cast(get_tail()).value;
}
//*************************************************************************
//*************************************************************************
const_reference back() const
{
ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(list_empty));
return data_cast(get_tail()).value;
}
//*************************************************************************
//*************************************************************************
template <typename TIterator>
void assign(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
{
#if ETL_IS_DEBUG_BUILD
difference_type d = etl::distance(first, last);
ETL_ASSERT(d >= 0, ETL_ERROR(list_iterator));
ETL_ASSERT(size_t(d) <= MAX_SIZE, ETL_ERROR(list_full));
#endif
initialise();
// Add all of the elements.
while (first != last)
{
data_node_t& node = allocate_data_node(*first);
join(get_tail(), node);
join(node, terminal_node);
++first;
}
}
//*************************************************************************
//*************************************************************************
void assign(size_t n, const T& value)
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(list_full));
#endif
initialise();
// Add all of the elements.
while (n-- > 0)
{
data_node_t& node = allocate_data_node(value);
join(*terminal_node.previous, node);
join(node, terminal_node);
}
}
//*************************************************************************
//*************************************************************************
void push_front(const T& value)
{
ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(list_full));
insert_node(get_head(), allocate_data_node(value));
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
void push_front(rvalue_reference value)
{
ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(list_full));
insert_node(get_head(), allocate_data_node(etl::move(value)));
}
#endif
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_LIST_FORCE_CPP03_IMPLEMENTATION)
//*************************************************************************
//*************************************************************************
template <typename... Args>
reference emplace_front(Args&&... args)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(etl::forward<Args>(args)...);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(get_head(), *p_data_node);
return front();
}
#else
//*************************************************************************
//*************************************************************************
reference emplace_front()
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T();
ETL_INCREMENT_DEBUG_COUNT;
insert_node(get_head(), *p_data_node);
return front();
}
//*************************************************************************
//*************************************************************************
template <typename T1>
reference emplace_front(const T1& value1)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value1);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(get_head(), *p_data_node);
return front();
}
//*************************************************************************
//*************************************************************************
template <typename T1, typename T2>
reference emplace_front(const T1& value1, const T2& value2)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value1, value2);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(get_head(), *p_data_node);
return front();
}
//*************************************************************************
//*************************************************************************
template <typename T1, typename T2, typename T3>
reference emplace_front(const T1& value1, const T2& value2, const T3& value3)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value1, value2, value3);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(get_head(), *p_data_node);
return front();
}
//*************************************************************************
//*************************************************************************
template <typename T1, typename T2, typename T3, typename T4>
reference emplace_front(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value1, value2, value3, value4);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(get_head(), *p_data_node);
return front();
}
#endif
//*************************************************************************
//*************************************************************************
void pop_front()
{
ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!empty(), ETL_ERROR(list_empty));
node_t& node = get_head();
remove_node(node);
}
//*************************************************************************
//*************************************************************************
void push_back(const T& value)
{
ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(list_full));
insert_node(terminal_node, allocate_data_node(value));
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
void push_back(rvalue_reference value)
{
ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(list_full));
insert_node(terminal_node, allocate_data_node(etl::move(value)));
}
#endif
//*************************************************************************
//*************************************************************************
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
template <typename... Args>
reference emplace_back(Args&&... args)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(etl::forward<Args>(args)...);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(terminal_node, *p_data_node);
return back();
}
#else
reference emplace_back()
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T();
ETL_INCREMENT_DEBUG_COUNT;
insert_node(terminal_node, *p_data_node);
return back();
}
template <typename T1>
reference emplace_back(const T1& value1)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value1);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(terminal_node, *p_data_node);
return back();
}
template <typename T1, typename T2>
reference emplace_back(const T1& value1, const T2& value2)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value1, value2);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(terminal_node, *p_data_node);
return back();
}
template <typename T1, typename T2, typename T3>
reference emplace_back(const T1& value1, const T2& value2, const T3& value3)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value1, value2, value3);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(terminal_node, *p_data_node);
return back();
}
template <typename T1, typename T2, typename T3, typename T4>
reference emplace_back(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
{
ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value1, value2, value3, value4);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(terminal_node, *p_data_node);
return back();
}
#endif
//*************************************************************************
//*************************************************************************
void pop_back()
{
ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!empty(), ETL_ERROR(list_empty));
node_t& node = get_tail();
remove_node(node);
}
//*************************************************************************
//*************************************************************************
iterator insert(const_iterator position, const_reference value)
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
data_node_t& data_node = allocate_data_node(value);
insert_node(*to_iterator(position).p_node, data_node);
return iterator(data_node);
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
iterator insert(const_iterator position, rvalue_reference value)
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
data_node_t& data_node = allocate_data_node(etl::move(value));
insert_node(*to_iterator(position).p_node, data_node);
return iterator(data_node);
}
#endif
//*************************************************************************
//*************************************************************************
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_LIST_FORCE_CPP03_IMPLEMENTATION)
template <typename... Args>
iterator emplace(const_iterator position, Args&&... args)
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(etl::forward<Args>(args)...);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(*to_iterator(position).p_node, *p_data_node);
return iterator(*p_data_node);
}
#else
iterator emplace(const_iterator position)
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T();
ETL_INCREMENT_DEBUG_COUNT;
insert_node(*to_iterator(position).p_node, *p_data_node);
return iterator(*p_data_node);
}
template <typename T1>
iterator emplace(const_iterator position, const T1& value1)
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value1);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(*to_iterator(position).p_node, *p_data_node);
return iterator(*p_data_node);
}
template <typename T1, typename T2>
iterator emplace(const_iterator position, const T1& value1, const T2& value2)
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value1, value2);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(*to_iterator(position).p_node, *p_data_node);
return iterator(*p_data_node);
}
template <typename T1, typename T2, typename T3>
iterator emplace(const_iterator position, const T1& value1, const T2& value2, const T3& value3)
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value1, value2, value3);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(*to_iterator(position).p_node, *p_data_node);
return iterator(*p_data_node);
}
template <typename T1, typename T2, typename T3, typename T4>
iterator emplace(const_iterator position, const T1& value1, const T2& value2, const T3& value3, const T4& value4)
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value1, value2, value3, value4);
ETL_INCREMENT_DEBUG_COUNT;
insert_node(*to_iterator(position).p_node, *p_data_node);
return iterator(*p_data_node);
}
#endif
//*************************************************************************
//*************************************************************************
void insert(const_iterator position, size_t n, const_reference value)
{
for (size_t i = 0UL; i < n; ++i)
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
// Set up the next free node and insert.
insert_node(*to_iterator(position).p_node, allocate_data_node(value));
}
}
//*************************************************************************
//*************************************************************************
template <typename TIterator>
void insert(const_iterator position, TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
{
while (first != last)
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
// Set up the next free node and insert.
insert_node(*to_iterator(position).p_node, allocate_data_node(*first));
++first;
}
}
//*************************************************************************
//*************************************************************************
iterator erase(const_iterator position)
{
iterator position_ = to_iterator(position);
++position_;
remove_node(*position_.p_node->previous);
return position_;
}
//*************************************************************************
//*************************************************************************
iterator erase(const_iterator first, const_iterator last)
{
iterator first_ = to_iterator(first);
iterator last_ = to_iterator(last);
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);
// Erase the ones in between.
while (p_first != p_last)
{
p_next = p_first->next; // Remember the next node.
destroy_data_node(static_cast<data_node_t&>(*p_first)); // Destroy the current node.
p_first = p_next; // Move to the next node.
}
return last_;
}
//*************************************************************************
//*************************************************************************
void resize(size_t n)
{
resize(n, T());
}
//*************************************************************************
//*************************************************************************
void resize(size_t n, const_reference value)
{
ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(list_full));
// Zero?
if (n == 0U)
{
clear();
}
// Smaller?
else if (n < size())
{
iterator i_start = end();
etl::advance(i_start, -difference_type(size() - n));
erase(i_start, end());
}
// Larger?
else if (n > size())
{
insert(end(), n - size(), value);
}
}
//*************************************************************************
//*************************************************************************
void clear()
{
initialise();
}
//*************************************************************************
// Removes the values specified.
//*************************************************************************
void remove(const_reference value)
{
iterator iValue = begin();
while (iValue != end())
{
if (value == *iValue)
{
iValue = erase(iValue);
}
else
{
++iValue;
}
}
}
//*************************************************************************
//*************************************************************************
template <typename TPredicate>
void remove_if(TPredicate predicate)
{
iterator iValue = begin();
while (iValue != end())
{
if (predicate(*iValue))
{
iValue = erase(iValue);
}
else
{
++iValue;
}
}
}
//*************************************************************************
//*************************************************************************
void unique()
{
unique(etl::equal_to<T>());
}
//*************************************************************************
//*************************************************************************
template <typename TIsEqual>
void unique(TIsEqual isEqual)
{
if (empty())
{
return;
}
iterator i_item = begin();
++i_item;
iterator i_previous = begin();
while (i_item != end())
{
if (isEqual(*i_previous, *i_item))
{
i_item = erase(i_item);
}
else
{
i_previous = i_item;
++i_item;
}
}
}
//*************************************************************************
//*************************************************************************
void splice(iterator to, ilist& other)
{
if (&other != this)
{
insert(to, other.begin(), other.end());
other.erase(other.begin(), other.end());
}
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
void splice(iterator to, ilist&& other)
{
if (&other != this)
{
typename ilist<T>::iterator itr = other.begin();
while (itr != other.end())
{
to = insert(to, etl::move(*itr));
++itr;
}
other.erase(other.begin(), other.end());
}
}
#endif
//*************************************************************************
//*************************************************************************
void splice(iterator to, ilist& other, iterator from)
{
if (&other == this)
{
// Internal move.
move(to, from);
}
else
{
// From another list.
insert(to, *from);
other.erase(from);
}
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
void splice(iterator to, ilist&& other, iterator from)
{
if (&other == this)
{
// Internal move.
move(to, from);
}
else
{
// From another list.
insert(to, etl::move(*from));
other.erase(from);
}
}
#endif
//*************************************************************************
//*************************************************************************
void splice(iterator to, ilist& other, iterator first, iterator last)
{
if (&other == this)
{
// Internal move.
move(to, first, last);
}
else
{
// From another list.
insert(to, first, last);
other.erase(first, last);
}
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
void splice(iterator to, ilist&& other, iterator first, iterator last)
{
if (&other == this)
{
// Internal move.
move(to, first, last);
}
else
{
// From another list.
ilist::iterator itr = first;
while (itr != last)
{
to = insert(to, etl::move(*itr));
++itr;
++to;
}
other.erase(first, last);
}
}
#endif
//*************************************************************************
//*************************************************************************
void merge(ilist& other)
{
merge(other, etl::less<value_type>());
}
//*************************************************************************
//*************************************************************************
template <typename TCompare>
void merge(ilist& 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(list_unsorted));
ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(list_unsorted));
#endif
ilist::iterator other_begin = other.begin();
ilist::iterator other_end = other.end();
ilist::iterator this_begin = begin();
ilist::iterator this_end = end();
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();
}
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
void merge(ilist&& other)
{
merge(etl::move(other), etl::less<value_type>());
}
//*************************************************************************
//*************************************************************************
template <typename TCompare>
void merge(ilist&& other, TCompare compare)
{
if (!other.empty())
{
#if ETL_IS_DEBUG_BUILD
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
ilist::iterator other_begin = other.begin();
ilist::iterator other_end = other.end();
ilist::iterator this_begin = begin();
ilist::iterator this_end = end();
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, etl::move(*other_begin));
++other_begin;
}
}
}
// Any left over?
if ((this_begin == this_end) && (other_begin != other_end))
{
while (other_begin != other_end)
{
insert(this_end, etl::move(*other_begin));
++other_begin;
}
}
other.clear();
}
}
#endif
//*************************************************************************
//*************************************************************************
void sort()
{
sort(etl::less<T>());
}
//*************************************************************************
//*************************************************************************
template <typename TCompare>
void sort(TCompare compare)
{
iterator i_left;
iterator i_right;
iterator i_node;
iterator i_head;
iterator i_tail;
int list_size = 1;
int number_of_merges;
int left_size;
int right_size;
if (is_trivial_list())
{
return;
}
while (true)
{
i_left = begin();
i_head = end();
i_tail = end();
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 node of merge comes from left or right.
if (left_size == 0)
{
// Left is empty. The node must come from right.
i_node = 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++;
--left_size;
}
else if (!compare(*i_right, *i_left))
{
// First node of left is lower or same. The node must come from
// left.
i_node = i_left++;
--left_size;
}
else
{
// First node of right is lower. The node must come from right.
i_node = i_right;
++i_right;
--right_size;
}
// Add the next node to the merged head.
if (i_head == end())
{
join(*i_head.p_node, *i_node.p_node);
i_head = i_node;
i_tail = i_node;
}
else
{
join(*i_tail.p_node, *i_node.p_node);
i_tail = i_node;
}
join(*i_tail.p_node, terminal_node);
}
// 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;
}
}
//*************************************************************************
//*************************************************************************
ilist& operator=(const ilist& rhs)
{
if (&rhs != this)
{
assign(rhs.cbegin(), rhs.cend());
}
return *this;
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
ilist& operator=(ilist&& rhs)
{
if (&rhs != this)
{
this->initialise();
iterator itr = rhs.begin();
while (itr != rhs.end())
{
push_back(etl::move(*itr));
++itr;
}
rhs.initialise();
}
return *this;
}
#endif
protected:
//*************************************************************************
//*************************************************************************
ilist(bool pool_is_shared_)
: list_base(pool_is_shared_)
{
}
//*************************************************************************
//*************************************************************************
ilist(etl::ipool& node_pool, size_t max_size_, bool pool_is_shared_)
: list_base(node_pool, max_size_, pool_is_shared_)
{
}
//*************************************************************************
//*************************************************************************
void initialise()
{
if (this->p_node_pool != ETL_NULLPTR)
{
if (!empty())
{
if (etl::is_trivially_destructible<T>::value && !has_shared_pool())
{
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
p_node_pool->release_all();
ETL_RESET_DEBUG_COUNT;
}
else
{
node_t* p_first = terminal_node.next;
node_t* p_last = &terminal_node;
while (p_first != p_last)
{
destroy_data_node(static_cast<data_node_t&>(*p_first)); // Destroy the current node.
p_first = p_first->next; // Move to the next node.
}
}
}
}
join(terminal_node, terminal_node);
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
void move_container(ilist&& rhs)
{
if (&rhs != this)
{
this->initialise();
if (!rhs.empty())
{
// Are we using the same pool?
if (this->get_node_pool() == rhs.get_node_pool())
{
// Just link the nodes to this list.
join(terminal_node, rhs.get_head());
join(rhs.get_tail(), terminal_node);
ETL_SET_DEBUG_COUNT(ETL_OBJECT_GET_DEBUG_COUNT(rhs));
// Clear the rhs.
ETL_OBJECT_RESET_DEBUG_COUNT(rhs);
rhs.join(rhs.terminal_node, rhs.terminal_node);
}
else
{
// Add all of the elements.
etl::ilist<T>::iterator first = rhs.begin();
etl::ilist<T>::iterator last = rhs.end();
while (first != last)
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
insert_node(terminal_node, this->allocate_data_node(etl::move(*first)));
++first;
}
rhs.initialise();
}
}
}
}
#endif
private:
//*************************************************************************
//*************************************************************************
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);
}
//*************************************************************************
//*************************************************************************
void move(iterator to, iterator first, iterator last)
{
if ((first == to) || (last == to))
{
return; // Can't more to before yourself!
}
#if ETL_IS_DEBUG_BUILD
// 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);
}
//*************************************************************************
//*************************************************************************
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_t&>(node));
}
//*************************************************************************
//*************************************************************************
data_node_t& allocate_data_node(const_reference value)
{
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(value);
ETL_INCREMENT_DEBUG_COUNT;
return *p_data_node;
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
data_node_t& allocate_data_node(rvalue_reference value)
{
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
data_node_t* p_data_node = allocate_data_node();
::new (&(p_data_node->value)) T(etl::move(value));
ETL_INCREMENT_DEBUG_COUNT;
return *p_data_node;
}
#endif
//*************************************************************************
//*************************************************************************
data_node_t* allocate_data_node()
{
data_node_t* (etl::ipool::*func)() = &etl::ipool::allocate<data_node_t>;
return (p_node_pool->*func)();
}
//*************************************************************************
//*************************************************************************
void destroy_data_node(data_node_t& node)
{
ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool));
node.value.~T();
p_node_pool->release(&node);
ETL_DECREMENT_DEBUG_COUNT;
}
// Disable copy construction.
ilist(const ilist&);
#if defined(ETL_POLYMORPHIC_LIST) || defined(ETL_POLYMORPHIC_CONTAINERS)
public:
virtual ~ilist() {}
#else
protected:
~ilist() {}
#endif
private:
//*************************************************************************
//*************************************************************************
iterator to_iterator(const_iterator itr) const
{
return iterator(*(const_cast<node_t*>(itr.p_node)));
}
};
//*************************************************************************
//*************************************************************************
template <typename T, const size_t MAX_SIZE_>
class list : public etl::ilist<T>
{
public:
ETL_STATIC_ASSERT((MAX_SIZE_ > 0U), "Zero capacity etl::list is not valid");
static ETL_CONSTANT size_t MAX_SIZE = MAX_SIZE_;
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
#if ETL_USING_CPP11
typedef T&& rvalue_reference;
#endif
typedef size_t size_type;
//*************************************************************************
//*************************************************************************
list()
: etl::ilist<T>(node_pool, MAX_SIZE, false)
{
}
//*************************************************************************
//*************************************************************************
~list()
{
this->initialise();
}
//*************************************************************************
//*************************************************************************
explicit list(size_t initial_size)
: etl::ilist<T>(node_pool, MAX_SIZE, false)
{
this->assign(initial_size, T());
}
//*************************************************************************
//*************************************************************************
list(size_t initial_size, const T& value)
: etl::ilist<T>(node_pool, MAX_SIZE, false)
{
this->assign(initial_size, value);
}
//*************************************************************************
//*************************************************************************
list(const list& other)
: etl::ilist<T>(node_pool, MAX_SIZE, false)
{
if (this != &other)
{
this->assign(other.cbegin(), other.cend());
}
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
list(list&& other)
: etl::ilist<T>(node_pool, MAX_SIZE, false)
{
if (this != &other)
{
this->initialise();
typename etl::ilist<T>::iterator itr = other.begin();
while (itr != other.end())
{
this->push_back(etl::move(*itr));
++itr;
}
other.initialise();
}
}
#endif
//*************************************************************************
//*************************************************************************
template <typename TIterator>
list(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
: ilist<T>(node_pool, MAX_SIZE, false)
{
this->assign(first, last);
}
#if ETL_HAS_INITIALIZER_LIST
//*************************************************************************
//*************************************************************************
list(std::initializer_list<T> init)
: ilist<T>(node_pool, MAX_SIZE, false)
{
this->assign(init.begin(), init.end());
}
#endif
//*************************************************************************
//*************************************************************************
list& operator=(const list& rhs)
{
if (&rhs != this)
{
this->assign(rhs.cbegin(), rhs.cend());
}
return *this;
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
list& operator=(list&& rhs)
{
this->move_container(etl::move(rhs));
return *this;
}
#endif
private:
etl::pool<typename etl::ilist<T>::data_node_t, MAX_SIZE> node_pool;
};
template <typename T, const size_t MAX_SIZE_>
ETL_CONSTANT size_t list<T, MAX_SIZE_>::MAX_SIZE;
//*************************************************************************
//*************************************************************************
#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST
template <typename... T>
list(T...) -> list<typename etl::common_type_t<T...>, sizeof...(T)>;
#endif
//*************************************************************************
//*************************************************************************
#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
template <typename... T>
constexpr auto make_list(T... t) -> etl::list<typename etl::common_type_t<T...>, sizeof...(T)>
{
return {etl::forward<T>(t)...};
}
#endif
//*************************************************************************
//*************************************************************************
template <typename T>
class list_ext : public etl::ilist<T>
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef typename etl::ilist<T>::data_node_t pool_type;
//*************************************************************************
//*************************************************************************
list_ext()
: etl::ilist<T>(true)
{
}
//*************************************************************************
//*************************************************************************
explicit list_ext(etl::ipool& node_pool)
: etl::ilist<T>(node_pool, node_pool.max_size(), true)
{
}
//*************************************************************************
//*************************************************************************
~list_ext()
{
this->initialise();
}
//*************************************************************************
//*************************************************************************
explicit list_ext(size_t initial_size, etl::ipool& node_pool)
: etl::ilist<T>(node_pool, node_pool.max_size(), true)
{
this->assign(initial_size, T());
}
//*************************************************************************
//*************************************************************************
list_ext(size_t initial_size, const T& value, etl::ipool& node_pool)
: etl::ilist<T>(node_pool, node_pool.max_size(), true)
{
this->assign(initial_size, value);
}
//*************************************************************************
//*************************************************************************
list_ext(const list_ext& other)
: etl::ilist<T>(*other.p_node_pool, other.p_node_pool->max_size(), true)
{
if (this != &other)
{
this->assign(other.cbegin(), other.cend());
}
}
//*************************************************************************
//*************************************************************************
list_ext(const list_ext& other, etl::ipool& node_pool)
: etl::ilist<T>(node_pool, node_pool.max_size(), true)
{
if (this != &other)
{
this->assign(other.cbegin(), other.cend());
}
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
list_ext(list_ext&& other)
: etl::ilist<T>(*other.p_node_pool, other.p_node_pool->max_size(), true)
{
this->move_container(etl::move(other));
}
//*************************************************************************
//*************************************************************************
list_ext(list_ext&& other, etl::ipool& node_pool)
: etl::ilist<T>(node_pool, node_pool.max_size(), true)
{
this->move_container(etl::move(other));
}
#endif
//*************************************************************************
//*************************************************************************
template <typename TIterator>
list_ext(TIterator first, TIterator last, etl::ipool& node_pool, typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
: ilist<T>(node_pool, node_pool.max_size(), true)
{
this->assign(first, last);
}
#if ETL_HAS_INITIALIZER_LIST
//*************************************************************************
//*************************************************************************
list_ext(std::initializer_list<T> init, etl::ipool& node_pool)
: ilist<T>(node_pool, node_pool.max_size(), true)
{
this->assign(init.begin(), init.end());
}
#endif
//*************************************************************************
//*************************************************************************
list_ext& operator=(const list_ext& rhs)
{
if (&rhs != this)
{
this->assign(rhs.cbegin(), rhs.cend());
}
return *this;
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
list_ext& operator=(list_ext&& rhs)
{
this->move_container(etl::move(rhs));
return *this;
}
#endif
//*************************************************************************
//*************************************************************************
void set_pool(etl::ipool& pool)
{
// Clear the list of any current elements.
if (this->get_node_pool() != ETL_NULLPTR)
{
this->clear();
}
this->set_node_pool(pool);
}
//*************************************************************************
//*************************************************************************
etl::ipool& get_pool() const
{
return *this->p_node_pool;
}
};
//*************************************************************************
//*************************************************************************
template <typename T>
bool operator==(const etl::ilist<T>& lhs, const etl::ilist<T>& rhs)
{
return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin());
}
//*************************************************************************
//*************************************************************************
template <typename T>
bool operator!=(const etl::ilist<T>& lhs, const etl::ilist<T>& rhs)
{
return !(lhs == rhs);
}
//*************************************************************************
//*************************************************************************
template <typename T>
bool operator<(const etl::ilist<T>& lhs, const etl::ilist<T>& rhs)
{
return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
//*************************************************************************
//*************************************************************************
template <typename T>
bool operator>(const etl::ilist<T>& lhs, const etl::ilist<T>& rhs)
{
return (rhs < lhs);
}
//*************************************************************************
//*************************************************************************
template <typename T>
bool operator<=(const etl::ilist<T>& lhs, const etl::ilist<T>& rhs)
{
return !(lhs > rhs);
}
//*************************************************************************
//*************************************************************************
template <typename T>
bool operator>=(const etl::ilist<T>& lhs, const etl::ilist<T>& rhs)
{
return !(lhs < rhs);
}
} // namespace etl
#include "private/minmax_pop.h"
#endif
algorithm.h
etl::ilist::const_iterator
const_iterator
Definition list.h:562
etl::ilist::iterator
iterator.
Definition list.h:475
etl::list_ext
Template deduction guides.
Definition list.h:2233
etl::list_ext::list_ext
list_ext(const list_ext &other, etl::ipool &node_pool)
Copy constructor. Explicit pool.
Definition list.h:2302
etl::list_ext::list_ext
list_ext(size_t initial_size, etl::ipool &node_pool)
Construct from size.
Definition list.h:2272
etl::list_ext::set_pool
void set_pool(etl::ipool &pool)
Set the pool instance.
Definition list.h:2380
etl::list_ext::list_ext
list_ext(size_t initial_size, const T &value, etl::ipool &node_pool)
Construct from size and value.
Definition list.h:2281
etl::list_ext::list_ext
list_ext(TIterator first, TIterator last, etl::ipool &node_pool, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Construct from range.
Definition list.h:2335
etl::list_ext::list_ext
list_ext()
Default constructor.
Definition list.h:2248
etl::list_ext::get_pool
etl::ipool & get_pool() const
Get the pool instance.
Definition list.h:2394
etl::list_ext::operator=
list_ext & operator=(const list_ext &rhs)
Assignment operator.
Definition list.h:2355
etl::list_ext::list_ext
list_ext(etl::ipool &node_pool)
Default constructor.
Definition list.h:2256
etl::list_ext::~list_ext
~list_ext()
Destructor.
Definition list.h:2264
etl::list_ext::list_ext
list_ext(const list_ext &other)
Copy constructor. Implicit pool.
Definition list.h:2290
etl::list
A templated list implementation that uses a fixed size buffer.
Definition list.h:2066
etl::list::~list
~list()
Destructor.
Definition list.h:2096
etl::list::list
list(const list &other)
Copy constructor.
Definition list.h:2122
etl::list::list
list(size_t initial_size, const T &value)
Construct from size and value.
Definition list.h:2113
etl::list::list
list(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Construct from range.
Definition list.h:2158
etl::list::operator=
list & operator=(const list &rhs)
Assignment operator.
Definition list.h:2178
etl::list::list
list(size_t initial_size)
Construct from size.
Definition list.h:2104
etl::list::list
list()
Default constructor.
Definition list.h:2088
debug_count.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::const_iterator
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
etl::data_node_t
etl::ilist::ilist
ilist(etl::ipool &node_pool, size_t max_size_, bool pool_is_shared_)
Constructor.
Definition list.h:1834
etl::ilist::rend
const_reverse_iterator rend() const
Gets the reverse end of the list.
Definition list.h:734
etl::ilist::clear
void clear()
Clears the list.
Definition list.h:1323
etl::ilist::cbegin
const_iterator cbegin() const
Gets the beginning of the list.
Definition list.h:694
etl::ilist::end
iterator end()
Gets the end of the list.
Definition list.h:678
etl::ilist::push_back
void push_back(const T &value)
Pushes a value to the back of the list.
Definition list.h:984
etl::ilist::emplace
iterator emplace(const_iterator position)
Emplaces a value to the list at the specified position.
Definition list.h:1148
etl::ilist::ilist
ilist(bool pool_is_shared_)
Constructor.
Definition list.h:1826
etl::ilist::back
reference back()
Definition list.h:782
etl::list_base::size_type
size_t size_type
The type used for determining the size of list.
Definition list.h:154
etl::list_base::reverse
void reverse()
Reverses the list.
Definition list.h:195
etl::ilist::crend
const_reverse_iterator crend() const
Gets the reverse end of the list.
Definition list.h:750
etl::ilist::emplace_front
reference emplace_front(const T1 &value1)
Emplaces a value to the front of the list.
Definition list.h:905
etl::ilist::splice
void splice(iterator to, ilist &other, iterator from)
Splices an element from another list to this.
Definition list.h:1443
etl::list_base::size
size_type size() const
Gets the size of the list.
Definition list.h:237
etl::ilist::sort
void sort(TCompare compare)
Definition list.h:1676
etl::list_base::available
size_type available() const
Definition list.h:281
etl::ilist::splice
void splice(iterator to, ilist &other, iterator first, iterator last)
Splices a range of elements from another list to this.
Definition list.h:1481
etl::list_base::join
void join(node_t &left, node_t &right)
Join two nodes.
Definition list.h:342
etl::ilist::insert
void insert(const_iterator position, size_t n, const_reference value)
Inserts 'n' copies of a value to the list at the specified position.
Definition list.h:1221
etl::ilist::unique
void unique(TIsEqual isEqual)
Definition list.h:1383
etl::ilist::insert
void insert(const_iterator position, TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Inserts a range of values to the list at the specified position.
Definition list.h:1236
etl::ilist::rbegin
const_reverse_iterator rbegin() const
Gets the reverse beginning of the list.
Definition list.h:718
etl::list_base::list_base
list_base(bool pool_is_shared_)
The constructor that is called from derived classes.
Definition list.h:351
etl::list_base::p_node_pool
etl::ipool * p_node_pool
The pool of data nodes used in the list.
Definition list.h:392
etl::list_base::max_size
size_type max_size() const
Gets the maximum possible size of the list.
Definition list.h:221
etl::ilist::resize
void resize(size_t n)
Resizes the list.
Definition list.h:1289
etl::list_base::list_base
list_base(etl::ipool &node_pool_, size_type max_size_, bool pool_is_shared_)
The constructor that is called from derived classes.
Definition list.h:362
etl::list_base::full
bool full() const
Checks to see if the list is full.
Definition list.h:271
etl::ilist::rend
reverse_iterator rend()
Gets the reverse end of the list.
Definition list.h:726
etl::ilist::rbegin
reverse_iterator rbegin()
Gets the reverse beginning of the list.
Definition list.h:710
etl::ilist::emplace_front
reference emplace_front()
Emplaces a value to the front of the list.
Definition list.h:888
etl::ilist::operator=
ilist & operator=(const ilist &rhs)
Assignment operator.
Definition list.h:1787
etl::ilist::insert
iterator insert(const_iterator position, const_reference value)
Inserts a value to the list at the specified position.
Definition list.h:1105
etl::list_base::MAX_SIZE
size_type MAX_SIZE
The maximum size of the list.
Definition list.h:394
etl::list_base::terminal_node
node_t terminal_node
The node that acts as the list start and end.
Definition list.h:393
etl::ilist::push_front
void push_front(const T &value)
Pushes a value to the front of the list.
Definition list.h:848
etl::ilist::initialise
void initialise()
Initialise the list.
Definition list.h:1842
etl::list_base::pool_is_shared
bool pool_is_shared
If true then the pool is shared between lists.
Definition list.h:395
etl::ilist::splice
void splice(iterator to, ilist &other)
Splices from another list to this.
Definition list.h:1411
etl::ilist::end
const_iterator end() const
Gets the end of the list.
Definition list.h:686
etl::list_base::ETL_DECLARE_DEBUG_COUNT
ETL_DECLARE_DEBUG_COUNT
Internal debugging.
Definition list.h:396
etl::ilist::front
reference front()
Definition list.h:760
etl::ilist::pop_front
void pop_front()
Removes a value from the front of the list.
Definition list.h:973
etl::ilist::begin
const_iterator begin() const
Gets the beginning of the list.
Definition list.h:670
etl::ilist::merge
void merge(ilist &other)
Merge another list into this one. Both lists should be sorted.
Definition list.h:1526
etl::list_base::is_trivial_list
bool is_trivial_list() const
Is the list a trivial length?
Definition list.h:292
etl::ilist::assign
void assign(size_t n, const T &value)
Assigns 'n' copies of a value to the list.
Definition list.h:828
etl::ilist::erase
iterator erase(const_iterator first, const_iterator last)
Erases a range of elements.
Definition list.h:1263
etl::ilist::emplace_front
reference emplace_front(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Emplaces a value to the front of the list.
Definition list.h:956
etl::list_base::set_node_pool
void set_node_pool(etl::ipool &node_pool_)
Set the node pool instance.
Definition list.h:373
etl::ilist::emplace_front
reference emplace_front(const T1 &value1, const T2 &value2, const T3 &value3)
Emplaces a value to the front of the list.
Definition list.h:939
etl::ilist::merge
void merge(ilist &other, TCompare compare)
Merge another list into this one. Both lists should be sorted.
Definition list.h:1535
etl::ilist::resize
void resize(size_t n, const_reference value)
Resizes the list.
Definition list.h:1297
etl::list_base::capacity
size_type capacity() const
Gets the maximum possible size of the list.
Definition list.h:229
etl::ilist::emplace_back
reference emplace_back()
Emplaces a value to the back of the list.
Definition list.h:1021
etl::list_base::empty
bool empty() const
Checks to see if the list is empty.
Definition list.h:263
etl::list_base::get_node_pool
etl::ipool * get_node_pool()
Get the node pool instance.
Definition list.h:382
etl::ilist::begin
iterator begin()
Gets the beginning of the list.
Definition list.h:662
etl::ilist::sort
void sort()
Definition list.h:1645
etl::ilist::back
const_reference back() const
Definition list.h:793
etl::ilist::unique
void unique()
Definition list.h:1373
etl::ilist::front
const_reference front() const
Definition list.h:771
etl::list_base::get_head
node_t & get_head()
Get the head node.
Definition list.h:300
etl::list_base::get_head
const node_t & get_head() const
Get the head node.
Definition list.h:308
etl::list_base::insert_node
void insert_node(node_t &position, node_t &node)
Insert a node before 'position'.
Definition list.h:332
etl::list_base::get_tail
const node_t & get_tail() const
Get the tail node.
Definition list.h:324
etl::ilist::cend
const_iterator cend() const
Gets the end of the list.
Definition list.h:702
etl::ilist::crbegin
const_reverse_iterator crbegin() const
Gets the reverse beginning of the list.
Definition list.h:742
etl::list_base::~list_base
~list_base()
Destructor.
Definition list.h:390
etl::ilist::remove_if
void remove_if(TPredicate predicate)
Removes according to a predicate.
Definition list.h:1352
etl::ilist::assign
void assign(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Definition list.h:806
etl::list_base::get_tail
node_t & get_tail()
Get the tail node.
Definition list.h:316
etl::ilist::erase
iterator erase(const_iterator position)
Erases the value at the specified position.
Definition list.h:1251
etl::list_base::has_shared_pool
bool has_shared_pool() const
true if the list has a shared pool.
Definition list.h:187
etl::ilist::pop_back
void pop_back()
Removes a value from the back of the list.
Definition list.h:1094
etl::ilist::emplace_front
reference emplace_front(const T1 &value1, const T2 &value2)
Emplaces a value to the front of the list.
Definition list.h:922
etl::ilist
Definition list.h:405
etl::list_base
Definition list.h:151
etl::list_empty
Definition list.h:95
etl::list_full
Definition list.h:81
etl::list_iterator
Definition list.h:109
etl::list_no_pool
Definition list.h:137
etl::list_unsorted
Definition list.h:123
etl::ipool::allocate
T * allocate()
Definition ipool.h:334
etl::ipool
Definition ipool.h:110
etl::pool
Definition pool.h:54
initializer_list.h
iterator.h
memory.h
minmax_pop.h
minmax_push.h
etl
Definition absolute.h:40
etl::swap
ETL_CONSTEXPR14 void swap(etl::typed_storage_ext< T > &lhs, etl::typed_storage_ext< T > &rhs) ETL_NOEXCEPT
Swap two etl::typed_storage_ext.
Definition alignment.h:856
etl::operator==
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1078
etl::operator>
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1130
etl::operator>=
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1144
etl::operator!=
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1090
etl::operator<
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1103
etl::operator<=
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1117
nullptr.h
parameter_type.h
placement_new.h
platform.h
pool.h
etl::compare
Definition compare.h:51
etl::equal_to
Definition functional.h:305
etl::ilist::data_node_t
The data node element in the list.
Definition list.h:426
etl::reference
etl::iterator
iterator
Definition iterator.h:482
etl::less
Definition functional.h:201
etl::list_base::node_t
The node element in the list.
Definition list.h:160
etl::list_base::node_t::reverse
void reverse()
Reverses the previous & next pointers.
Definition list.h:173
etl::list_base::node_t::node_t
node_t()
Constructor.
Definition list.h:164
etl::type
etl::parameter_type::type
etl::conditional< etl::is_fundamental< T >::value||etl::is_pointer< T >::value, T, constT & >::type type
By default fundamental and pointer types are passed by value.
Definition parameter_type.h:46
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