mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-29 22:08:45 +08:00
Merge remote-tracking branch 'origin/feature/rvalue-references' into development
This commit is contained in:
commit
6e59d815bc
@ -49,7 +49,6 @@ SOFTWARE.
|
||||
#include "debug_count.h"
|
||||
#include "algorithm.h"
|
||||
#include "type_traits.h"
|
||||
#include "parameter_type.h"
|
||||
|
||||
#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL)
|
||||
#include <initializer_list>
|
||||
@ -1948,6 +1947,29 @@ namespace etl
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Move assignment operator.
|
||||
//*************************************************************************
|
||||
ideque& operator =(ideque&& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
clear();
|
||||
iterator itr = rhs.begin();
|
||||
while (itr != rhs.end())
|
||||
{
|
||||
push_back(std::move(*itr));
|
||||
++itr;
|
||||
}
|
||||
|
||||
rhs.initialise();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ETL_IDEQUE_REPAIR_ENABLE
|
||||
//*************************************************************************
|
||||
/// Fix the internal pointers after a low level memory copy.
|
||||
|
||||
@ -46,8 +46,8 @@ SOFTWARE.
|
||||
#include "debug_count.h"
|
||||
#include "nullptr.h"
|
||||
#include "type_traits.h"
|
||||
#include "parameter_type.h"
|
||||
#include "algorithm.h"
|
||||
#include "memory.h"
|
||||
|
||||
#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL)
|
||||
#include <initializer_list>
|
||||
@ -418,6 +418,7 @@ namespace etl
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T&& rvalue_reference;
|
||||
typedef size_t size_type;
|
||||
|
||||
protected:
|
||||
@ -429,7 +430,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
struct data_node_t : public node_t
|
||||
{
|
||||
explicit data_node_t(parameter_t value_)
|
||||
explicit data_node_t(const T& value_)
|
||||
: value(value_)
|
||||
{
|
||||
}
|
||||
@ -823,7 +824,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Assigns 'n' copies of a value to the list.
|
||||
//*************************************************************************
|
||||
void assign(size_t n, parameter_t value)
|
||||
void assign(size_t n, const T& value)
|
||||
{
|
||||
#if defined(ETL_DEBUG)
|
||||
ETL_ASSERT(n <= available(), ETL_ERROR(list_full));
|
||||
@ -843,7 +844,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Pushes a value to the front of the list.
|
||||
//*************************************************************************
|
||||
void push_front(parameter_t value)
|
||||
void push_front(const T& value)
|
||||
{
|
||||
#if defined(ETL_CHECK_PUSH_POP)
|
||||
ETL_ASSERT(!full(), ETL_ERROR(list_full));
|
||||
@ -851,6 +852,19 @@ namespace etl
|
||||
insert_node(get_head(), allocate_data_node(value));
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Pushes a value to the front of the list.
|
||||
//*************************************************************************
|
||||
void push_front(rvalue_reference value)
|
||||
{
|
||||
#if defined(ETL_CHECK_PUSH_POP)
|
||||
ETL_ASSERT(!full(), ETL_ERROR(list_full));
|
||||
#endif
|
||||
insert_node(get_head(), allocate_data_node(std::move(value)));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL)
|
||||
//*************************************************************************
|
||||
/// Emplaces a value to the front of the list.
|
||||
@ -953,7 +967,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Pushes a value to the back of the list.
|
||||
//*************************************************************************
|
||||
void push_back(parameter_t value)
|
||||
void push_back(const T& value)
|
||||
{
|
||||
#if defined(ETL_CHECK_PUSH_POP)
|
||||
ETL_ASSERT(!full(), ETL_ERROR(list_full));
|
||||
@ -961,6 +975,19 @@ namespace etl
|
||||
insert_node(terminal_node, allocate_data_node(value));
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Pushes a value to the back of the list.
|
||||
//*************************************************************************
|
||||
void push_back(rvalue_reference value)
|
||||
{
|
||||
#if defined(ETL_CHECK_PUSH_POP)
|
||||
ETL_ASSERT(!full(), ETL_ERROR(list_full));
|
||||
#endif
|
||||
insert_node(terminal_node, allocate_data_node(std::move(value)));
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Emplaces a value to the back of the list.
|
||||
//*************************************************************************
|
||||
@ -1051,7 +1078,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Inserts a value to the list at the specified position.
|
||||
//*************************************************************************
|
||||
iterator insert(iterator position, const value_type& value)
|
||||
iterator insert(iterator position, const_reference value)
|
||||
{
|
||||
ETL_ASSERT(!full(), ETL_ERROR(list_full));
|
||||
|
||||
@ -1061,6 +1088,21 @@ namespace etl
|
||||
return iterator(data_node);
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Inserts a value to the list at the specified position.
|
||||
//*************************************************************************
|
||||
iterator insert(iterator position, rvalue_reference value)
|
||||
{
|
||||
ETL_ASSERT(!full(), ETL_ERROR(list_full));
|
||||
|
||||
data_node_t& data_node = allocate_data_node(std::move(value));
|
||||
insert_node(*position.p_node, data_node);
|
||||
|
||||
return iterator(data_node);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Emplaces a value to the list at the specified position.
|
||||
//*************************************************************************
|
||||
@ -1139,7 +1181,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Inserts 'n' copies of a value to the list at the specified position.
|
||||
//*************************************************************************
|
||||
void insert(iterator position, size_t n, const value_type& value)
|
||||
void insert(iterator position, size_t n, const_reference value)
|
||||
{
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
@ -1209,7 +1251,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Resizes the list.
|
||||
//*************************************************************************
|
||||
void resize(size_t n, parameter_t value)
|
||||
void resize(size_t n, const_reference value)
|
||||
{
|
||||
ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(list_full));
|
||||
|
||||
@ -1238,7 +1280,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
// Removes the values specified.
|
||||
//*************************************************************************
|
||||
void remove(const value_type& value)
|
||||
void remove(const_reference value)
|
||||
{
|
||||
iterator iValue = begin();
|
||||
|
||||
@ -1327,6 +1369,25 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Splices from another list to this.
|
||||
//*************************************************************************
|
||||
void splice(iterator to, ilist&& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
ilist::iterator itr = other.begin();
|
||||
while (itr != other.end())
|
||||
{
|
||||
to = insert(to, std::move(*itr++));
|
||||
}
|
||||
|
||||
other.erase(other.begin(), other.end());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Splices an element from another list to this.
|
||||
//*************************************************************************
|
||||
@ -1345,6 +1406,26 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Splices an element from another list to this.
|
||||
//*************************************************************************
|
||||
void splice(iterator to, ilist&& other, iterator from)
|
||||
{
|
||||
if (&other == this)
|
||||
{
|
||||
// Internal move.
|
||||
move(to, from);
|
||||
}
|
||||
else
|
||||
{
|
||||
// From another list.
|
||||
insert(to, std::move(*from));
|
||||
other.erase(from);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Splices a range of elements from another list to this.
|
||||
//*************************************************************************
|
||||
@ -1363,6 +1444,32 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Splices a range of elements from another list to this.
|
||||
//*************************************************************************
|
||||
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, std::move(*itr++));
|
||||
++to;
|
||||
}
|
||||
|
||||
other.erase(first, last);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Merge another list into this one. Both lists should be sorted.
|
||||
//*************************************************************************
|
||||
@ -1419,6 +1526,67 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Merge another list into this one. Both lists should be sorted.
|
||||
//*************************************************************************
|
||||
void merge(ilist&& other)
|
||||
{
|
||||
merge(std::move(other), std::less<value_type>());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Merge another list into this one. Both lists should be sorted.
|
||||
//*************************************************************************
|
||||
template <typename TCompare>
|
||||
void merge(ilist&& other, TCompare compare)
|
||||
{
|
||||
if (!other.empty())
|
||||
{
|
||||
#if defined(ETL_DEBUG)
|
||||
ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(list_unsorted));
|
||||
ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(list_unsorted));
|
||||
#endif
|
||||
|
||||
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, std::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, std::move(*other_begin++));
|
||||
}
|
||||
}
|
||||
|
||||
other.clear();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Sort using in-place merge sort algorithm.
|
||||
/// Uses 'less-than operator as the predicate.
|
||||
@ -1554,6 +1722,30 @@ namespace etl
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Assignment operator.
|
||||
//*************************************************************************
|
||||
ilist& operator = (ilist&& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
this->initialise();
|
||||
|
||||
iterator itr = rhs.begin();
|
||||
while (itr != rhs.end())
|
||||
{
|
||||
push_back(std::move(*itr));
|
||||
++itr;
|
||||
}
|
||||
|
||||
rhs.initialise();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
//*************************************************************************
|
||||
@ -1675,7 +1867,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Allocate a data_node_t.
|
||||
//*************************************************************************
|
||||
data_node_t& allocate_data_node(parameter_t value)
|
||||
data_node_t& allocate_data_node(const_reference value)
|
||||
{
|
||||
ETL_ASSERT(p_node_pool != nullptr, ETL_ERROR(list_no_pool));
|
||||
|
||||
@ -1686,6 +1878,22 @@ namespace etl
|
||||
return *p_data_node;
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Allocate a data_node_t.
|
||||
//*************************************************************************
|
||||
data_node_t& allocate_data_node(rvalue_reference value)
|
||||
{
|
||||
ETL_ASSERT(p_node_pool != nullptr, ETL_ERROR(list_no_pool));
|
||||
|
||||
data_node_t* p_data_node = p_node_pool->allocate<data_node_t>();
|
||||
::new (&(p_data_node->value)) T(std::move(value));
|
||||
ETL_INCREMENT_DEBUG_COUNT
|
||||
|
||||
return *p_data_node;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Destroy a data_node_t.
|
||||
//*************************************************************************
|
||||
@ -1715,7 +1923,6 @@ namespace etl
|
||||
|
||||
//*************************************************************************
|
||||
/// A templated list implementation that uses a fixed size buffer.
|
||||
///\note 'merge' and 'splice' and are not supported.
|
||||
//*************************************************************************
|
||||
template <typename T, const size_t MAX_SIZE_>
|
||||
class list : public etl::ilist<T>
|
||||
@ -1731,6 +1938,7 @@ namespace etl
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T&& rvalue_reference;
|
||||
typedef size_t size_type;
|
||||
|
||||
//*************************************************************************
|
||||
@ -1761,7 +1969,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Construct from size and value.
|
||||
//*************************************************************************
|
||||
list(size_t initial_size, typename ilist<T>::parameter_t value)
|
||||
list(size_t initial_size, const T& value)
|
||||
: etl::ilist<T>(node_pool, MAX_SIZE, false)
|
||||
{
|
||||
this->assign(initial_size, value);
|
||||
@ -1779,6 +1987,29 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Move constructor.
|
||||
//*************************************************************************
|
||||
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(std::move(*itr));
|
||||
++itr;
|
||||
}
|
||||
|
||||
other.initialise();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Construct from range.
|
||||
//*************************************************************************
|
||||
@ -1813,6 +2044,30 @@ namespace etl
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Assignment operator.
|
||||
//*************************************************************************
|
||||
list& operator = (list&& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
this->initialise();
|
||||
|
||||
typename etl::ilist<T>::iterator itr = rhs.begin();
|
||||
while (itr != rhs.end())
|
||||
{
|
||||
this->push_back(std::move(*itr));
|
||||
++itr;
|
||||
}
|
||||
|
||||
rhs.initialise();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
/// The pool of nodes used in the list.
|
||||
@ -1821,7 +2076,6 @@ namespace etl
|
||||
|
||||
//*************************************************************************
|
||||
/// A templated list implementation that uses a fixed size buffer.
|
||||
///\note 'merge' and 'splice' and are not supported.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
class list<T, 0> : public etl::ilist<T>
|
||||
@ -1873,7 +2127,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
/// Construct from size and value.
|
||||
//*************************************************************************
|
||||
list(size_t initial_size, typename ilist<T>::parameter_t value, etl::ipool& node_pool)
|
||||
list(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);
|
||||
@ -1891,6 +2145,29 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Move constructor.
|
||||
//*************************************************************************
|
||||
list(list&& other)
|
||||
: etl::ilist<T>(*other.p_node_pool, other.p_node_pool->max_size(), true)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
this->initialise();
|
||||
|
||||
typename etl::ilist<T>::iterator itr = other.begin();
|
||||
while (itr != other.end())
|
||||
{
|
||||
this->push_back(std::move(*itr));
|
||||
++itr;
|
||||
}
|
||||
|
||||
other.initialise();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Construct from range.
|
||||
//*************************************************************************
|
||||
@ -1925,6 +2202,30 @@ namespace etl
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Assignment operator.
|
||||
//*************************************************************************
|
||||
list& operator = (list&& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
this->initialise();
|
||||
|
||||
typename etl::ilist<T>::iterator itr = rhs.begin();
|
||||
while (itr != rhs.end())
|
||||
{
|
||||
this->push_back(std::move(*itr));
|
||||
++itr;
|
||||
}
|
||||
|
||||
rhs.initialise();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Set the pool instance.
|
||||
//*************************************************************************
|
||||
|
||||
@ -417,6 +417,18 @@ namespace etl
|
||||
::new (p) T(value);
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*****************************************************************************
|
||||
/// Copy construct an item at address p.
|
||||
///\ingroup memory
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
void create_copy_at(T* p, T&& value)
|
||||
{
|
||||
::new (p) T(std::move(value));
|
||||
}
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
/// Copy construct an item at address p.
|
||||
///\ingroup memory
|
||||
@ -462,6 +474,19 @@ namespace etl
|
||||
return *reinterpret_cast<T*>(p);
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*****************************************************************************
|
||||
/// Construct an item at address p.
|
||||
///\ingroup memory
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
T& make_copy_at(T* p, T&& other)
|
||||
{
|
||||
::new (p) T(std::move(other));
|
||||
return *reinterpret_cast<T*>(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
/// Construct an item at address p.
|
||||
///\ingroup memory
|
||||
@ -485,6 +510,17 @@ namespace etl
|
||||
return *reinterpret_cast<T*>(p);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Construct an item at address p.
|
||||
///\ingroup memory
|
||||
//*****************************************************************************
|
||||
template <typename T, typename TParameter>
|
||||
T& make_value_at(T* p, TParameter&& value)
|
||||
{
|
||||
::new (p) T(std::move(value));
|
||||
return *reinterpret_cast<T*>(p);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Construct an item at address p.
|
||||
///\ingroup memory
|
||||
|
||||
@ -326,6 +326,13 @@ namespace etl
|
||||
template <typename T> struct is_trivially_copy_assignable : etl::is_pod<T> {};
|
||||
#endif
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
/// is_rvalue_reference
|
||||
///\ingroup type_traits
|
||||
template <class T> struct is_rvalue_reference : etl::false_type {};
|
||||
template <class T> struct is_rvalue_reference<T&&> : etl::true_type {};
|
||||
#endif
|
||||
|
||||
/// conditional
|
||||
///\ingroup type_traits
|
||||
template <bool B, typename T, typename F> struct conditional { typedef T type; };
|
||||
@ -347,7 +354,7 @@ namespace etl
|
||||
struct conditional_integral_constant<false, T, TRUE_VALUE, FALSE_VALUE>
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Not an integral type");
|
||||
static const T value = FALSE_VALUE;
|
||||
static const T value = FALSE_VALUE;
|
||||
};
|
||||
|
||||
/// make_signed
|
||||
|
||||
@ -40,7 +40,6 @@ SOFTWARE.
|
||||
#include "platform.h"
|
||||
#include "algorithm.h"
|
||||
#include "type_traits.h"
|
||||
#include "parameter_type.h"
|
||||
#include "error_handler.h"
|
||||
#include "memory.h"
|
||||
#include "container.h"
|
||||
@ -86,6 +85,7 @@ namespace etl
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T&& rvalue_reference;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T* iterator;
|
||||
@ -405,7 +405,7 @@ namespace etl
|
||||
/// If asserts or exceptions are enabled, emits vector_full if the vector is already full.
|
||||
///\param value The value to add.
|
||||
//*********************************************************************
|
||||
void push_back(parameter_t value)
|
||||
void push_back(const_reference value)
|
||||
{
|
||||
#if defined(ETL_CHECK_PUSH_POP)
|
||||
ETL_ASSERT(size() != CAPACITY, ETL_ERROR(vector_full));
|
||||
@ -413,6 +413,21 @@ namespace etl
|
||||
create_back(value);
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*********************************************************************
|
||||
/// Inserts a value at the end of the vector.
|
||||
/// If asserts or exceptions are enabled, emits vector_full if the vector is already full.
|
||||
///\param value The value to add.
|
||||
//*********************************************************************
|
||||
void push_back(rvalue_reference value)
|
||||
{
|
||||
#if defined(ETL_CHECK_PUSH_POP)
|
||||
ETL_ASSERT(size() != CAPACITY, ETL_ERROR(vector_full));
|
||||
#endif
|
||||
create_back(std::move(value));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) && !ETL_VECTOR_FORCE_CPP03
|
||||
//*********************************************************************
|
||||
/// Constructs a value at the end of the vector.
|
||||
@ -513,7 +528,7 @@ namespace etl
|
||||
///\param position The position to insert before.
|
||||
///\param value The value to insert.
|
||||
//*********************************************************************
|
||||
iterator insert(iterator position, parameter_t value)
|
||||
iterator insert(iterator position, const_reference value)
|
||||
{
|
||||
ETL_ASSERT(size() + 1 <= CAPACITY, ETL_ERROR(vector_full));
|
||||
|
||||
@ -524,13 +539,39 @@ namespace etl
|
||||
else
|
||||
{
|
||||
create_back(back());
|
||||
std::copy_backward(position, p_end - 1, p_end);
|
||||
std::copy_backward(position, p_end - 2, p_end - 1);
|
||||
*position = value;
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*********************************************************************
|
||||
/// Inserts a value to the vector.
|
||||
/// If asserts or exceptions are enabled, emits vector_full if the vector is already full.
|
||||
///\param position The position to insert before.
|
||||
///\param value The value to insert.
|
||||
//*********************************************************************
|
||||
iterator insert(iterator position, rvalue_reference value)
|
||||
{
|
||||
ETL_ASSERT(size() + 1 <= CAPACITY, ETL_ERROR(vector_full));
|
||||
|
||||
if (position == end())
|
||||
{
|
||||
create_back(std::move(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
create_back(std::move(back()));
|
||||
std::move_backward(position, p_end - 2, p_end - 1);
|
||||
*position = std::move(value);
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Emplaces a value to the vextor at the specified position.
|
||||
//*************************************************************************
|
||||
@ -551,7 +592,7 @@ namespace etl
|
||||
{
|
||||
p = etl::addressof(*position);
|
||||
create_back(back());
|
||||
std::copy_backward(position, p_end - 1, p_end);
|
||||
std::copy_backward(position, p_end - 2, p_end - 1);
|
||||
(*position).~T();
|
||||
}
|
||||
|
||||
@ -576,7 +617,7 @@ namespace etl
|
||||
{
|
||||
p = etl::addressof(*position);
|
||||
create_back(back());
|
||||
std::copy_backward(position, p_end - 1, p_end);
|
||||
std::copy_backward(position, p_end - 2, p_end - 1);
|
||||
(*position).~T();
|
||||
}
|
||||
|
||||
@ -601,7 +642,7 @@ namespace etl
|
||||
{
|
||||
p = etl::addressof(*position);
|
||||
create_back(back());
|
||||
std::copy_backward(position, p_end - 1, p_end);
|
||||
std::copy_backward(position, p_end - 2, p_end - 1);
|
||||
(*position).~T();
|
||||
}
|
||||
|
||||
@ -626,7 +667,7 @@ namespace etl
|
||||
{
|
||||
p = etl::addressof(*position);
|
||||
create_back(back());
|
||||
std::copy_backward(position, p_end - 1, p_end);
|
||||
std::copy_backward(position, p_end - 2, p_end - 1);
|
||||
(*position).~T();
|
||||
}
|
||||
|
||||
@ -651,7 +692,7 @@ namespace etl
|
||||
{
|
||||
p = etl::addressof(*position);
|
||||
create_back(back());
|
||||
std::copy_backward(position, p_end - 1, p_end);
|
||||
std::copy_backward(position, p_end - 2, p_end - 1);
|
||||
(*position).~T();
|
||||
}
|
||||
|
||||
@ -701,15 +742,15 @@ namespace etl
|
||||
etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old);
|
||||
ETL_ADD_DEBUG_COUNT(construct_old_n)
|
||||
|
||||
// Copy old.
|
||||
etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end);
|
||||
// Copy old.
|
||||
etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end);
|
||||
|
||||
// Construct new.
|
||||
etl::uninitialized_fill_n(p_end, construct_new_n, value);
|
||||
ETL_ADD_DEBUG_COUNT(construct_new_n)
|
||||
|
||||
// Copy new.
|
||||
std::fill_n(p_buffer + insert_begin, copy_new_n, value);
|
||||
// Copy new.
|
||||
std::fill_n(p_buffer + insert_begin, copy_new_n, value);
|
||||
|
||||
p_end += n;
|
||||
}
|
||||
@ -758,15 +799,15 @@ namespace etl
|
||||
etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old);
|
||||
ETL_ADD_DEBUG_COUNT(construct_old_n)
|
||||
|
||||
// Copy old.
|
||||
etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end);
|
||||
// Copy old.
|
||||
etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end);
|
||||
|
||||
// Construct new.
|
||||
etl::uninitialized_copy_n(first + copy_new_n, construct_new_n, p_end);
|
||||
ETL_ADD_DEBUG_COUNT(construct_new_n)
|
||||
|
||||
// Copy new.
|
||||
etl::copy_n(first, copy_new_n, p_buffer + insert_begin);
|
||||
// Copy new.
|
||||
etl::copy_n(first, copy_new_n, p_buffer + insert_begin);
|
||||
|
||||
p_end += count;
|
||||
}
|
||||
@ -806,7 +847,7 @@ namespace etl
|
||||
// Destroy the elements left over at the end.
|
||||
etl::destroy(p_end - n_delete, p_end);
|
||||
ETL_SUBTRACT_DEBUG_COUNT(n_delete)
|
||||
p_end -= n_delete;
|
||||
p_end -= n_delete;
|
||||
}
|
||||
|
||||
return first;
|
||||
@ -825,6 +866,29 @@ namespace etl
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Move assignment operator.
|
||||
//*************************************************************************
|
||||
ivector& operator = (ivector&& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
clear();
|
||||
iterator itr = rhs.begin();
|
||||
while (itr != rhs.end())
|
||||
{
|
||||
push_back(std::move(*itr));
|
||||
++itr;
|
||||
}
|
||||
|
||||
rhs.initialise();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the current size of the vector.
|
||||
///\return The current size of the vector.
|
||||
@ -888,7 +952,7 @@ namespace etl
|
||||
etl::destroy(p_buffer, p_end);
|
||||
ETL_SUBTRACT_DEBUG_COUNT(int32_t(std::distance(p_buffer, p_end)))
|
||||
|
||||
p_end = p_buffer;
|
||||
p_end = p_buffer;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -898,7 +962,7 @@ namespace etl
|
||||
{
|
||||
uintptr_t length = p_end - p_buffer;
|
||||
p_buffer = p_buffer_;
|
||||
p_end = p_buffer_ + length;
|
||||
p_end = p_buffer_ + length;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -920,7 +984,7 @@ namespace etl
|
||||
//*********************************************************************
|
||||
/// Create a new element with a value at the back
|
||||
//*********************************************************************
|
||||
inline void create_back(parameter_t value)
|
||||
inline void create_back(const_reference value)
|
||||
{
|
||||
etl::create_copy_at(p_end, value);
|
||||
ETL_INCREMENT_DEBUG_COUNT
|
||||
@ -928,6 +992,19 @@ namespace etl
|
||||
++p_end;
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*********************************************************************
|
||||
/// Create a new element with a value at the back
|
||||
//*********************************************************************
|
||||
inline void create_back(rvalue_reference value)
|
||||
{
|
||||
etl::create_copy_at(p_end, std::move(value));
|
||||
ETL_INCREMENT_DEBUG_COUNT
|
||||
|
||||
++p_end;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Destroy an element at the back.
|
||||
//*********************************************************************
|
||||
@ -1035,7 +1112,12 @@ namespace etl
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
}
|
||||
|
||||
#include "private/ivectorpointer.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// A vector implementation that uses a fixed size buffer.
|
||||
///\tparam T The element type.
|
||||
@ -1114,14 +1196,6 @@ namespace etl
|
||||
this->assign(other.begin(), other.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Destructor.
|
||||
//*************************************************************************
|
||||
~vector()
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Assignment operator.
|
||||
//*************************************************************************
|
||||
@ -1135,6 +1209,58 @@ namespace etl
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//*************************************************************************
|
||||
/// Move constructor.
|
||||
//*************************************************************************
|
||||
vector(vector&& other)
|
||||
: etl::ivector<T>(reinterpret_cast<T*>(&buffer), MAX_SIZE)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
this->initialise();
|
||||
|
||||
typename etl::ivector<T>::iterator itr = other.begin();
|
||||
while (itr != other.end())
|
||||
{
|
||||
this->push_back(std::move(*itr));
|
||||
++itr;
|
||||
}
|
||||
|
||||
other.initialise();
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Move assignment operator.
|
||||
//*************************************************************************
|
||||
vector& operator = (vector&& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
this->clear();
|
||||
typename etl::ivector<T>::iterator itr = rhs.begin();
|
||||
while (itr != rhs.end())
|
||||
{
|
||||
this->push_back(std::move(*itr));
|
||||
++itr;
|
||||
}
|
||||
|
||||
rhs.initialise();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Destructor.
|
||||
//*************************************************************************
|
||||
~vector()
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Fix the internal pointers after a low level memory copy.
|
||||
//*************************************************************************
|
||||
@ -1230,7 +1356,10 @@ namespace etl
|
||||
vector(const vector& other)
|
||||
: etl::ivector<T*>(reinterpret_cast<T**>(&buffer), MAX_SIZE)
|
||||
{
|
||||
this->assign(other.begin(), other.end());
|
||||
if (this != &other)
|
||||
{
|
||||
this->assign(other.begin(), other.end());
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -1260,8 +1389,6 @@ namespace etl
|
||||
};
|
||||
}
|
||||
|
||||
#include "private/ivectorpointer.h"
|
||||
|
||||
#ifdef ETL_COMPILER_GCC
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
85
test/data.h
85
test/data.h
@ -152,4 +152,89 @@ std::ostream& operator << (std::ostream& s, const TestDataNDC<T>& rhs)
|
||||
return s;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Movable.
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
class TestDataM : public etl::instance_count<TestDataM<T>>
|
||||
{
|
||||
public:
|
||||
|
||||
explicit TestDataM(const T& value_)
|
||||
: value(value_)
|
||||
, valid(true)
|
||||
{
|
||||
}
|
||||
|
||||
TestDataM(TestDataM&& other)
|
||||
: value(other.value)
|
||||
, valid(true)
|
||||
{
|
||||
other.value = T();
|
||||
other.valid = false;
|
||||
}
|
||||
|
||||
TestDataM& operator =(TestDataM&& other)
|
||||
{
|
||||
value = other.value;
|
||||
valid = true;
|
||||
|
||||
other.value = T();
|
||||
other.valid = false;
|
||||
}
|
||||
|
||||
bool operator < (const TestDataM& other) const
|
||||
{
|
||||
return value < other.value;
|
||||
}
|
||||
|
||||
bool operator > (const TestDataM& other) const
|
||||
{
|
||||
return other.value < value;
|
||||
}
|
||||
|
||||
bool operator <= (const TestDataM& other) const
|
||||
{
|
||||
return !(other.value < value);
|
||||
}
|
||||
|
||||
bool operator >= (const TestDataM& other) const
|
||||
{
|
||||
return !(value < other.value);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return valid;
|
||||
}
|
||||
|
||||
T value;
|
||||
bool valid;
|
||||
|
||||
private:
|
||||
|
||||
TestDataM(const TestDataM& other) = delete;
|
||||
TestDataM& operator =(const TestDataM& other) = delete;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
bool operator == (const TestDataM<T>& lhs, const TestDataM<T>& rhs)
|
||||
{
|
||||
return lhs.value == rhs.value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator != (const TestDataM<T>& lhs, const TestDataM<T>& rhs)
|
||||
{
|
||||
return lhs.value != rhs.value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::ostream& operator << (std::ostream& s, const TestDataM<T>& rhs)
|
||||
{
|
||||
s << rhs.value;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@ -156,6 +156,34 @@ namespace
|
||||
CHECK(std::equal(deque1.begin(), deque1.end(), deque2.begin()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_constructor)
|
||||
{
|
||||
const size_t SIZE = 10U;
|
||||
typedef etl::deque<std::unique_ptr<uint32_t>, SIZE> Data;
|
||||
|
||||
std::unique_ptr<uint32_t> p1(new uint32_t(1U));
|
||||
std::unique_ptr<uint32_t> p2(new uint32_t(2U));
|
||||
std::unique_ptr<uint32_t> p3(new uint32_t(3U));
|
||||
std::unique_ptr<uint32_t> p4(new uint32_t(4U));
|
||||
|
||||
Data deque1;
|
||||
deque1.push_back(std::move(p1));
|
||||
deque1.push_back(std::move(p2));
|
||||
deque1.push_back(std::move(p3));
|
||||
deque1.push_back(std::move(p4));
|
||||
|
||||
Data deque2(std::move(deque1));
|
||||
|
||||
CHECK_EQUAL(0U, deque1.size());
|
||||
CHECK_EQUAL(4U, deque2.size());
|
||||
|
||||
CHECK_EQUAL(1U, *deque2[0]);
|
||||
CHECK_EQUAL(2U, *deque2[1]);
|
||||
CHECK_EQUAL(3U, *deque2[2]);
|
||||
CHECK_EQUAL(4U, *deque2[3]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_assignment)
|
||||
{
|
||||
@ -168,6 +196,35 @@ namespace
|
||||
CHECK(std::equal(deque1.begin(), deque1.end(), deque2.begin()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_assignment)
|
||||
{
|
||||
const size_t SIZE = 10U;
|
||||
typedef etl::deque<std::unique_ptr<uint32_t>, SIZE> Data;
|
||||
|
||||
std::unique_ptr<uint32_t> p1(new uint32_t(1U));
|
||||
std::unique_ptr<uint32_t> p2(new uint32_t(2U));
|
||||
std::unique_ptr<uint32_t> p3(new uint32_t(3U));
|
||||
std::unique_ptr<uint32_t> p4(new uint32_t(4U));
|
||||
|
||||
Data deque1;
|
||||
deque1.push_back(std::move(p1));
|
||||
deque1.push_back(std::move(p2));
|
||||
deque1.push_back(std::move(p3));
|
||||
deque1.push_back(std::move(p4));
|
||||
|
||||
Data deque2;
|
||||
deque2 = std::move(deque1);
|
||||
|
||||
CHECK_EQUAL(0U, deque1.size());
|
||||
CHECK_EQUAL(4U, deque2.size());
|
||||
|
||||
CHECK_EQUAL(1U, *deque2[0]);
|
||||
CHECK_EQUAL(2U, *deque2[1]);
|
||||
CHECK_EQUAL(3U, *deque2[2]);
|
||||
CHECK_EQUAL(4U, *deque2[3]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_assignment_interface)
|
||||
{
|
||||
@ -183,6 +240,40 @@ namespace
|
||||
CHECK(std::equal(deque1.begin(), deque1.end(), deque2.begin()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_assignment_interface)
|
||||
{
|
||||
const size_t SIZE = 10U;
|
||||
typedef etl::deque<std::unique_ptr<uint32_t>, SIZE> Data;
|
||||
typedef etl::ideque<std::unique_ptr<uint32_t>> IData;
|
||||
|
||||
std::unique_ptr<uint32_t> p1(new uint32_t(1U));
|
||||
std::unique_ptr<uint32_t> p2(new uint32_t(2U));
|
||||
std::unique_ptr<uint32_t> p3(new uint32_t(3U));
|
||||
std::unique_ptr<uint32_t> p4(new uint32_t(4U));
|
||||
|
||||
Data deque1;
|
||||
deque1.push_back(std::move(p1));
|
||||
deque1.push_back(std::move(p2));
|
||||
deque1.push_back(std::move(p3));
|
||||
deque1.push_back(std::move(p4));
|
||||
|
||||
Data deque2;
|
||||
|
||||
IData& ideque1 = deque1;
|
||||
IData& ideque2 = deque2;
|
||||
|
||||
ideque2 = std::move(ideque1);
|
||||
|
||||
CHECK_EQUAL(0U, deque1.size());
|
||||
CHECK_EQUAL(4U, deque2.size());
|
||||
|
||||
CHECK_EQUAL(1U, *deque2[0]);
|
||||
CHECK_EQUAL(2U, *deque2[1]);
|
||||
CHECK_EQUAL(3U, *deque2[2]);
|
||||
CHECK_EQUAL(4U, *deque2[3]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_self_assignment)
|
||||
{
|
||||
@ -1693,7 +1784,7 @@ namespace
|
||||
TEST(test_move)
|
||||
{
|
||||
const size_t SIZE = 10U;
|
||||
typedef etl::deque<std::unique_ptr<unsigned>, SIZE> Data;
|
||||
typedef etl::deque<std::unique_ptr<uint32_t>, SIZE> Data;
|
||||
|
||||
Data data1;
|
||||
|
||||
|
||||
@ -38,12 +38,14 @@ SOFTWARE.
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
SUITE(test_list)
|
||||
{
|
||||
typedef TestDataDC<std::string> ItemDC;
|
||||
typedef TestDataNDC<std::string> ItemNDC;
|
||||
typedef TestDataM<uint32_t> ItemM;
|
||||
|
||||
const size_t SIZE = 10;
|
||||
|
||||
@ -54,6 +56,9 @@ namespace
|
||||
|
||||
typedef etl::list<int, SIZE> DataInt;
|
||||
|
||||
typedef etl::list<ItemM, SIZE> DataM;
|
||||
typedef etl::ilist<ItemM> IDataM;
|
||||
|
||||
typedef std::list<ItemNDC> CompareData;
|
||||
typedef std::vector<ItemNDC> InitialData;
|
||||
|
||||
@ -199,6 +204,38 @@ namespace
|
||||
CHECK_EQUAL(compare_data.size() - 2, other_data.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_constructor)
|
||||
{
|
||||
ItemM p1(1U);
|
||||
ItemM p2(2U);
|
||||
ItemM p3(3U);
|
||||
ItemM p4(4U);
|
||||
|
||||
DataM data1;
|
||||
data1.push_back(std::move(p1));
|
||||
data1.push_back(std::move(p2));
|
||||
data1.push_back(std::move(p3));
|
||||
data1.push_back(std::move(p4));
|
||||
|
||||
CHECK(!bool(p1));
|
||||
CHECK(!bool(p2));
|
||||
CHECK(!bool(p3));
|
||||
CHECK(!bool(p4));
|
||||
|
||||
DataM data2(std::move(data1));
|
||||
|
||||
CHECK_EQUAL(0U, data1.size());
|
||||
CHECK_EQUAL(4U, data2.size());
|
||||
|
||||
DataM::const_iterator itr = data2.begin();
|
||||
|
||||
CHECK_EQUAL(1U, (*itr++).value);
|
||||
CHECK_EQUAL(2U, (*itr++).value);
|
||||
CHECK_EQUAL(3U, (*itr++).value);
|
||||
CHECK_EQUAL(4U, (*itr++).value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_iterator)
|
||||
{
|
||||
@ -429,6 +466,35 @@ namespace
|
||||
CHECK(are_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_position_value_move)
|
||||
{
|
||||
ItemM p1(1U);
|
||||
ItemM p2(2U);
|
||||
ItemM p3(3U);
|
||||
ItemM p4(4U);
|
||||
|
||||
DataM data1;
|
||||
data1.insert(data1.begin(), std::move(p1));
|
||||
data1.insert(data1.begin(), std::move(p2));
|
||||
data1.insert(data1.begin(), std::move(p3));
|
||||
data1.insert(data1.begin(), std::move(p4));
|
||||
|
||||
CHECK_EQUAL(4U, data1.size());
|
||||
|
||||
CHECK(!bool(p1));
|
||||
CHECK(!bool(p2));
|
||||
CHECK(!bool(p3));
|
||||
CHECK(!bool(p4));
|
||||
|
||||
DataM::const_iterator itr = data1.begin();
|
||||
|
||||
CHECK_EQUAL(4U, (*itr++).value);
|
||||
CHECK_EQUAL(3U, (*itr++).value);
|
||||
CHECK_EQUAL(2U, (*itr++).value);
|
||||
CHECK_EQUAL(1U, (*itr++).value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_position_value)
|
||||
{
|
||||
@ -554,6 +620,35 @@ namespace
|
||||
CHECK(are_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_push_front_move)
|
||||
{
|
||||
ItemM p1(1U);
|
||||
ItemM p2(2U);
|
||||
ItemM p3(3U);
|
||||
ItemM p4(4U);
|
||||
|
||||
DataM data;
|
||||
data.push_front(std::move(p1));
|
||||
data.push_front(std::move(p2));
|
||||
data.push_front(std::move(p3));
|
||||
data.push_front(std::move(p4));
|
||||
|
||||
CHECK_EQUAL(4U, data.size());
|
||||
|
||||
CHECK(!bool(p1));
|
||||
CHECK(!bool(p2));
|
||||
CHECK(!bool(p3));
|
||||
CHECK(!bool(p4));
|
||||
|
||||
DataM::const_iterator itr = data.begin();
|
||||
|
||||
CHECK_EQUAL(4U, (*itr++).value);
|
||||
CHECK_EQUAL(3U, (*itr++).value);
|
||||
CHECK_EQUAL(2U, (*itr++).value);
|
||||
CHECK_EQUAL(1U, (*itr++).value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_front)
|
||||
{
|
||||
@ -681,6 +776,35 @@ namespace
|
||||
CHECK(are_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_push_back_move)
|
||||
{
|
||||
ItemM p1(1U);
|
||||
ItemM p2(2U);
|
||||
ItemM p3(3U);
|
||||
ItemM p4(4U);
|
||||
|
||||
DataM data;
|
||||
data.push_back(std::move(p1));
|
||||
data.push_back(std::move(p2));
|
||||
data.push_back(std::move(p3));
|
||||
data.push_back(std::move(p4));
|
||||
|
||||
CHECK_EQUAL(4U, data.size());
|
||||
|
||||
CHECK(!bool(p1));
|
||||
CHECK(!bool(p2));
|
||||
CHECK(!bool(p3));
|
||||
CHECK(!bool(p4));
|
||||
|
||||
DataM::const_iterator itr = data.begin();
|
||||
|
||||
CHECK_EQUAL(1U, (*itr++).value);
|
||||
CHECK_EQUAL(2U, (*itr++).value);
|
||||
CHECK_EQUAL(3U, (*itr++).value);
|
||||
CHECK_EQUAL(4U, (*itr++).value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_back)
|
||||
{
|
||||
@ -894,7 +1018,6 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_assignment)
|
||||
{
|
||||
CompareData compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC other_data;
|
||||
|
||||
@ -907,6 +1030,34 @@ namespace
|
||||
CHECK(are_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_assignment)
|
||||
{
|
||||
ItemM p1(1U);
|
||||
ItemM p2(2U);
|
||||
ItemM p3(3U);
|
||||
ItemM p4(4U);
|
||||
|
||||
DataM data1;
|
||||
data1.push_back(std::move(p1));
|
||||
data1.push_back(std::move(p2));
|
||||
data1.push_back(std::move(p3));
|
||||
data1.push_back(std::move(p4));
|
||||
|
||||
DataM data2;
|
||||
data2 = std::move(data1);
|
||||
|
||||
CHECK_EQUAL(0U, data1.size());
|
||||
CHECK_EQUAL(4U, data2.size());
|
||||
|
||||
DataM::const_iterator itr = data2.begin();
|
||||
|
||||
CHECK_EQUAL(1U, (*itr++).value);
|
||||
CHECK_EQUAL(2U, (*itr++).value);
|
||||
CHECK_EQUAL(3U, (*itr++).value);
|
||||
CHECK_EQUAL(4U, (*itr++).value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_assignment_interface)
|
||||
{
|
||||
@ -926,6 +1077,38 @@ namespace
|
||||
CHECK(are_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_assignment_interface)
|
||||
{
|
||||
ItemM p1(1U);
|
||||
ItemM p2(2U);
|
||||
ItemM p3(3U);
|
||||
ItemM p4(4U);
|
||||
|
||||
DataM data1;
|
||||
data1.push_back(std::move(p1));
|
||||
data1.push_back(std::move(p2));
|
||||
data1.push_back(std::move(p3));
|
||||
data1.push_back(std::move(p4));
|
||||
|
||||
DataM data2;
|
||||
|
||||
IDataM& idata1 = data1;
|
||||
IDataM& idata2 = data2;
|
||||
|
||||
idata2 = std::move(idata1);
|
||||
|
||||
CHECK_EQUAL(0U, data1.size());
|
||||
CHECK_EQUAL(4U, data2.size());
|
||||
|
||||
DataM::const_iterator itr = data2.begin();
|
||||
|
||||
CHECK_EQUAL(1U, (*itr++).value);
|
||||
CHECK_EQUAL(2U, (*itr++).value);
|
||||
CHECK_EQUAL(3U, (*itr++).value);
|
||||
CHECK_EQUAL(4U, (*itr++).value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_self_assignment)
|
||||
{
|
||||
@ -1565,6 +1748,7 @@ namespace
|
||||
DataNDC2 data0(merge_data0.begin(), merge_data0.end());
|
||||
DataNDC2 data1(merge_data1.begin(), merge_data1.end());
|
||||
|
||||
|
||||
CompareData compare0(merge_data0.begin(), merge_data0.end());
|
||||
CompareData compare1(merge_data1.begin(), merge_data1.end());
|
||||
|
||||
@ -1644,8 +1828,6 @@ namespace
|
||||
data0.reverse();
|
||||
data1.reverse();
|
||||
|
||||
|
||||
|
||||
CompareData compare0(merge_data0.begin(), merge_data0.end());
|
||||
CompareData compare1(merge_data1.begin(), merge_data1.end());
|
||||
|
||||
@ -1670,5 +1852,146 @@ namespace
|
||||
|
||||
CHECK_THROW(data0.merge(data1), etl::list_unsorted);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_merge_move)
|
||||
{
|
||||
ItemM p1(1U);
|
||||
ItemM p2(2U);
|
||||
ItemM p3(3U);
|
||||
ItemM p4(4U);
|
||||
|
||||
ItemM p5(5U);
|
||||
ItemM p6(6U);
|
||||
ItemM p7(7U);
|
||||
ItemM p8(8U);
|
||||
|
||||
DataM data1;
|
||||
data1.push_back(std::move(p1));
|
||||
data1.push_back(std::move(p2));
|
||||
data1.push_back(std::move(p3));
|
||||
data1.push_back(std::move(p4));
|
||||
|
||||
DataM data2;
|
||||
data2.push_back(std::move(p5));
|
||||
data2.push_back(std::move(p6));
|
||||
data2.push_back(std::move(p7));
|
||||
data2.push_back(std::move(p8));
|
||||
|
||||
data1.merge(std::move(data2));
|
||||
|
||||
CHECK_EQUAL(8U, data1.size());
|
||||
CHECK_EQUAL(0U, data2.size());
|
||||
|
||||
DataM::const_iterator itr = data1.begin();
|
||||
|
||||
CHECK_EQUAL(1U, (*itr++).value);
|
||||
CHECK_EQUAL(2U, (*itr++).value);
|
||||
CHECK_EQUAL(3U, (*itr++).value);
|
||||
CHECK_EQUAL(4U, (*itr++).value);
|
||||
CHECK_EQUAL(5U, (*itr++).value);
|
||||
CHECK_EQUAL(6U, (*itr++).value);
|
||||
CHECK_EQUAL(7U, (*itr++).value);
|
||||
CHECK_EQUAL(8U, (*itr++).value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_splice_move_range_same)
|
||||
{
|
||||
ItemM p1(1U);
|
||||
ItemM p2(2U);
|
||||
ItemM p3(3U);
|
||||
ItemM p4(4U);
|
||||
ItemM p5(5U);
|
||||
ItemM p6(6U);
|
||||
ItemM p7(7U);
|
||||
ItemM p8(8U);
|
||||
|
||||
DataM data;
|
||||
data.push_back(std::move(p1));
|
||||
data.push_back(std::move(p2));
|
||||
data.push_back(std::move(p3));
|
||||
data.push_back(std::move(p4));
|
||||
data.push_back(std::move(p5));
|
||||
data.push_back(std::move(p6));
|
||||
data.push_back(std::move(p7));
|
||||
data.push_back(std::move(p8));
|
||||
|
||||
DataM::iterator begin;
|
||||
DataM::iterator end;
|
||||
DataM::iterator to;
|
||||
|
||||
// Move nearby.
|
||||
begin = data.begin();
|
||||
std::advance(begin, 4);
|
||||
end = begin;
|
||||
std::advance(end, 2);
|
||||
to = data.begin();
|
||||
std::advance(to, 2);
|
||||
data.splice(to, std::move(data), begin, end);
|
||||
|
||||
CHECK_EQUAL(8U, data.size());
|
||||
|
||||
DataM::const_iterator itr = data.begin();
|
||||
|
||||
CHECK_EQUAL(1U, (*itr++).value);
|
||||
CHECK_EQUAL(2U, (*itr++).value);
|
||||
CHECK_EQUAL(5U, (*itr++).value);
|
||||
CHECK_EQUAL(6U, (*itr++).value);
|
||||
CHECK_EQUAL(3U, (*itr++).value);
|
||||
CHECK_EQUAL(4U, (*itr++).value);
|
||||
CHECK_EQUAL(7U, (*itr++).value);
|
||||
CHECK_EQUAL(8U, (*itr++).value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_splice_move_range_different)
|
||||
{
|
||||
ItemM p1(1U);
|
||||
ItemM p2(2U);
|
||||
ItemM p3(3U);
|
||||
ItemM p4(4U);
|
||||
ItemM p5(5U);
|
||||
ItemM p6(6U);
|
||||
ItemM p7(7U);
|
||||
ItemM p8(8U);
|
||||
|
||||
DataM data1;
|
||||
data1.push_back(std::move(p1));
|
||||
data1.push_back(std::move(p2));
|
||||
data1.push_back(std::move(p3));
|
||||
data1.push_back(std::move(p4));
|
||||
|
||||
DataM data2;
|
||||
data2.push_back(std::move(p5));
|
||||
data2.push_back(std::move(p6));
|
||||
data2.push_back(std::move(p7));
|
||||
data2.push_back(std::move(p8));
|
||||
|
||||
DataM::iterator begin;
|
||||
DataM::iterator end;
|
||||
DataM::iterator to;
|
||||
|
||||
// Move.
|
||||
begin = data2.begin();
|
||||
std::advance(begin, 1);
|
||||
end = begin;
|
||||
std::advance(end, 2);
|
||||
to = data1.begin();
|
||||
std::advance(to, 2);
|
||||
data1.splice(to, std::move(data2), begin, end);
|
||||
|
||||
CHECK_EQUAL(6U, data1.size());
|
||||
CHECK_EQUAL(2U, data2.size());
|
||||
|
||||
DataM::const_iterator itr = data1.begin();
|
||||
|
||||
CHECK_EQUAL(1U, (*itr++).value); // 1
|
||||
CHECK_EQUAL(2U, (*itr++).value); // 2
|
||||
CHECK_EQUAL(6U, (*itr++).value); // 7
|
||||
CHECK_EQUAL(7U, (*itr++).value); // 6
|
||||
CHECK_EQUAL(3U, (*itr++).value); // 3
|
||||
CHECK_EQUAL(4U, (*itr++).value); // 4
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -514,6 +514,31 @@ namespace
|
||||
CHECK(is_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_push_back_literal)
|
||||
{
|
||||
Compare_Data compare_data;
|
||||
Data data;
|
||||
|
||||
compare_data.push_back(1);
|
||||
compare_data.push_back(2);
|
||||
compare_data.push_back(3);
|
||||
compare_data.push_back(4);
|
||||
|
||||
data.push_back(1);
|
||||
data.push_back(2);
|
||||
data.push_back(3);
|
||||
data.push_back(4);
|
||||
|
||||
CHECK_EQUAL(compare_data.size(), data.size());
|
||||
|
||||
bool is_equal = std::equal(data.begin(),
|
||||
data.end(),
|
||||
compare_data.begin());
|
||||
|
||||
CHECK(is_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_push_back_excess)
|
||||
{
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "etl/vector.h"
|
||||
#include "data.h"
|
||||
@ -188,6 +189,34 @@ namespace
|
||||
CHECK(data2 != data);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_constructor)
|
||||
{
|
||||
const size_t SIZE = 10U;
|
||||
typedef etl::vector<std::unique_ptr<uint32_t>, SIZE> Data;
|
||||
|
||||
std::unique_ptr<uint32_t> p1(new uint32_t(1U));
|
||||
std::unique_ptr<uint32_t> p2(new uint32_t(2U));
|
||||
std::unique_ptr<uint32_t> p3(new uint32_t(3U));
|
||||
std::unique_ptr<uint32_t> p4(new uint32_t(4U));
|
||||
|
||||
Data data1;
|
||||
data1.push_back(std::move(p1));
|
||||
data1.push_back(std::move(p2));
|
||||
data1.push_back(std::move(p3));
|
||||
data1.push_back(std::move(p4));
|
||||
|
||||
Data data2(std::move(data1));
|
||||
|
||||
CHECK_EQUAL(0U, data1.size());
|
||||
CHECK_EQUAL(4U, data2.size());
|
||||
|
||||
CHECK_EQUAL(1U, *data2[0]);
|
||||
CHECK_EQUAL(2U, *data2[1]);
|
||||
CHECK_EQUAL(3U, *data2[2]);
|
||||
CHECK_EQUAL(4U, *data2[3]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_assignment)
|
||||
{
|
||||
@ -203,6 +232,35 @@ namespace
|
||||
CHECK(is_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_assignment)
|
||||
{
|
||||
const size_t SIZE = 10U;
|
||||
typedef etl::vector<std::unique_ptr<uint32_t>, SIZE> Data;
|
||||
|
||||
std::unique_ptr<uint32_t> p1(new uint32_t(1U));
|
||||
std::unique_ptr<uint32_t> p2(new uint32_t(2U));
|
||||
std::unique_ptr<uint32_t> p3(new uint32_t(3U));
|
||||
std::unique_ptr<uint32_t> p4(new uint32_t(4U));
|
||||
|
||||
Data data1;
|
||||
data1.push_back(std::move(p1));
|
||||
data1.push_back(std::move(p2));
|
||||
data1.push_back(std::move(p3));
|
||||
data1.push_back(std::move(p4));
|
||||
|
||||
Data data2;
|
||||
data2 = std::move(data1);
|
||||
|
||||
CHECK_EQUAL(0U, data1.size());
|
||||
CHECK_EQUAL(4U, data2.size());
|
||||
|
||||
CHECK_EQUAL(1U, *data2[0]);
|
||||
CHECK_EQUAL(2U, *data2[1]);
|
||||
CHECK_EQUAL(3U, *data2[2]);
|
||||
CHECK_EQUAL(4U, *data2[3]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_assignment_iterface)
|
||||
{
|
||||
@ -221,6 +279,40 @@ namespace
|
||||
CHECK(is_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_move_assignment_interface)
|
||||
{
|
||||
const size_t SIZE = 10U;
|
||||
typedef etl::vector<std::unique_ptr<uint32_t>, SIZE> Data;
|
||||
typedef etl::ivector<std::unique_ptr<uint32_t>> IData;
|
||||
|
||||
std::unique_ptr<uint32_t> p1(new uint32_t(1U));
|
||||
std::unique_ptr<uint32_t> p2(new uint32_t(2U));
|
||||
std::unique_ptr<uint32_t> p3(new uint32_t(3U));
|
||||
std::unique_ptr<uint32_t> p4(new uint32_t(4U));
|
||||
|
||||
Data data1;
|
||||
data1.push_back(std::move(p1));
|
||||
data1.push_back(std::move(p2));
|
||||
data1.push_back(std::move(p3));
|
||||
data1.push_back(std::move(p4));
|
||||
|
||||
Data data2;
|
||||
|
||||
IData& idata1 = data1;
|
||||
IData& idata2 = data2;
|
||||
|
||||
idata2 = std::move(idata1);
|
||||
|
||||
CHECK_EQUAL(0U, data1.size());
|
||||
CHECK_EQUAL(4U, data2.size());
|
||||
|
||||
CHECK_EQUAL(1U, *data2[0]);
|
||||
CHECK_EQUAL(2U, *data2[1]);
|
||||
CHECK_EQUAL(3U, *data2[2]);
|
||||
CHECK_EQUAL(4U, *data2[3]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_self_assignment)
|
||||
{
|
||||
@ -571,6 +663,80 @@ namespace
|
||||
CHECK(is_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_push_back_unique_ptr)
|
||||
{
|
||||
etl::vector<std::unique_ptr<int>, SIZE> data;
|
||||
|
||||
std::unique_ptr<int> p1(new int(1));
|
||||
std::unique_ptr<int> p2(new int(2));
|
||||
std::unique_ptr<int> p3(new int(3));
|
||||
std::unique_ptr<int> p4(new int(4));
|
||||
|
||||
data.push_back(std::move(p1));
|
||||
data.push_back(std::move(p2));
|
||||
data.push_back(std::move(p3));
|
||||
data.push_back(std::move(p4));
|
||||
|
||||
CHECK(!bool(p1));
|
||||
CHECK(!bool(p2));
|
||||
CHECK(!bool(p3));
|
||||
CHECK(!bool(p4));
|
||||
|
||||
CHECK_EQUAL(1, *data[0]);
|
||||
CHECK_EQUAL(2, *data[1]);
|
||||
CHECK_EQUAL(3, *data[2]);
|
||||
CHECK_EQUAL(4, *data[3]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_int)
|
||||
{
|
||||
etl::vector<int, SIZE> data;
|
||||
|
||||
int p1(1);
|
||||
int p2(2);
|
||||
int p3(3);
|
||||
int p4(4);
|
||||
|
||||
data.insert(data.begin(), p1);
|
||||
data.insert(data.begin(), p2);
|
||||
data.insert(data.begin(), p3);
|
||||
data.insert(data.begin(), p4);
|
||||
|
||||
CHECK_EQUAL(4, data[0]);
|
||||
CHECK_EQUAL(3, data[1]);
|
||||
CHECK_EQUAL(2, data[2]);
|
||||
CHECK_EQUAL(1, data[3]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_unique_ptr)
|
||||
{
|
||||
etl::vector<std::unique_ptr<int>, SIZE> data;
|
||||
|
||||
std::unique_ptr<int> p1(new int(1));
|
||||
std::unique_ptr<int> p2(new int(2));
|
||||
std::unique_ptr<int> p3(new int(3));
|
||||
std::unique_ptr<int> p4(new int(4));
|
||||
|
||||
data.insert(data.begin(), std::move(p1));
|
||||
data.insert(data.begin(), std::move(p2));
|
||||
data.insert(data.begin(), std::move(p3));
|
||||
data.insert(data.begin(), std::move(p4));
|
||||
|
||||
CHECK(!bool(p1));
|
||||
CHECK(!bool(p2));
|
||||
CHECK(!bool(p3));
|
||||
CHECK(!bool(p4));
|
||||
|
||||
CHECK_EQUAL(1, *data[3]);
|
||||
CHECK_EQUAL(4, *data[0]);
|
||||
CHECK_EQUAL(3, *data[1]);
|
||||
CHECK_EQUAL(2, *data[2]);
|
||||
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
// To test the CPP03 versions then ETL_TEST_VECTOR_CPP11 must be set to 0 in vector.h
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_back_multiple)
|
||||
|
||||
@ -532,6 +532,7 @@
|
||||
<ClInclude Include="..\..\include\etl\vector.h" />
|
||||
<ClInclude Include="..\..\include\etl\visitor.h" />
|
||||
<ClInclude Include="..\..\include\etl\wstring.h" />
|
||||
<ClInclude Include="..\data.h" />
|
||||
<ClInclude Include="..\ecl_user.h" />
|
||||
<ClInclude Include="..\etl_profile.h" />
|
||||
<ClInclude Include="..\murmurhash3.h" />
|
||||
|
||||
@ -720,6 +720,9 @@
|
||||
<ClInclude Include="..\..\include\etl\absolute.h">
|
||||
<Filter>ETL\Maths</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\data.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\main.cpp">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user