diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 50059cd3..d0713724 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -57,8 +57,8 @@ namespace etl template ETLSTD::pair minmax_element(TIterator begin, - TIterator end, - TCompare compare) + TIterator end, + TCompare compare) { TIterator minimum = begin; TIterator maximum = begin; @@ -88,7 +88,7 @@ namespace etl //*************************************************************************** template ETLSTD::pair minmax_element(TIterator begin, - TIterator end) + TIterator end) { typedef typename ETLSTD::iterator_traits::value_type value_t; @@ -102,7 +102,7 @@ namespace etl //*************************************************************************** template ETLSTD::pair minmax(const T& a, - const T& b) + const T& b) { return (b < a) ? ETLSTD::pair(b, a) : ETLSTD::pair(a, b); } @@ -115,8 +115,8 @@ namespace etl template ETLSTD::pair minmax(const T& a, - const T& b, - TCompare compare) + const T& b, + TCompare compare) { return compare(b, a) ? ETLSTD::pair(b, a) : ETLSTD::pair(a, b); } @@ -1124,12 +1124,17 @@ namespace etl //*************************************************************************** /// Sorts the elements using shell sort. - /// Uses users defined comparison. + /// Uses user defined comparison. ///\ingroup algorithm //*************************************************************************** template - void sort(TIterator first, TIterator last, TCompare compare) + void shell_sort(TIterator first, TIterator last, TCompare compare) { + if (first == last) + { + return; + } + typedef typename ETLSTD::iterator_traits::difference_type difference_t; difference_t n = ETLSTD::distance(first, last); @@ -1160,9 +1165,77 @@ namespace etl ///\ingroup algorithm //*************************************************************************** template + void shell_sort(TIterator first, TIterator last) + { + etl::shell_sort(first, last, ETLSTD::less::value_type>()); + } + + //*************************************************************************** + /// Sorts the elements using insertion sort. + /// Uses user defined comparison. + ///\ingroup algorithm + //*************************************************************************** + template + void insertion_sort(TIterator first, TIterator last, TCompare compare) + { + for (TIterator itr = first; itr != last; ++itr) + { + ETLSTD::rotate(ETLSTD::upper_bound(first, itr, *itr, compare), itr, ETLSTD::next(itr)); + } + } + + //*************************************************************************** + /// Sorts the elements using insertion sort. + ///\ingroup algorithm + //*************************************************************************** + template + void insertion_sort(TIterator first, TIterator last) + { + etl::insertion_sort(first, last, ETLSTD::less::value_type>()); + } + + //*************************************************************************** + /// Sorts the elements. + /// Uses user defined comparison. + ///\ingroup algorithm + //*************************************************************************** + template + void sort(TIterator first, TIterator last, TCompare compare) + { + etl::shell_sort(first, last, compare); + } + + //*************************************************************************** + /// Sorts the elements. + ///\ingroup algorithm + //*************************************************************************** + template void sort(TIterator first, TIterator last) { - etl::sort(first, last, ETLSTD::less::value_type>()); + etl::shell_sort(first, last, ETLSTD::less::value_type>()); + } + + //*************************************************************************** + /// Sorts the elements. + /// Stable. + /// Uses user defined comparison. + ///\ingroup algorithm + //*************************************************************************** + template + void stable_sort(TIterator first, TIterator last, TCompare compare) + { + etl::insertion_sort(first, last, compare); + } + + //*************************************************************************** + /// Sorts the elements. + /// Stable. + ///\ingroup algorithm + //*************************************************************************** + template + void stable_sort(TIterator first, TIterator last) + { + etl::insertion_sort(first, last, ETLSTD::less::value_type>()); } #if ETL_CPP11_SUPPORTED diff --git a/include/etl/delegate.h b/include/etl/delegate.h index e5a8941e..2c92281a 100644 --- a/include/etl/delegate.h +++ b/include/etl/delegate.h @@ -197,7 +197,7 @@ namespace etl //************************************************************************* TReturn operator()(TParams... args) const { - ETL_ASSERT(invocation.stub != nullptr, ETL_ERROR(delegate_uninitialised)); + ETL_ASSERT(is_valid(), ETL_ERROR(delegate_uninitialised)); return (*invocation.stub)(invocation.object, args...); } diff --git a/include/etl/forward_list.h b/include/etl/forward_list.h index 9c1ffe3b..6edca31f 100644 --- a/include/etl/forward_list.h +++ b/include/etl/forward_list.h @@ -1185,9 +1185,29 @@ namespace etl } //************************************************************************* - /// Sort using in-place merge sort algorithm. - /// Uses a supplied predicate function or functor. - /// This is not my algorithm. I got it off the web somewhere. + /// Stable sort using in-place merge sort algorithm. + /// Copyright 2001 Simon Tatham. + /// + /// 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 SIMON TATHAM 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. //************************************************************************* template void sort(TCompare compare) diff --git a/include/etl/indirect_vector.h b/include/etl/indirect_vector.h new file mode 100644 index 00000000..71135f45 --- /dev/null +++ b/include/etl/indirect_vector.h @@ -0,0 +1,1610 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2019 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_INDIRECT_VECTOR_INCLUDED +#define ETL_INDIRECT_VECTOR_INCLUDED + +#include "platform.h" +#include "vector.h" +#include "pool.h" + +#include "stl/iterator.h" +#include "stl/functional.h" + +#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) + #include +#endif + +#ifdef ETL_COMPILER_GCC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif + +//***************************************************************************** +///\defgroup indirect_vector indirect_vector +/// A indirect_vector with the capacity defined at compile time. Objects are allocated from a pool and stored as pointers. +///\ingroup containers +//***************************************************************************** + +namespace etl +{ + //*************************************************************************** + /// The base class for specifically sized vectors. + /// Can be used as a reference type for all vectors containing a specific type. + ///\ingroup indirect_vector + //*************************************************************************** + template + class iindirect_vector + { + public: + + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; +#if ETL_CPP11_SUPPORTED + typedef T&& rvalue_reference; +#endif + typedef T* pointer; + typedef const T* const_pointer; + typedef pointer const * indirect_pointer; + typedef const_pointer const * indirect_const_pointer; + + typedef typename etl::ivector::size_type size_type; + typedef typename etl::ivector::difference_type difference_type; + + //************************************************************************* + /// iterator. + //************************************************************************* + class iterator : public std::iterator + { + public: + + friend class iindirect_vector; + + iterator() + { + } + + iterator(const iterator& other) + : lookup_itr(other.lookup_itr) + { + } + + iterator& operator ++() + { + ++lookup_itr; + return *this; + } + + iterator operator ++(int) + { + iterator temp(*this); + ++lookup_itr; + return temp; + } + + iterator& operator --() + { + --lookup_itr; + return *this; + } + + iterator operator --(int) + { + iterator temp(*this); + --lookup_itr; + return temp; + } + + iterator operator =(const iterator& other) + { + lookup_itr = other.lookup_itr; + return *this; + } + + iterator operator +=(size_type n) + { + lookup_itr += n; + return *this; + } + + iterator operator -=(size_type n) + { + lookup_itr -= n; + return *this; + } + + reference operator *() + { + return **lookup_itr; + } + + const_reference operator *() const + { + return **lookup_itr; + } + + pointer operator &() + { + return &(**lookup_itr); + } + + const_pointer operator &() const + { + return &(**lookup_itr); + } + + pointer operator ->() + { + return &(**lookup_itr); + } + + const_pointer operator ->() const + { + return &(**lookup_itr); + } + + friend iterator operator +(const iterator& lhs, difference_type offset) + { + iterator result(lhs); + result += offset; + return result; + } + + friend iterator operator -(const iterator& lhs, difference_type offset) + { + iterator result(lhs); + result -= offset; + return result; + } + + friend difference_type operator -(const iterator& lhs, const iterator& rhs) + { + return lhs.lookup_itr - rhs.lookup_itr; + } + + friend bool operator == (const iterator& lhs, const iterator& rhs) + { + return lhs.lookup_itr == rhs.lookup_itr; + } + + friend bool operator != (const iterator& lhs, const iterator& rhs) + { + return !(lhs == rhs); + } + + friend bool operator < (const iterator& lhs, const iterator& rhs) + { + return lhs.lookup_itr < rhs.lookup_itr; + } + + private: + + typedef typename etl::ivector::iterator lookup_itr_t; + + iterator(lookup_itr_t itr_) + : lookup_itr(itr_) + { + } + + lookup_itr_t lookup_itr; + }; + + //************************************************************************* + /// const_iterator. + //************************************************************************* + class const_iterator : public std::iterator + { + public: + + friend class iindirect_vector; + + const_iterator() + { + } + + const_iterator(const const_iterator& other) + : lookup_itr(other.lookup_itr) + { + } + + const_iterator(const typename iindirect_vector::iterator& other) + : lookup_itr(other.lookup_itr) + { + } + + const_iterator& operator ++() + { + ++lookup_itr; + return *this; + } + + const_iterator operator ++(int) + { + const_iterator temp(*this); + ++lookup_itr; + return temp; + } + + const_iterator& operator --() + { + --lookup_itr; + return *this; + } + + const_iterator operator --(int) + { + const_iterator temp(*this); + --lookup_itr; + return temp; + } + + const_iterator operator +=(size_type n) + { + lookup_itr += n; + return *this; + } + + const_iterator operator -=(size_type n) + { + lookup_itr -= n; + return *this; + } + + const_iterator operator =(const const_iterator& other) + { + lookup_itr = other.lookup_itr; + return *this; + } + + const_reference operator *() const + { + return **lookup_itr; + } + + const_pointer operator &() const + { + return &(**lookup_itr); + } + + const_pointer operator ->() const + { + return &(**lookup_itr); + } + + friend const_iterator operator +(const const_iterator& lhs, difference_type offset) + { + const_iterator result(lhs); + result += offset; + return result; + } + + friend const_iterator operator -(const const_iterator& lhs, difference_type offset) + { + const_iterator result(lhs); + result -= offset; + return result; + } + + friend difference_type operator -(const const_iterator& lhs, const const_iterator& rhs) + { + return lhs.lookup_itr - rhs.lookup_itr; + } + + friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) + { + return lhs.lookup_itr == rhs.lookup_itr; + } + + friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) + { + return !(lhs == rhs); + } + + friend bool operator < (const const_iterator& lhs, const const_iterator& rhs) + { + return lhs.lookup_itr < rhs.lookup_itr; + } + + private: + + typedef typename etl::ivector::const_iterator lookup_itr_t; + + const_iterator(lookup_itr_t itr_) + : lookup_itr(itr_) + { + } + + lookup_itr_t lookup_itr; + }; + + typedef ETLSTD::reverse_iterator reverse_iterator; + typedef ETLSTD::reverse_iterator const_reverse_iterator; + + protected: + + typedef typename etl::parameter_type::type parameter_t; + + public: + + //********************************************************************* + /// Returns an iterator to the beginning of the indirect_vector. + ///\return An iterator to the beginning of the indirect_vector. + //********************************************************************* + iterator begin() + { + return iterator(lookup.begin()); + } + + //********************************************************************* + /// Returns a const_iterator to the beginning of the indirect_vector. + ///\return A const iterator to the beginning of the indirect_vector. + //********************************************************************* + const_iterator begin() const + { + return const_iterator(lookup.begin()); + } + + //********************************************************************* + /// Returns an iterator to the end of the indirect_vector. + ///\return An iterator to the end of the indirect_vector. + //********************************************************************* + iterator end() + { + return iterator(lookup.end()); + } + + //********************************************************************* + /// Returns a const_iterator to the end of the indirect_vector. + ///\return A const iterator to the end of the indirect_vector. + //********************************************************************* + const_iterator end() const + { + return const_iterator(lookup.end()); + } + + //********************************************************************* + /// Returns a const_iterator to the beginning of the indirect_vector. + ///\return A const iterator to the beginning of the indirect_vector. + //********************************************************************* + const_iterator cbegin() const + { + return const_iterator(lookup.begin()); + } + + //********************************************************************* + /// Returns a const_iterator to the end of the indirect_vector. + ///\return A const iterator to the end of the indirect_vector. + //********************************************************************* + const_iterator cend() const + { + return const_iterator(lookup.cend()); + } + + //********************************************************************* + /// Returns an reverse iterator to the reverse beginning of the indirect_vector. + ///\return Iterator to the reverse beginning of the indirect_vector. + //********************************************************************* + reverse_iterator rbegin() + { + return reverse_iterator(end()); + } + + //********************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the indirect_vector. + ///\return Const iterator to the reverse beginning of the indirect_vector. + //********************************************************************* + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(end()); + } + + //********************************************************************* + /// Returns a reverse iterator to the end + 1 of the indirect_vector. + ///\return Reverse iterator to the end + 1 of the indirect_vector. + //********************************************************************* + reverse_iterator rend() + { + return reverse_iterator(begin()); + } + + //********************************************************************* + /// Returns a const reverse iterator to the end + 1 of the indirect_vector. + ///\return Const reverse iterator to the end + 1 of the indirect_vector. + //********************************************************************* + const_reverse_iterator rend() const + { + return const_reverse_iterator(begin()); + } + + //********************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the indirect_vector. + ///\return Const reverse iterator to the reverse beginning of the indirect_vector. + //********************************************************************* + const_reverse_iterator crbegin() const + { + return const_reverse_iterator(cend()); + } + + //********************************************************************* + /// Returns a const reverse iterator to the end + 1 of the indirect_vector. + ///\return Const reverse iterator to the end + 1 of the indirect_vector. + //********************************************************************* + const_reverse_iterator crend() const + { + return const_reverse_iterator(cbegin()); + } + + //********************************************************************* + /// Resizes the indirect_vector. + /// If asserts or exceptions are enabled and the new size is larger than the + /// maximum then a vector_full is thrown. + ///\param new_size The new size. + //********************************************************************* + void resize(size_t new_size) + { + resize(new_size, T()); + } + + //********************************************************************* + /// Resizes the indirect_vector. + /// If asserts or exceptions are enabled and the new size is larger than the + /// maximum then a vector_full is thrown. + ///\param new_size The new size. + ///\param value The value to fill new elements with. Default = default constructed value. + //********************************************************************* + void resize(size_t new_size, T value) + { + ETL_ASSERT(new_size <= capacity(), ETL_ERROR(vector_full)); + + if (new_size <= capacity()) + { + if (new_size > size()) + { + size_type n = new_size - size(); + + while (n-- != 0U) + { + T* p = storage.create(value); + lookup.push_back(p); + } + } + else + { + size_type n = size() - new_size; + + while (n-- != 0U) + { + pop_back(); + } + } + } + } + + //********************************************************************* + /// Does nothing. + //********************************************************************* + void reserve(size_t) + { + } + + //********************************************************************* + /// Returns a reference to the value at index 'i' + ///\param i The index. + ///\return A reference to the value at index 'i' + //********************************************************************* + reference operator [](size_t i) + { + return *lookup[i]; + } + + //********************************************************************* + /// Returns a const reference to the value at index 'i' + ///\param i The index. + ///\return A const reference to the value at index 'i' + //********************************************************************* + const_reference operator [](size_t i) const + { + return *lookup[i]; + } + + //********************************************************************* + /// Returns a reference to the value at index 'i' + /// If asserts or exceptions are enabled, emits an etl::vector_out_of_bounds if the index is out of range. + ///\param i The index. + ///\return A reference to the value at index 'i' + //********************************************************************* + reference at(size_t i) + { + return *lookup.at(i); + } + + //********************************************************************* + /// Returns a const reference to the value at index 'i' + /// If asserts or exceptions are enabled, emits an etl::vector_out_of_bounds if the index is out of range. + ///\param i The index. + ///\return A const reference to the value at index 'i' + //********************************************************************* + const_reference at(size_t i) const + { + return *lookup.at(i); + } + + //********************************************************************* + /// Returns a reference to the first element. + ///\return A reference to the first element. + //********************************************************************* + reference front() + { + return *(lookup.front()); + } + + //********************************************************************* + /// Returns a const reference to the first element. + ///\return A const reference to the first element. + //********************************************************************* + const_reference front() const + { + return *(lookup.front()); + } + + //********************************************************************* + /// Returns a reference to the last element. + ///\return A reference to the last element. + //********************************************************************* + reference back() + { + return *(lookup.back()); + } + + //********************************************************************* + /// Returns a const reference to the last element. + ///\return A const reference to the last element. + //********************************************************************* + const_reference back() const + { + return *(lookup.back()); + } + + //********************************************************************* + /// Returns a pointer to the beginning of the internal lookup vector data. + /// These are a list of pointers to objects + ///\return An indirect pointer to the beginning of the internal lookup vector data. + //********************************************************************* + indirect_pointer data() + { + return lookup.data(); + } + + //********************************************************************* + /// Returns a pointer to the beginning of the internal lookup vector data. + /// These are a list of pointers to objects + ///\return An indirect pointer to the beginning of the internal lookup vector data. + //********************************************************************* + indirect_const_pointer data() const + { + return lookup.data(); + } + + //********************************************************************* + /// Assigns values to the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_vector does not have enough free space. + /// If asserts or exceptions are enabled, emits vector_iterator if the iterators are reversed. + ///\param first The iterator to the first element. + ///\param last The iterator to the last element + 1. + //********************************************************************* + template + void assign(TIterator first, TIterator last) + { + ETL_STATIC_ASSERT((etl::is_same::type, typename etl::remove_cv::value_type>::type>::value), "Iterator type does not match container type"); + +#if defined(ETL_DEBUG) + difference_type d = std::distance(first, last); + ETL_ASSERT(static_cast(d) <= capacity(), ETL_ERROR(vector_full)); +#endif + + initialise(); + + while (first != last) + { + T* p = storage.create(*first); + lookup.push_back(p); + ++first; + } + } + + //********************************************************************* + /// Assigns values to the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_vector does not have enough free space. + ///\param n The number of elements to add. + ///\param value The value to insert for each element. + //********************************************************************* + void assign(size_t n, parameter_t value) + { + ETL_ASSERT(n <= capacity(), ETL_ERROR(vector_full)); + + initialise(); + + while (n-- != 0U) + { + T* p = storage.create(value); + lookup.push_back(p); + } + } + + //************************************************************************* + /// Clears the indirect_vector. + //************************************************************************* + void clear() + { + initialise(); + } + + //********************************************************************* + /// Inserts a value at the end of the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_vector is already full. + ///\param value The value to add. + //********************************************************************* + void push_back(const_reference value) + { +#if defined(ETL_CHECK_PUSH_POP) + ETL_ASSERT(size() != capacity(), ETL_ERROR(vector_full)); +#endif + T* p = storage.create(value); + lookup.push_back(p); + } + +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value at the end of the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_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 + T* p = storage.create(std::move(value)); + lookup.push_back(p); + } +#endif + +#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_VECTOR_FORCE_CPP03) + //********************************************************************* + /// Constructs a value at the end of the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_vector is already full. + ///\param value The value to add. + //********************************************************************* + template + void emplace_back(Args && ... args) + { + T* p = storage.create(std::forward(args)...); + lookup.push_back(p); + } +#else + //********************************************************************* + /// Constructs a value at the end of the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_vector is already full. + ///\param value The value to add. + //********************************************************************* + template + void emplace_back(const T1& value1) + { + T* p = storage.create(T(value1)); + lookup.push_back(p); + } + + //********************************************************************* + /// Constructs a value at the end of the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_vector is already full. + ///\param value The value to add. + //********************************************************************* + template + void emplace_back(const T1& value1, const T2& value2) + { + T* p = storage.create(T(value1, value2)); + lookup.push_back(p); + } + + //********************************************************************* + /// Constructs a value at the end of the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_vector is already full. + ///\param value The value to add. + //********************************************************************* + template + void emplace_back(const T1& value1, const T2& value2, const T3& value3) + { + T* p = storage.create(T(value1, value2, value3)); + lookup.push_back(p); + } + + //********************************************************************* + /// Constructs a value at the end of the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_vector is already full. + ///\param value The value to add. + //********************************************************************* + template + void emplace_back(const T1& value1, const T2& value2, const T3& value3, const T4& value4) + { + T* p = storage.create(T(value1, value2, value3, value4)); + lookup.push_back(p); + } +#endif + + //************************************************************************* + /// Removes an element from the end of the indirect_vector. + //************************************************************************* + void pop_back() + { + ETL_ASSERT(!empty(), ETL_ERROR(vector_empty)); + + reference object = back(); + storage.destroy(etl::addressof(object)); + lookup.pop_back(); + } + + //********************************************************************* + /// Inserts a value to the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_vector is already full. + ///\param position The position to insert before. + ///\param value The value to insert. + //********************************************************************* + iterator insert(iterator position, const_reference value) + { + ETL_ASSERT(size() + 1 <= capacity(), ETL_ERROR(vector_full)); + + T* p = storage.create(T(value)); + position = iterator(lookup.insert(position.lookup_itr, p)); + + return position; + } + +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_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)); + + T* p = storage.create(T(std::move(value))); + position = iterator(lookup.insert(position.lookup_itr, p)); + + return position; + } +#endif + + //************************************************************************* + /// Emplaces a value to the vector at the specified position. + //************************************************************************* +#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) + template + iterator emplace(iterator position, Args && ... args) + { + ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(T(std::forward(args)...)); + position = iterator(lookup.insert(position.lookup_itr, p)); + + return position; + } +#else + template + iterator emplace(iterator position, const T1& value1) + { + ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(T(value1)); + position = iterator(lookup.insert(position.lookup_itr, p)); + + return position; + } + + template + iterator emplace(iterator position, const T1& value1, const T2& value2) + { + ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(T(value1, value2)); + position = iterator(lookup.insert(position.lookup_itr, p)); + + return position; + } + + template + iterator emplace(iterator position, const T1& value1, const T2& value2, const T3& value3) + { + ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(T(value1, value2, value3)); + position = iterator(lookup.insert(position.lookup_itr, p)); + + return position; + } + + template + iterator emplace(iterator position, const T1& value1, const T2& value2, const T3& value3, const T4& value4) + { + ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(T(value1, value2, value3, value4)); + position = iterator(lookup.insert(position.lookup_itr, p)); + + return position; + } +#endif + + //********************************************************************* + /// Inserts 'n' values to the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_vector does not have enough free space. + ///\param position The position to insert before. + ///\param n The number of elements to add. + ///\param value The value to insert. + //********************************************************************* + void insert(iterator position, size_t n, parameter_t value) + { + ETL_ASSERT((size() + n) <= capacity(), ETL_ERROR(vector_full)); + + // Make space for the new lookup pointers. + typename etl::ivector::iterator lookup_itr = position.lookup_itr; + lookup.insert(lookup_itr, n, nullptr); + + while (n-- != 0U) + { + T* p = storage.create(value); + *lookup_itr++ = p; + } + } + + //********************************************************************* + /// Inserts a range of values to the indirect_vector. + /// If asserts or exceptions are enabled, emits vector_full if the indirect_vector does not have enough free space. + ///\param position The position to insert before. + ///\param first The first element to add. + ///\param last The last + 1 element to add. + //********************************************************************* + template + void insert(iterator position, TIterator first, TIterator last) + { + size_t count = size_t(std::distance(first, last)); + + ETL_ASSERT((size() + count) <= capacity(), ETL_ERROR(vector_full)); + + // Make space for the new lookup pointers. + typename etl::ivector::iterator lookup_itr = position.lookup_itr; + lookup.insert(lookup_itr, count, nullptr); + + while (first != last) + { + T* p = storage.create(*first); + *lookup_itr++ = p; + ++first; + } + } + + //********************************************************************* + /// Erases an element. + ///\param i_element Iterator to the element. + ///\return An iterator pointing to the element that followed the erased element. + //********************************************************************* + iterator erase(iterator i_element) + { + storage.destroy(etl::addressof(*i_element)); + + return iterator(lookup.erase(i_element.lookup_itr)); + } + + //********************************************************************* + /// Erases a range of elements. + /// The range includes all the elements between first and last, including the + /// element pointed by first, but not the one pointed by last. + ///\param first Iterator to the first element. + ///\param last Iterator to the last element. + ///\return An iterator pointing to the element that followed the erased element. + //********************************************************************* + iterator erase(iterator first, iterator last) + { + iterator element = first; + + while (element != last) + { + storage.destroy(etl::addressof(*element)); + ++element; + } + + lookup.erase(first.lookup_itr, last.lookup_itr); + + return last; + } + + //************************************************************************* + /// Assignment operator. + //************************************************************************* + iindirect_vector& operator = (const iindirect_vector& rhs) + { + if (&rhs != this) + { + assign(rhs.cbegin(), rhs.cend()); + } + + return *this; + } + +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + iindirect_vector& operator = (iindirect_vector&& 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 indirect_vector. + ///\return The current size of the indirect_vector. + //************************************************************************* + size_type size() const + { + return lookup.size(); + } + + //************************************************************************* + /// Gets the current capacity of the indirect_vector. + ///\return The capacity of the indirect_vector. +//************************************************************************* + size_type capacity() const + { + return lookup.capacity(); + } + + //************************************************************************* + /// Checks the 'empty' state of the indirect_vector. + ///\return true if empty. + //************************************************************************* + bool empty() const + { + return lookup.empty(); + } + + //************************************************************************* + /// Checks the 'full' state of the indirect_vector. + ///\return true if full. + //************************************************************************* + bool full() const + { + return lookup.full(); + } + + //************************************************************************* + /// Returns the maximum size. + ///\return The maximum size. + //************************************************************************* + size_type max_size() const + { + return lookup.max_size(); + } + + //************************************************************************* + /// Returns the remaining capacity. + ///\return The remaining capacity. + //************************************************************************* + size_type available() const + { + return lookup.available(); + } + + //************************************************************************* + /// Sorts the indirect vector using the default 'less'. + //************************************************************************* + void sort() + { + sort_function(begin(), end(), std::less()); + } + + //************************************************************************* + /// Sorts the indirect vector using a supplied compare function. + //************************************************************************* + template + void sort(TCompare compare) + { + sort_function(begin(), end(), compare); + } + + //************************************************************************* + /// Sorts the indirect vector between two iterators. + //************************************************************************* + void sort(iterator first, iterator last) + { + sort_function(first, last, std::less()); + } + + //************************************************************************* + /// Sorts the indirect vector between two iterators. + //************************************************************************* + template + void sort(iterator first, iterator last, TCompare compare) + { + sort_function(first, last, compare); + } + + //************************************************************************* + /// Sorts the indirect vector using the default 'less'. + //************************************************************************* + void stable_sort() + { + stable_sort_function(begin(), end(), std::less()); + } + + //************************************************************************* + /// Sorts the indirect vector using a supplied compare function. + //************************************************************************* + template + void stable_sort(TCompare compare) + { + stable_sort_function(begin(), end(), compare); + } + + //************************************************************************* + /// Sorts the indirect vector between two iterators. + //************************************************************************* + void stable_sort(iterator first, iterator last) + { + stable_sort_function(first, last, std::less()); + } + + //************************************************************************* + /// Sorts the indirect vector between two iterators. + //************************************************************************* + template + void stable_sort(iterator first, iterator last, TCompare compare) + { + stable_sort_function(first, last, compare); + } + + //************************************************************************* + /// Checks to see if the vector is sorted, using the default 'less'. + //************************************************************************* + bool is_sorted() const + { + return is_sorted_function(cbegin(), cend(), std::less()); + } + + //************************************************************************* + /// Sorts the indirect vector using a supplied compare function. + //************************************************************************* + template + bool is_sorted(TCompare compare) const + { + return is_sorted_function(cbegin(), cend(), compare); + } + + //************************************************************************* + /// Sorts the indirect vector between two iterators. + //************************************************************************* + bool is_sorted(const_iterator first, const_iterator last) const + { + return is_sorted_function(first, last, std::less()); + } + + //************************************************************************* + /// Sorts the indirect vector between two iterators. + //************************************************************************* + template + bool is_sorted(const_iterator first, const_iterator last, TCompare compare) const + { + return is_sorted_function(first, last, compare); + } + + protected: + + //********************************************************************* + /// Constructor. + //********************************************************************* + iindirect_vector(etl::ivector& lookup_, etl::ipool& storage_) + : lookup(lookup_) + , storage(storage_) + { + } + + //********************************************************************* + /// Initialise the indirect_vector. + //********************************************************************* + void initialise() + { + iterator itr = begin(); + + while (itr != end()) + { + storage.destroy(etl::addressof(*itr)); + ++itr; + } + + lookup.clear(); + } + + etl::ivector& lookup; + etl::ipool& storage; + + private: + + //********************************************************************* + /// Sorts the range. + //********************************************************************* + template + void sort_function(iterator first, iterator last, TCompare compare) + { + etl::sort(first.lookup_itr, last.lookup_itr, ObjectCompare(compare)); + } + + //********************************************************************* + /// Sorts the range. + /// Stable + //********************************************************************* + template + void stable_sort_function(iterator first, iterator last, TCompare compare) + { + etl::stable_sort(first.lookup_itr, last.lookup_itr, ObjectCompare(compare)); + } + + //********************************************************************* + /// Checks if the range is sorted. + //********************************************************************* + template + bool is_sorted_function(const_iterator first, const_iterator last, TCompare compare) const + { + return etl::is_sorted(first.lookup_itr, last.lookup_itr, ObjectCompare(compare)); + } + + //********************************************************************* + /// How to compare two objects via the lookup iterators. + /// \tparam TCompare Type to compare two T objects. + //********************************************************************* + template + struct ObjectCompare + { + ObjectCompare(TCompare compare_) + : compare(compare_) + { + } + + bool operator ()(const T* lhs, const T* rhs) const + { + return compare(*lhs, *rhs); + } + + TCompare compare; + }; + + // Disable copy construction. + iindirect_vector(const iindirect_vector&) ETL_DELETE; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_INDIRECT_VECTOR) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual +#else + protected: +#endif + ~iindirect_vector() + { + initialise(); + } + }; + + //*************************************************************************** + /// Equal operator. + ///\param lhs Reference to the first indirect_vector. + ///\param rhs Reference to the second indirect_vector. + ///\return true if the arrays are equal, otherwise false + ///\ingroup indirect_vector + //*************************************************************************** + template + bool operator ==(const etl::iindirect_vector& lhs, const etl::iindirect_vector& rhs) + { + return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); + } + + //*************************************************************************** + /// Not equal operator. + ///\param lhs Reference to the first indirect_vector. + ///\param rhs Reference to the second indirect_vector. + ///\return true if the arrays are not equal, otherwise false + ///\ingroup indirect_vector + //*************************************************************************** + template + bool operator !=(const etl::iindirect_vector& lhs, const etl::iindirect_vector& rhs) + { + return !(lhs == rhs); + } + + //*************************************************************************** + /// Less than operator. + ///\param lhs Reference to the first indirect_vector. + ///\param rhs Reference to the second indirect_vector. + ///\return true if the first indirect_vector is lexicographically less than the second, otherwise false + ///\ingroup indirect_vector + //*************************************************************************** + template + bool operator <(const etl::iindirect_vector& lhs, const etl::iindirect_vector& rhs) + { + return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); + } + + //*************************************************************************** + /// Greater than operator. + ///\param lhs Reference to the first indirect_vector. + ///\param rhs Reference to the second indirect_vector. + ///\return true if the first indirect_vector is lexicographically greater than the second, otherwise false + ///\ingroup indirect_vector + //*************************************************************************** + template + bool operator >(const etl::iindirect_vector& lhs, const etl::iindirect_vector& rhs) + { + return (rhs < lhs); + } + + //*************************************************************************** + /// Less than or equal operator. + ///\param lhs Reference to the first indirect_vector. + ///\param rhs Reference to the second indirect_vector. + ///\return true if the first indirect_vector is lexicographically less than or equal to the second, otherwise false + ///\ingroup indirect_vector + //*************************************************************************** + template + bool operator <=(const etl::iindirect_vector& lhs, const etl::iindirect_vector& rhs) + { + return !(lhs > rhs); + } + + //*************************************************************************** + /// Greater than or equal operator. + ///\param lhs Reference to the first indirect_vector. + ///\param rhs Reference to the second indirect_vector. + ///\return true if the first indirect_vector is lexicographically greater than or equal to the second, otherwise false + ///\ingroup indirect_vector + //*************************************************************************** + template + bool operator >=(const etl::iindirect_vector& lhs, const etl::iindirect_vector& rhs) + { + return !(lhs < rhs); + } + + //*************************************************************************** + /// A indirect_vector implementation that uses a fixed size buffer. + ///\tparam T The element type. + ///\tparam MAX_SIZE_ The maximum number of elements that can be stored. + ///\ingroup indirect_vector + //*************************************************************************** + template + class indirect_vector : public etl::iindirect_vector + { + public: + + static const size_t MAX_SIZE = MAX_SIZE_; + + //************************************************************************* + /// Constructor. + //************************************************************************* + indirect_vector() + : etl::iindirect_vector(lookup_vector, storage_pool) + { + this->initialise(); + } + + //************************************************************************* + /// Constructor, with size. + ///\param initial_size The initial size of the indirect_vector. + //************************************************************************* + explicit indirect_vector(size_t initial_size) + : etl::iindirect_vector(lookup_vector, storage_pool) + { + this->initialise(); + this->resize(initial_size); + } + + //************************************************************************* + /// Constructor, from initial size and value. + ///\param initial_size The initial size of the indirect_vector. + ///\param value The value to fill the indirect_vector with. + //************************************************************************* + indirect_vector(size_t initial_size, typename etl::iindirect_vector::parameter_t value) + : etl::iindirect_vector(lookup_vector, storage_pool) + { + this->initialise(); + this->resize(initial_size, value); + } + + //************************************************************************* + /// Constructor, from an iterator range. + ///\tparam TIterator The iterator type. + ///\param first The iterator to the first element. + ///\param last The iterator to the last element + 1. + //************************************************************************* + template + indirect_vector(TIterator first, TIterator last) + : etl::iindirect_vector(lookup_vector, storage_pool) + { + this->assign(first, last); + } + +#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) + //************************************************************************* + /// Constructor, from an initializer_list. + //************************************************************************* + indirect_vector(std::initializer_list init) + : etl::iindirect_vector(lookup_vector, storage_pool) + { + this->assign(init.begin(), init.end()); + } +#endif + + //************************************************************************* + /// Copy constructor. + //************************************************************************* + indirect_vector(const indirect_vector& other) + : etl::iindirect_vector(lookup_vector, storage_pool) + { + this->assign(other.begin(), other.end()); + } + + //************************************************************************* + /// Assignment operator. + //************************************************************************* + indirect_vector& operator = (const indirect_vector& rhs) + { + if (&rhs != this) + { + this->assign(rhs.cbegin(), rhs.cend()); + } + + return *this; + } + +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + indirect_vector(indirect_vector&& other) + : etl::iindirect_vector(lookup_vector, storage_pool) + { + if (this != &other) + { + this->initialise(); + + typename etl::iindirect_vector::iterator itr = other.begin(); + while (itr != other.end()) + { + this->push_back(std::move(*itr)); + ++itr; + } + + other.initialise(); + } + } + + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + indirect_vector& operator = (indirect_vector&& rhs) + { + if (&rhs != this) + { + this->clear(); + typename etl::iindirect_vector::iterator itr = rhs.begin(); + while (itr != rhs.end()) + { + this->push_back(std::move(*itr)); + ++itr; + } + + rhs.initialise(); + } + + return *this; + } +#endif + + //************************************************************************* + /// Destructor. + //************************************************************************* + ~indirect_vector() + { + this->clear(); + } + + private: + + etl::vector lookup_vector; + etl::pool storage_pool; + }; + +// //*************************************************************************** +// /// A indirect_vector implementation that uses a fixed size buffer. +// /// The buffer is supplied on construction. +// ///\tparam T The element type. +// ///\ingroup indirect_vector +// //*************************************************************************** +// template +// class indirect_vector : public etl::iindirect_vector +// { +// public: +// +// //************************************************************************* +// /// Constructor. +// //************************************************************************* +// indirect_vector(void* buffer, size_t max_size) +// : etl::iindirect_vector(reinterpret_cast(buffer), max_size) +// { +// this->initialise(); +// } +// +// //************************************************************************* +// /// Constructor, with size. +// ///\param initial_size The initial size of the indirect_vector. +// //************************************************************************* +// explicit indirect_vector(size_t initial_size, void* buffer, size_t max_size) +// : etl::iindirect_vector(reinterpret_cast(buffer), max_size) +// { +// this->initialise(); +// this->resize(initial_size); +// } +// +// //************************************************************************* +// /// Constructor, from initial size and value. +// ///\param initial_size The initial size of the indirect_vector. +// ///\param value The value to fill the indirect_vector with. +// //************************************************************************* +// indirect_vector(size_t initial_size, typename etl::iindirect_vector::parameter_t value, void* buffer, size_t max_size) +// : etl::iindirect_vector(reinterpret_cast(buffer), max_size) +// { +// this->initialise(); +// this->resize(initial_size, value); +// } +// +// //************************************************************************* +// /// Constructor, from an iterator range. +// ///\tparam TIterator The iterator type. +// ///\param first The iterator to the first element. +// ///\param last The iterator to the last element + 1. +// //************************************************************************* +// template +// indirect_vector(TIterator first, TIterator last, void* buffer, size_t max_size) +// : etl::iindirect_vector(reinterpret_cast(buffer), max_size) +// { +// this->assign(first, last); +// } +// +//#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) +// //************************************************************************* +// /// Constructor, from an initializer_list. +// //************************************************************************* +// indirect_vector(std::initializer_list init, void* buffer, size_t max_size) +// : etl::iindirect_vector(reinterpret_cast(buffer), max_size) +// { +// this->assign(init.begin(), init.end()); +// } +//#endif +// +// //************************************************************************* +// /// Copy constructor. +// //************************************************************************* +// indirect_vector(const indirect_vector& other, void* buffer, size_t max_size) +// : etl::iindirect_vector(reinterpret_cast(buffer), max_size) +// { +// this->assign(other.begin(), other.end()); +// } +// +// //************************************************************************* +// /// Assignment operator. +// //************************************************************************* +// indirect_vector& operator = (const indirect_vector& rhs) +// { +// if (&rhs != this) +// { +// this->assign(rhs.cbegin(), rhs.cend()); +// } +// +// return *this; +// } +// +//#if ETL_CPP11_SUPPORTED +// //************************************************************************* +// /// Move constructor. +// //************************************************************************* +// indirect_vector(indirect_vector&& other, void* buffer, size_t max_size) +// : etl::iindirect_vector(reinterpret_cast(buffer), max_size) +// { +// if (this != &other) +// { +// this->initialise(); +// +// this->p_buffer = other.p_buffer; +// this->p_end = other.p_end; +// +// this->initialise_destination_external_buffer_after_move(); +// other.initialise_source_external_buffer_after_move(); +// } +// } +// +// //************************************************************************* +// /// Move assignment operator. +// //************************************************************************* +// indirect_vector& operator = (indirect_vector&& rhs) +// { +// if (&rhs != this) +// { +// this->clear(); +// this->p_buffer = rhs.p_buffer; +// this->p_end = rhs.p_end; +// +// this->initialise_destination_external_buffer_after_move(); +// rhs.initialise_source_external_buffer_after_move(); +// } +// +// return *this; +// } +//#endif +// +// //************************************************************************* +// /// Destructor. +// //************************************************************************* +// ~indirect_vector() +// { +// this->clear(); +// } +// }; +} + +#ifdef ETL_COMPILER_GCC +#pragma GCC diagnostic pop +#endif + +#endif + diff --git a/include/etl/intrusive_forward_list.h b/include/etl/intrusive_forward_list.h index 7303e984..d2265bb6 100644 --- a/include/etl/intrusive_forward_list.h +++ b/include/etl/intrusive_forward_list.h @@ -715,9 +715,29 @@ namespace etl } //************************************************************************* - /// Sort using in-place merge sort algorithm. - /// Uses a supplied predicate function or functor. - /// This is not my algorithm. I got it off the web somewhere. + /// Stable sort using in-place merge sort algorithm. + /// Copyright 2001 Simon Tatham. + /// + /// 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 SIMON TATHAM 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. //************************************************************************* template void sort(TCompare compare) diff --git a/include/etl/intrusive_list.h b/include/etl/intrusive_list.h index c3fde511..2b250c94 100644 --- a/include/etl/intrusive_list.h +++ b/include/etl/intrusive_list.h @@ -784,9 +784,29 @@ namespace etl } //************************************************************************* - /// Sort using in-place merge sort algorithm. - /// Uses a supplied predicate function or functor. - /// This is not my algorithm. I got it off the web somewhere. + /// Stable sort using in-place merge sort algorithm. + /// Copyright 2001 Simon Tatham. + /// + /// 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 SIMON TATHAM 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. //************************************************************************* template void sort(TCompare compare) diff --git a/include/etl/list.h b/include/etl/list.h index 0c10d42d..20cfb9f8 100644 --- a/include/etl/list.h +++ b/include/etl/list.h @@ -1606,9 +1606,29 @@ namespace etl } //************************************************************************* - /// Sort using in-place merge sort algorithm. - /// Uses a supplied predicate function or functor. - /// This is not my algorithm. I got it off the web somewhere. + /// Stable sort using in-place merge sort algorithm. + /// Copyright 2001 Simon Tatham. + /// + /// 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 SIMON TATHAM 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. //************************************************************************* template void sort(TCompare compare) diff --git a/include/etl/stl/alternate/algorithm.h b/include/etl/stl/alternate/algorithm.h index 849b39a2..b1f496df 100644 --- a/include/etl/stl/alternate/algorithm.h +++ b/include/etl/stl/alternate/algorithm.h @@ -691,6 +691,7 @@ namespace etlstd return private_heap::is_heap(first, last - first, compare); } + //*************************************************************************** // Search template TIterator1 search(TIterator1 first, TIterator1 last, TIterator2 search_first, TIterator2 search_last, TCompare compare) @@ -735,6 +736,30 @@ namespace etlstd return etlstd::search(first, last, search_first, search_last, compare()); } + + //*************************************************************************** + // Rotate + template + TIterator rotate(TIterator first, TIterator middle, TIterator last) + { + TIterator next = middle; + + while (first != next) + { + etlstd::swap(*first++, *next++); + + if (next == last) + { + next = middle; + } + else if (first == middle) + { + middle = next; + } + } + + return first; + } } #endif diff --git a/include/etl/stl/alternate/iterator.h b/include/etl/stl/alternate/iterator.h index 1b6cf1ca..40a2e339 100644 --- a/include/etl/stl/alternate/iterator.h +++ b/include/etl/stl/alternate/iterator.h @@ -370,6 +370,24 @@ namespace etlstd { return itr.operator +(n); } + + //*************************************************************************** + // Previous + template + TIterator prev(TIterator itr, typename etlstd::iterator_traits::difference_type n = 1) + { + etlstd::advance(itr, -n); + return itr; + } + + //*************************************************************************** + // Next + template + TIterator next(TIterator itr, typename etlstd::iterator_traits::difference_type n = 1) + { + etlstd::advance(itr, n); + return itr; + } } #endif diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 8469f4cc..d01e2084 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -243,8 +243,7 @@ namespace etl ///\ingroup type_traits template struct is_fundamental : integral_constant::value || is_void::value || - is_same::type>::value> {}; + is_same::type>::value> {}; /// is_compound ///\ingroup type_traits @@ -258,25 +257,27 @@ namespace etl /// is_pointer ///\ingroup type_traits - template struct is_pointer : false_type {}; - template struct is_pointer : true_type {}; + template struct is_pointer_helper : false_type {}; + template struct is_pointer_helper : true_type {}; + template struct is_pointer : is_pointer_helper::type> {}; /// is_reference ///\ingroup type_traits - template struct is_reference : false_type {}; - template struct is_reference : true_type {}; + template struct is_reference_helper : false_type {}; + template struct is_reference_helper : true_type {}; + template struct is_reference : is_reference_helper::type> {}; /// is_pod /// For C++03, only fundamental and pointers types are recognised. ///\ingroup type_traits -#if (ETL_CPP11_SUPPORTED && !defined(ARDUINO) && !defined(ETL_STLPORT)) && !defined(ETL_IN_UNIT_TEST) && !defined(ETL_NO_STL) +#if (ETL_CPP11_SUPPORTED && !defined(ARDUINO) && !defined(ETL_STLPORT)) && !defined(IN_TYPE_TRAITS_TEST) && !defined(ETL_NO_STL) // For compilers that support C++11 template struct is_pod : std::is_pod {}; #else template struct is_pod : etl::integral_constant::value || etl::is_pointer::value> {}; #endif -#if (ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED) && !defined(ETL_STLPORT) && !defined(ETL_IN_UNIT_TEST) && !defined(ETL_NO_STL) +#if (ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED) && !defined(ETL_STLPORT) && !defined(IN_TYPE_TRAITS_TEST) && !defined(ETL_NO_STL) /// is_trivially_constructible ///\ingroup type_traits template struct is_trivially_constructible : std::is_trivially_constructible {}; @@ -292,6 +293,10 @@ namespace etl /// is_trivially_copy_assignable ///\ingroup type_traits template struct is_trivially_copy_assignable : std::is_trivially_copy_assignable {}; + + /// is_trivially_copyable + ///\ingroup type_traits + template struct is_trivially_copyable : std::is_trivially_copyable {}; #else /// is_trivially_constructible /// For C++03, only POD types are recognised. @@ -312,6 +317,11 @@ namespace etl /// For C++03, only POD types are recognised. ///\ingroup type_traits template struct is_trivially_copy_assignable : etl::is_pod {}; + + /// is_trivially_copyable + /// For C++03, only POD types are recognised. + ///\ingroup type_traits + template struct is_trivially_copyable : etl::is_pod {}; #endif #if ETL_CPP11_SUPPORTED diff --git a/include/etl/vector.h b/include/etl/vector.h index cd7e0373..02e2a2d1 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -575,7 +575,7 @@ namespace etl #endif //************************************************************************* - /// Emplaces a value to the vextor at the specified position. + /// Emplaces a value to the vector at the specified position. //************************************************************************* #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) template diff --git a/temp/.gitignore b/temp/.gitignore new file mode 100644 index 00000000..8e1feeee --- /dev/null +++ b/temp/.gitignore @@ -0,0 +1 @@ +/Containers - Supporting rvalue references.txt diff --git a/temp/message_router.h b/temp/message_router.h deleted file mode 100644 index 85d95fe0..00000000 --- a/temp/message_router.h +++ /dev/null @@ -1,984 +0,0 @@ -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2017 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_MESSAGE_ROUTER__ -#define __ETL_MESSAGE_ROUTER__ - -#include - -namespace etl -{ - /// Allow alternative type for message id. -#if !defined(ETL_MESSAGE_ID_TYPE) - typedef uint_least8_t message_id_t; -#else - typedef ETL_MESSAGE_ID_TYPE message_id_t; -#endif - - //*************************************************************************** - class imessage - { - public: - - virtual ~imessage() {} - virtual etl::message_id_t get_message_id() const = 0; - }; - - //*************************************************************************** - template - class message : public imessage - { - public: - - enum - { - ID = ID_ - }; - - //******************************************* - etl::message_id_t get_message_id() const - { - return etl::message_id_t(ID); - } - }; - - //*************************************************************************** - class imessage_router - { - public: - - virtual ~imessage_router() {} - virtual void receive(const etl::imessage& message) = 0; - virtual void receive(imessage_router& source, const etl::imessage& message) = 0; - virtual bool accepts(etl::message_id_t id) const = 0; - - //******************************************* - bool accepts(const etl::imessage& msg) const - { - return accepts(msg.get_message_id()); - } - - //******************************************* - void send_message(imessage_router& destination, - const etl::imessage& message) - { - destination.receive(*this, message); - } - }; - - //*************************************************************************** - /// This router can be used either as a sink for messages - /// or as a producer-only of messages such an interrupt routine. - //*************************************************************************** - class null_message_router : public imessage_router - { - public: - - //******************************************* - void receive(const etl::imessage& message) - { - } - - //******************************************* - void receive(etl::imessage_router& source, const etl::imessage& message) - { - } - - //******************************************* - bool accepts(etl::message_id_t id) const - { - return false; - } - - //******************************************* - static null_message_router& get() - { - static null_message_router instance; - return instance; - } - }; - - //*************************************************************************** - /// Send a message to a router. - /// Sets the 'sender' to etl::null_message_router type. - //*************************************************************************** - inline static void send_message(etl::imessage_router& destination, - const etl::imessage& message) - { - destination.receive(message); - } - - //*************************************************************************** - /// Send a message to a router. - //*************************************************************************** - inline static void send_message(etl::imessage_router& source, - etl::imessage_router& destination, - const etl::imessage& message) - { - destination.receive(source, message); - } - - //*************************************************************************** - // To generate to header file, run this at the command line. - // Note: You will need Python and COG installed. - // - // python -m cogapp -d -e -omessage_router.h -DHandlers= message_router_generator.h - // Where is the number of messages to support. - // - // e.g. - // To generate handlers for up to 16 messages... - // python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h - // - // See CreateMessageProcessor.bat - //*************************************************************************** - - //*************************************************************************** - // The code below has been auto generated. Do not manually edit. - //*************************************************************************** - - //*************************************************************************** - // The definition for all 16 message types. - //*************************************************************************** - template - class message_router : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const etl::message_id_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T11::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T12::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T13::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T14::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T15::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T16::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: case T16::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 15 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T11::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T12::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T13::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T14::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T15::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 14 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T11::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T12::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T13::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T14::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 13 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T11::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T12::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T13::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 12 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T11::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T12::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 11 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T11::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 10 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 9 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 8 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 7 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 6 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 5 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 4 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 3 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: case T3::ID: - return true; break; - default: - return false; break; - } - } - - class message_packet - { - public: - - explicit message_packet(const imessage& msg) - { - const etl::message_id_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: new (&storage) T1(static_cast(msg)); break; - case T2::ID: new (&storage) T2(static_cast(msg)); break; - case T3::ID: new (&storage) T3(static_cast(msg)); break; - default: break; - } - } - - ~message_packet() - { - static_cast(storage).~imessage(); - } - - message_packet(const message_packet& other) - { - const etl::message_id_t id = other.get_imessage().get_message_id(); - - switch (id) - { - case T1::ID: new (&storage) T1(static_cast(msg)); break; - case T2::ID: new (&storage) T2(static_cast(msg)); break; - case T3::ID: new (&storage) T3(static_cast(msg)); break; - default: break; - } - } - - message_packet& operator = (const message_packet& other) - { - if (this != &other) - { - static_cast(storage).~imessage(); - new (this) message_packet(other); - } - } - - const etl::imessage& get_imessage() const - { - return *reiniterpret_cast(storage); - } - - operator const imessage&() const - { - return get_imessage(); - } - - private: - - etl::aligned_storage::size, etl::largest_alignment::value>::type storage; - }; - }; - - //*************************************************************************** - // Specialisation for 2 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: case T2::ID: - return true; break; - default: - return false; break; - } - } - }; - - //*************************************************************************** - // Specialisation for 1 message type. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - void receive(const etl::imessage& msg) - { - receive(etl::null_message_router::get(), msg); - } - - void receive(etl::imessage_router& source, const etl::imessage& msg) - { - const size_t id = msg.get_message_id(); - - switch (id) - { - case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; - } - } - - bool accepts(etl::message_id_t id) const - { - switch (id) - { - case T1::ID: - return true; break; - default: - return false; break; - } - } - }; -} - -#endif diff --git a/test/codeblocks/ETL.cbp b/test/codeblocks/ETL.cbp index 6d92c017..fe5176f4 100644 --- a/test/codeblocks/ETL.cbp +++ b/test/codeblocks/ETL.cbp @@ -211,6 +211,7 @@ + @@ -393,6 +394,7 @@ + diff --git a/test/data.h b/test/data.h index f6b59b7a..972aff3c 100644 --- a/test/data.h +++ b/test/data.h @@ -77,6 +77,11 @@ public: return !(value < other.value); } + static bool are_identical(const TestDataDC& lhs, const TestDataDC& rhs) + { + return (lhs.value == rhs.value) && (lhs.index == rhs.index); + } + T value; int index; }; @@ -137,6 +142,11 @@ public: return !(value < other.value); } + static bool are_identical(const TestDataNDC& lhs, const TestDataNDC& rhs) + { + return (lhs.value == rhs.value) && (lhs.index == rhs.index); + } + T value; int index; }; diff --git a/test/etl_profile.h b/test/etl_profile.h index 578de812..f89b86cd 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -70,6 +70,7 @@ SOFTWARE. #define ETL_POLYMORPHIC_STRINGS #define ETL_POLYMORPHIC_POOL #define ETL_POLYMORPHIC_VECTOR +#define ETL_POLYMORPHIC_INDIRECT_VECTOR //#define ETL_POLYMORPHIC_CONTAINERS diff --git a/test/test_algorithm.cpp b/test/test_algorithm.cpp index 58f97af9..fad3eb08 100644 --- a/test/test_algorithm.cpp +++ b/test/test_algorithm.cpp @@ -31,6 +31,8 @@ SOFTWARE. #include "etl/algorithm.h" #include "etl/container.h" +#include "data.h" + #include #include #include @@ -40,6 +42,7 @@ SOFTWARE. namespace { + using NDC = TestDataNDC; std::random_device rng; std::mt19937 urng(rng()); @@ -914,6 +917,108 @@ namespace } } + //========================================================================= + TEST(stable_sort_default) + { + std::vector initial_data = { NDC(1, 1), NDC(2, 1), NDC(3, 1), NDC(2, 2), NDC(3, 2), NDC(4, 1), NDC(2, 3), NDC(3, 3), NDC(5, 1) }; + + std::vector data1(initial_data); + std::vector data2(initial_data); + + std::stable_sort(data1.begin(), data1.end()); + etl::stable_sort(data2.begin(), data2.end()); + + bool is_same = std::equal(data1.begin(), data1.end(), data2.begin(), NDC::are_identical); + CHECK(is_same); + } + + //========================================================================= + TEST(stable_sort_greater) + { + std::vector initial_data = { NDC(1, 1), NDC(2, 1), NDC(3, 1), NDC(2, 2), NDC(3, 2), NDC(4, 1), NDC(2, 3), NDC(3, 3), NDC(5, 1) }; + + std::vector data1(initial_data); + std::vector data2(initial_data); + + std::stable_sort(data1.begin(), data1.end(), std::greater()); + etl::stable_sort(data2.begin(), data2.end(), std::greater()); + + bool is_same = std::equal(data1.begin(), data1.end(), data2.begin(), NDC::are_identical); + CHECK(is_same); + } + + //========================================================================= + TEST(shell_sort_default) + { + std::vector data(100, 0); + std::iota(data.begin(), data.end(), 1); + + for (int i = 0; i < 100; ++i) + { + std::shuffle(data.begin(), data.end(), urng); + + std::vector data1 = data; + std::vector data2 = data; + + std::sort(data1.begin(), data1.end()); + etl::shell_sort(data2.begin(), data2.end()); + + bool is_same = std::equal(data1.begin(), data1.end(), data2.begin()); + CHECK(is_same); + } + } + + //========================================================================= + TEST(shell_sort_greater) + { + std::vector data(100, 0); + std::iota(data.begin(), data.end(), 1); + + for (int i = 0; i < 100; ++i) + { + std::shuffle(data.begin(), data.end(), urng); + + std::vector data1 = data; + std::vector data2 = data; + + std::sort(data1.begin(), data1.end(), std::greater()); + etl::shell_sort(data2.begin(), data2.end(), std::greater()); + + bool is_same = std::equal(data1.begin(), data1.end(), data2.begin()); + CHECK(is_same); + } + } + + //========================================================================= + TEST(insertion_sort_default) + { + std::vector initial_data = { NDC(1, 1), NDC(2, 1), NDC(3, 1), NDC(2, 2), NDC(3, 2), NDC(4, 1), NDC(2, 3), NDC(3, 3), NDC(5, 1) }; + + std::vector data1(initial_data); + std::vector data2(initial_data); + + std::stable_sort(data1.begin(), data1.end()); + etl::insertion_sort(data2.begin(), data2.end()); + + bool is_same = std::equal(data1.begin(), data1.end(), data2.begin(), NDC::are_identical); + CHECK(is_same); + } + + //========================================================================= + TEST(insertion_sort_greater) + { + std::vector initial_data = { NDC(1, 1), NDC(2, 1), NDC(3, 1), NDC(2, 2), NDC(3, 2), NDC(4, 1), NDC(2, 3), NDC(3, 3), NDC(5, 1) }; + + std::vector data1(initial_data); + std::vector data2(initial_data); + + std::stable_sort(data1.begin(), data1.end(), std::greater()); + etl::insertion_sort(data2.begin(), data2.end(), std::greater()); + + bool is_same = std::equal(data1.begin(), data1.end(), data2.begin(), NDC::are_identical); + CHECK(is_same); + } + //========================================================================= TEST(multimax) { diff --git a/test/test_indirect_vector.cpp b/test/test_indirect_vector.cpp new file mode 100644 index 00000000..691d8873 --- /dev/null +++ b/test/test_indirect_vector.cpp @@ -0,0 +1,1581 @@ +///****************************************************************************** +//The MIT License(MIT) +// +//Embedded Template Library. +//https://github.com/ETLCPP/etl +//https://www.etlcpp.com +// +//Copyright(c) 2019 jwellbelove +// +//Permission is hereby granted, free of charge, to any person obtaining a copy +//of this software and associated documentation files(the "Software"), to deal +//in the Software without restriction, including without limitation the rights +//to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +//copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions : +// +//The above copyright notice and this permission notice shall be included in all +//copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +//SOFTWARE. +//******************************************************************************/ + +#include "UnitTest++.h" + +#include +#include +#include +#include + +#include "etl/indirect_vector.h" +#include "data.h" + +namespace +{ + SUITE(test_indirect_vector) + { + static const size_t SIZE = 12; + + typedef TestDataNDC NDC; + typedef TestDataDC DC; + + static NDC ndc("NDC"); + + typedef etl::indirect_vector DataNDC; + typedef etl::iindirect_vector IDataNDC; + typedef std::vector CompareDataNDC; + + typedef etl::indirect_vector DataDC; + typedef etl::iindirect_vector IDataDC; + typedef std::vector CompareDataDC; + + CompareDataNDC initial_data; + CompareDataNDC less_data; + CompareDataNDC greater_data; + CompareDataNDC shorter_data; + CompareDataNDC different_data; + CompareDataNDC insert_data; + CompareDataNDC ordered_data; + CompareDataNDC part_ordered_data; + CompareDataNDC part_reverse_ordered_data; + CompareDataNDC stable_default_ordered_data; + CompareDataNDC stable_reverse_ordered_data; + CompareDataNDC stable_greater_ordered_data; + CompareDataNDC stable_greater_reverse_ordered_data; + CompareDataNDC unordered_data; + CompareDataNDC stable_part_ordered_data; + CompareDataNDC stable_part_greater_ordered_data; + + //************************************************************************* + struct SetupFixture + { + SetupFixture() + { + NDC n[] = { NDC("0"), NDC("1"), NDC("2"), NDC("3"), NDC("4"), NDC("4"), NDC("4"), NDC("5"), NDC("6"), NDC("7"), NDC("8"), NDC("9") }; + NDC n_insert[] = { NDC("11"), NDC("12"), NDC("13") }; + NDC n_less[] = { NDC("0"), NDC("1"), NDC("2"), NDC("3"), NDC("4"), NDC("4"), NDC("4"), NDC("5"), NDC("6"), NDC("7"), NDC("8"), NDC("9") }; + NDC n_greater[] = { NDC("0"), NDC("1"), NDC("2"), NDC("4"), NDC("4"), NDC("4"), NDC("4"), NDC("5"), NDC("6"), NDC("7"), NDC("8"), NDC("9") }; + + NDC n_unordered[] = { NDC("1"), NDC("4", 1), NDC("7"), NDC("4", 2), NDC("2"), NDC("4", 3), NDC("3"), NDC("6"), NDC("9"), NDC("0"), NDC("8"), NDC("5") }; + + NDC n_ordered[] = { NDC("0"), NDC("1"), NDC("2"), NDC("3"), NDC("4"), NDC("4"), NDC("4"), NDC("5"), NDC("6"), NDC("7"), NDC("8"), NDC("9") }; + NDC n_stable_default_ordered[] = { NDC("0"), NDC("1"), NDC("2"), NDC("3"), NDC("4", 1), NDC("4", 2), NDC("4", 3), NDC("5"), NDC("6"), NDC("7"), NDC("8"), NDC("9") }; + NDC n_stable_reverse_ordered[] = { NDC("0"), NDC("1"), NDC("2"), NDC("3"), NDC("4", 3), NDC("4", 2), NDC("4", 1), NDC("5"), NDC("6"), NDC("7"), NDC("8"), NDC("9") }; + NDC n_stable_greater_ordered[] = { NDC("9"), NDC("8"), NDC("7"), NDC("6"), NDC("5"), NDC("4", 1), NDC("4", 2), NDC("4", 3), NDC("3"), NDC("2"), NDC("1"), NDC("0") }; + NDC n_stable_greater_reverse_ordered_data[] = { NDC("9"), NDC("8"), NDC("7"), NDC("6"), NDC("5"), NDC("4", 3), NDC("4", 2), NDC("4", 1), NDC("3"), NDC("2"), NDC("1"), NDC("0") }; + + NDC n_part_ordered[] = { NDC("1"), NDC("4", 1), NDC("0"), NDC("2"), NDC("3"), NDC("4"), NDC("4"), NDC("6"), NDC("7"), NDC("9"), NDC("8"), NDC("5") }; + NDC n_part_reverse_ordered[] = { NDC("1"), NDC("4"), NDC("9"), NDC("7"), NDC("6"), NDC("4"), NDC("4"), NDC("3"), NDC("2"), NDC("0"), NDC("8"), NDC("5") }; + + NDC n_stable_part_ordered[] = { NDC("1"), NDC("4", 1), NDC("0"), NDC("2"), NDC("3"), NDC("4", 2), NDC("4", 3), NDC("6"), NDC("7"), NDC("9"), NDC("8"), NDC("5") }; + NDC n_stable_part_greater_ordered[] = { NDC("1"), NDC("4", 1), NDC("9"), NDC("7"), NDC("6"), NDC("4", 2), NDC("4", 3), NDC("3"), NDC("2"), NDC("0"), NDC("8"), NDC("5") }; + + + initial_data.assign(std::begin(n), std::end(n)); + insert_data.assign(std::begin(n_insert), std::end(n_insert)); + less_data.assign(std::begin(n_less), std::end(n_less)); + greater_data.assign(std::begin(n_greater), std::end(n_greater)); + shorter_data.assign(std::begin(n_greater), std::end(n_greater) - 1); + different_data.assign(initial_data.rbegin(), initial_data.rend()); + ordered_data.assign(std::begin(n_ordered), std::end(n_ordered)); + part_ordered_data.assign(std::begin(n_part_ordered), std::end(n_part_ordered)); + part_reverse_ordered_data.assign(std::begin(n_part_reverse_ordered), std::end(n_part_reverse_ordered)); + unordered_data.assign(std::begin(n_unordered), std::end(n_unordered)); + stable_default_ordered_data.assign(std::begin(n_stable_default_ordered), std::end(n_stable_default_ordered)); + stable_reverse_ordered_data.assign(std::begin(n_stable_reverse_ordered), std::end(n_stable_reverse_ordered)); + stable_greater_ordered_data.assign(std::begin(n_stable_greater_ordered), std::end(n_stable_greater_ordered)); + stable_greater_reverse_ordered_data.assign(std::begin(n_stable_greater_reverse_ordered_data), std::end(n_stable_greater_reverse_ordered_data)); + stable_part_ordered_data.assign(std::begin(n_stable_part_ordered), std::end(n_stable_part_ordered)); + stable_part_greater_ordered_data.assign(std::begin(n_stable_part_greater_ordered), std::end(n_stable_part_greater_ordered)); + } + }; + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_default_constructor) + { + DataDC data; + + CHECK_EQUAL(data.size(), size_t(0)); + CHECK(data.empty()); + CHECK_EQUAL(data.capacity(), SIZE); + CHECK_EQUAL(data.max_size(), SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_destruct_via_ivector) + { + const size_t INITIAL_SIZE = 5; + const NDC INITIAL_VALUE("1"); + + int current_count = NDC::get_instance_count(); + + DataNDC* p = new DataNDC(INITIAL_SIZE, INITIAL_VALUE); + delete p; + + DataNDC* pdata = new DataNDC(INITIAL_SIZE, INITIAL_VALUE); + CHECK_EQUAL(int(current_count + INITIAL_SIZE), NDC::get_instance_count()); + + IDataNDC* pidata = pdata; + delete pidata; + CHECK_EQUAL(current_count, NDC::get_instance_count()); + } + + //************************************************************************* + TEST(test_iterator_comparison_empty) + { + DataDC data; + + CHECK(data.begin() == data.end()); + CHECK(data.cbegin() == data.cend()); + CHECK(data.rbegin() == data.rend()); + CHECK(data.crbegin() == data.crend()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size) + { + const size_t INITIAL_SIZE = 5; + DataDC data(INITIAL_SIZE); + + CHECK(data.size() == INITIAL_SIZE); + CHECK(!data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size_value) + { + const size_t INITIAL_SIZE = 5; + const NDC INITIAL_VALUE("1"); + + std::vector compare_data(INITIAL_SIZE, INITIAL_VALUE); + DataNDC data(size_t(5), NDC("1")); + + CHECK(data.size() == INITIAL_SIZE); + CHECK(!data.empty()); + + bool is_equal = std::equal(data.begin(), + data.end(), + compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_size_excess) + { + CHECK_THROW(DataDC data(SIZE + 1), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_constructor_range) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + + DataNDC data(compare_data.begin(), compare_data.end()); + + CHECK(data.size() == SIZE); + CHECK(!data.empty()); + } + + //************************************************************************* + TEST(test_constructor_initializer_list) + { + CompareDataNDC compare_data = { NDC("0"), NDC("1"), NDC("2"), NDC("3") }; + DataNDC data = { NDC("0"), NDC("1"), NDC("2"), NDC("3") }; + + CHECK_EQUAL(compare_data.size(), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_constructor) + { + DataNDC data(initial_data.begin(), initial_data.end()); + DataNDC data2(data); + CHECK(data2 == data); + + data2[2] = NDC("X"); + CHECK(data2 != data); + } + + //************************************************************************* + TEST(test_move_constructor) + { + const size_t SIZE = 10U; + typedef etl::indirect_vector, SIZE> Data; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr 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)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(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) + { + DataNDC data(initial_data.begin(), initial_data.end()); + DataNDC other_data; + + other_data = data; + + bool is_equal = std::equal(data.begin(), + data.end(), + other_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST(test_move_assignment) + { + const size_t SIZE = 10U; + typedef etl::indirect_vector, SIZE> Data; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr 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)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(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) + { + DataNDC data1(initial_data.begin(), initial_data.end()); + DataNDC data2; + + IDataNDC& idata1 = data1; + IDataNDC& idata2 = data2; + + idata2 = idata1; + + bool is_equal = std::equal(data1.begin(), + data1.end(), + data2.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST(test_move_assignment_interface) + { + const size_t SIZE = 10U; + typedef etl::indirect_vector, SIZE> Data; + typedef etl::iindirect_vector> IData; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr 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) + { + DataNDC data(initial_data.begin(), initial_data.end()); + DataNDC other_data(data); + + other_data = other_data; + + bool is_equal = std::equal(data.begin(), + data.end(), + other_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_begin) + { + DataDC data(10); + const DataDC constData(10); + + CHECK_EQUAL(&data[0], &(*data.begin())); + CHECK_EQUAL(&constData[0], &(*constData.begin())); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_end) + { + DataDC data(10); + const DataDC constData(10); + + CHECK_EQUAL(&data[10], &(*data.end())); + CHECK_EQUAL(&constData[10], &(constData.end())); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_up) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 8; + + DataDC data(INITIAL_SIZE); + data.resize(NEW_SIZE); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_up_value) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 8; + const NDC INITIAL_VALUE("1"); + + DataNDC data(INITIAL_SIZE, INITIAL_VALUE); + data.resize(NEW_SIZE, INITIAL_VALUE); + + std::vector compare_data(NEW_SIZE, INITIAL_VALUE); + + 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_resize_excess) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = SIZE + 1; + + DataDC data(INITIAL_SIZE); + + CHECK_THROW(data.resize(NEW_SIZE), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_down) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 2; + + DataDC data(INITIAL_SIZE); + data.resize(NEW_SIZE); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_resize_down_value) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 2; + const NDC INITIAL_VALUE("1"); + + DataNDC data(INITIAL_SIZE, INITIAL_VALUE); + data.resize(NEW_SIZE, INITIAL_VALUE); + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_empty) + { + DataDC data; + data.resize(data.max_size()); + + CHECK(data.full()); + CHECK(!data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_full) + { + DataNDC data; + + CHECK(!data.full()); + CHECK(data.empty()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_index) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + + DataNDC data(compare_data.begin(), compare_data.end()); + + for (size_t i = 0; i < data.size(); ++i) + { + CHECK_EQUAL(data[i], compare_data[i]); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_index_const) + { + const CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + + const DataNDC data(compare_data.begin(), compare_data.end()); + + for (size_t i = 0; i < data.size(); ++i) + { + CHECK_EQUAL(data[i], compare_data[i]); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_at) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + DataNDC data(initial_data.begin(), initial_data.end()); + + for (size_t i = 0; i < data.size(); ++i) + { + CHECK_EQUAL(data.at(i), compare_data.at(i)); + } + + CHECK_THROW(data.at(data.size()), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_at_const) + { + const CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + const DataNDC data(initial_data.begin(), initial_data.end()); + + for (size_t i = 0; i < data.size(); ++i) + { + CHECK_EQUAL(data.at(i), compare_data.at(i)); + } + + CHECK_THROW(data.at(data.size()), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_front) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + DataNDC data(initial_data.begin(), initial_data.end()); + + CHECK(data.front() == compare_data.front()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_front_const) + { + const CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + const DataNDC data(initial_data.begin(), initial_data.end()); + + CHECK(data.front() == compare_data.front()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_back) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + DataNDC data(initial_data.begin(), initial_data.end()); + + CHECK(data.back() == compare_data.back()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_back_const) + { + const CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + const DataNDC data(initial_data.begin(), initial_data.end()); + + CHECK(data.back() == compare_data.back()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_data) + { + DataNDC data(initial_data.begin(), initial_data.end()); + + DataNDC::indirect_pointer p = data.data(); + + for (size_t i = 0U; i < data.size(); ++i) + { + CHECK(data[i] == **p); + ++p; + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_data_const) + { + const DataNDC data(initial_data.begin(), initial_data.end()); + + DataNDC::indirect_const_pointer p = data.data(); + + for (size_t i = 0U; i < data.size(); ++i) + { + CHECK(data[i] == **p); + ++p; + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assign_range) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + + DataNDC data; + + data.assign(compare_data.begin(), compare_data.end()); + + 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_assign_size_value) + { + const size_t INITIAL_SIZE = 5; + const NDC INITIAL_VALUE("1"); + std::vector compare_data(INITIAL_SIZE, INITIAL_VALUE); + + DataNDC data; + data.assign(INITIAL_SIZE, INITIAL_VALUE); + + 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_assign_size_value_excess) + { + const size_t INITIAL_SIZE = SIZE; + const size_t EXCESS_SIZE = SIZE + 1; + const NDC INITIAL_VALUE("1"); + std::vector compare_data(INITIAL_SIZE, INITIAL_VALUE); + + DataNDC data; + + CHECK_THROW(data.assign(EXCESS_SIZE, INITIAL_VALUE), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_push_back) + { + CompareDataNDC compare_data; + DataNDC data; + + for (size_t i = 0; i < SIZE; ++i) + { + std::string value(" "); + value[0] = char('A' + i); + compare_data.push_back(NDC(value)); + data.push_back(NDC(value)); + } + + 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) + { + DataNDC data; + + for (size_t i = 0; i < SIZE; ++i) + { + std::string value(" "); + value[0] = char('A' + i); + data.push_back(NDC(value)); + } + + CHECK_THROW(data.push_back(NDC("Z")), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back) + { + CompareDataNDC compare_data; + DataNDC data; + + for (size_t i = 0; i < SIZE; ++i) + { + std::string value(" "); + value[0] = char('A' + i); + compare_data.emplace_back(value); + data.emplace_back(value); + } + + 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_unique_ptr) + { + etl::indirect_vector, SIZE> data; + + std::unique_ptr p1(new int(1)); + std::unique_ptr p2(new int(2)); + std::unique_ptr p3(new int(3)); + std::unique_ptr 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::indirect_vector 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::indirect_vector, SIZE> data; + + std::unique_ptr p1(new int(1)); + std::unique_ptr p2(new int(2)); + std::unique_ptr p3(new int(3)); + std::unique_ptr 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) + { + class Data + { + public: + std::string a; + size_t b; + double c; + const char *d; + Data(std::string w) : a(w), b(0), c(0.0), d(0){} + Data(std::string w, size_t x) : a(w), b(x), c(0.0), d(0){} + Data(std::string w, size_t x, double y) : a(w), b(x), c(y), d(0){} + Data(std::string w, size_t x, double y, const char *z) : a(w), b(x), c(y), d(z){} + bool operator == (const Data &other) const + { + return (a == other.a) && (b == other.b) && (c == other.c) && (d == other.d); + } + }; + + std::vector compare_data; + etl::indirect_vector data; + + std::string s; + for (size_t i = 0; i < SIZE; ++i) + { + s += "x"; + + // 4 arguments + compare_data.emplace_back(s, i, static_cast(i) + 0.1234, "emplace_back"); + data.emplace_back(s, i, static_cast(i) + 0.1234, "emplace_back"); + + // 3 arguments + compare_data.emplace_back(s, i, static_cast(i) + 0.1234); + data.emplace_back(s, i, static_cast(i) + 0.1234); + + // 2 arguments + compare_data.emplace_back(s, i); + data.emplace_back(s, i); + + // 1 argument + compare_data.emplace_back(s); + data.emplace_back(s); + } + + CHECK_EQUAL(compare_data.size(), data.size()); + + const bool is_equal = std::equal(data.begin(), + data.end(), + compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + // The C++11 variadic version uses non-const rvalue references so has the ability + // to emplace non-const reference members, the pre-C++11 const reference overloads + // does not have the ability to pass const reference parameters to non-const + // constructor parameters (like the members in Data below) + // So this is only tested on C++11 onwards + TEST_FIXTURE(SetupFixture, test_emplace_back_non_const_references) + { +#if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_VECTOR_FORCE_CPP03) + class Data + { + public: + std::string &a; + size_t &b; + double &c; + const char *d; + Data(std::string &w, size_t &x, double &y, const char *z) : a(w), b(x), c(y), d(z){} + bool operator == (const Data &other) const + { + return (a == other.a) && (b == other.b) && (c == other.c) && (d == other.d); + } + }; + + std::vector compare_data; + etl::indirect_vector data; + + std::string a = "test_test_test"; + size_t b = 9999; + double c = 123.456; + const char *d = "abcdefghijklmnopqrstuvwxyz"; + for (size_t i = 0; i < SIZE; ++i) + { + data.emplace_back(a, b, c, d); + compare_data.emplace_back(a, b, c, d); + } + + CHECK_EQUAL(compare_data.size(), data.size()); + + const bool is_equal = std::equal(data.begin(), + data.end(), + compare_data.begin()); + + CHECK(is_equal); +#endif + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_pop_back) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + DataNDC data(initial_data.begin(), initial_data.end()); + + compare_data.pop_back(); + compare_data.pop_back(); + + data.pop_back(); + data.pop_back(); + + 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_pop_back_exception) + { + DataDC data; + + data.resize(2); + + data.pop_back(); + data.pop_back(); + + CHECK_THROW(data.pop_back(), etl::vector_empty); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value) + { + const size_t INITIAL_SIZE = 5; + const NDC INITIAL_VALUE("1"); + + for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset) + { + CompareDataNDC compare_data; + DataNDC data; + + data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + compare_data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + + data.insert(data.begin() + offset, INITIAL_VALUE); + compare_data.insert(compare_data.begin() + offset, INITIAL_VALUE); + + 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_emplace_position_value) + { + const size_t INITIAL_SIZE = 5; + const std::string INITIAL_VALUE("1"); + + for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset) + { + CompareDataNDC compare_data; + DataNDC data; + + data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + compare_data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + + data.emplace(data.begin() + offset, INITIAL_VALUE); + compare_data.emplace(compare_data.begin() + offset, INITIAL_VALUE); + + 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_insert_position_value_excess) + { + const size_t INITIAL_SIZE = SIZE; + const NDC INITIAL_VALUE("1"); + const NDC UNINITIALISED_VALUE("Z"); + + DataNDC data(INITIAL_SIZE, INITIAL_VALUE); + + size_t offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, INITIAL_VALUE), etl::vector_full); + + offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, INITIAL_VALUE), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, INITIAL_VALUE), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value) + { + const size_t INITIAL_SIZE = 5; + const size_t INSERT_SIZE = 3; + const NDC INITIAL_VALUE("1"); + + for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset) + { + CompareDataNDC compare_data; + DataNDC data; + + data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + compare_data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + data.insert(data.begin() + offset, INSERT_SIZE, INITIAL_VALUE); + compare_data.insert(compare_data.begin() + offset, INSERT_SIZE, INITIAL_VALUE); + + 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_insert_position_n_value_excess) + { + const size_t INITIAL_SIZE = SIZE; + const size_t INSERT_SIZE = 4; + const NDC INITIAL_VALUE("1"); + + DataNDC data(INITIAL_SIZE, INITIAL_VALUE); + + size_t offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, INITIAL_VALUE), etl::vector_full); + + offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, INITIAL_VALUE), etl::vector_full); + + offset = 4; + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, INITIAL_VALUE), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, INSERT_SIZE, INITIAL_VALUE), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range) + { + const size_t INITIAL_SIZE = 5; + const NDC INITIAL_VALUE("1"); + + for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset) + { + CompareDataNDC compare_data; + DataNDC data; + + data.resize(SIZE, NDC("Z")); + + data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + compare_data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + data.insert(data.begin() + offset, insert_data.begin(), insert_data.end()); + compare_data.insert(compare_data.begin() + offset, insert_data.begin(), insert_data.end()); + + 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_insert_position_range_excess) + { + const size_t INITIAL_SIZE = 5; + const NDC INITIAL_VALUE("1"); + + DataNDC data(INITIAL_SIZE, INITIAL_VALUE); + + size_t offset = 0; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = 2; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = 4; + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + + offset = data.size(); + + CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + DataNDC data(initial_data.begin(), initial_data.end()); + + compare_data.erase(compare_data.begin() + 2); + + data.erase(data.begin() + 2); + + 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_erase_range) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + DataNDC data(initial_data.begin(), initial_data.end()); + + compare_data.erase(compare_data.begin() + 2, compare_data.begin() + 4); + + data.erase(data.begin() + 2, data.begin() + 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_clear) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + + DataNDC data(compare_data.begin(), compare_data.end()); + data.clear(); + + CHECK_EQUAL(data.size(), size_t(0)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_iterator) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + + DataNDC data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.begin(), + data.end(), + compare_data.begin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_iterator) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + + DataNDC data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.cbegin(), + data.cend(), + compare_data.cbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_reverse_iterator) + { + CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + + DataNDC data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.rbegin(), + data.rend(), + compare_data.rbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_reverse_iterator) + { + const CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + + const DataNDC data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.crbegin(), + data.crend(), + compare_data.crbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_const_reverse_iterator2) + { + const CompareDataNDC compare_data(initial_data.begin(), initial_data.end()); + + const DataNDC data(compare_data.begin(), compare_data.end()); + + bool is_equal = std::equal(data.rbegin(), + data.rend(), + compare_data.rbegin()); + + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_equal) + { + const DataNDC initial1(initial_data.begin(), initial_data.end()); + const DataNDC initial2(initial_data.begin(), initial_data.end()); + + CHECK(initial1 == initial2); + + const DataNDC different(different_data.begin(), different_data.end()); + + CHECK(!(initial1 == different)); + + const DataNDC shorter(shorter_data.begin(), shorter_data.end()); + + CHECK(!(shorter == initial1)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_not_equal) + { + const DataNDC initial1(initial_data.begin(), initial_data.end()); + const DataNDC initial2(initial_data.begin(), initial_data.end()); + + CHECK(!(initial1 != initial2)); + + const DataNDC different(different_data.begin(), different_data.end()); + + CHECK(initial1 != different); + + const DataNDC shorter(shorter_data.begin(), shorter_data.end()); + + CHECK(shorter != initial1); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_less_than) + { + const DataNDC less(less_data.begin(), less_data.end()); + const DataNDC initial(initial_data.begin(), initial_data.end()); + + CHECK((less < initial) == (less_data < initial_data)); + + const DataNDC greater(greater_data.begin(), greater_data.end()); + + CHECK((greater < initial) == (greater_data < initial_data)); + + const DataNDC shorter(shorter_data.begin(), shorter_data.end()); + + CHECK((shorter < initial) == (shorter_data < initial_data)); + CHECK((initial < shorter) == (initial_data < shorter_data)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_less_than_or_equal) + { + const DataNDC less(less_data.begin(), less_data.end()); + const DataNDC initial(initial_data.begin(), initial_data.end()); + + CHECK((less <= initial) == (less_data <= initial_data)); + + const DataNDC greater(greater_data.begin(), greater_data.end()); + + CHECK((greater <= initial) == (greater_data <= initial_data)); + + const DataNDC shorter(shorter_data.begin(), shorter_data.end()); + + CHECK((shorter <= initial) == (shorter_data <= initial_data)); + CHECK((initial <= shorter) == (initial_data <= shorter_data)); + + const DataNDC initial2(initial_data.begin(), initial_data.end()); + CHECK((initial <= initial2) == (initial_data <= initial_data)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_greater_than) + { + const DataNDC less(less_data.begin(), less_data.end()); + const DataNDC initial(initial_data.begin(), initial_data.end()); + + CHECK((less > initial) == (less_data > initial_data)); + + const DataNDC greater(greater_data.begin(), greater_data.end()); + + CHECK((greater > initial) == (greater_data > initial_data)); + + const DataNDC shorter(shorter_data.begin(), shorter_data.end()); + + CHECK((shorter > initial) == (shorter_data > initial_data)); + CHECK((initial > shorter) == (initial_data > shorter_data)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_greater_than_or_equal) + { + const DataNDC less(less_data.begin(), less_data.end()); + const DataNDC initial(initial_data.begin(), initial_data.end()); + + CHECK((less >= initial) == (less_data >= initial_data)); + + const DataNDC greater(greater_data.begin(), greater_data.end()); + + CHECK((greater >= initial) == (greater_data >= initial_data)); + + const DataNDC shorter(shorter_data.begin(), shorter_data.end()); + + CHECK((shorter >= initial) == (shorter_data >= initial_data)); + CHECK((initial >= shorter) == (initial_data > shorter_data)); + + const DataNDC initial2(initial_data.begin(), initial_data.end()); + CHECK((initial >= initial2) == (initial_data >= initial_data)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_sort_default_order_from_unordered_std_sort) + { + DataNDC data(unordered_data.begin(), unordered_data.end()); + + std::sort(data.begin(), data.end()); + + bool is_equal = std::equal(data.begin(), + data.end(), + ordered_data.begin()); + + CHECK(is_equal); + CHECK(data.is_sorted()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_sort_default_order_from_unordered_std_stable_sort) + { + DataNDC data(unordered_data.begin(), unordered_data.end()); + + std::stable_sort(data.begin(), data.end()); + + bool is_equal = std::equal(data.begin(), + data.end(), + stable_default_ordered_data.begin(), + NDC::are_identical); + + CHECK(is_equal); + CHECK(data.is_sorted()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_sort_default_order_from_ordered) + { + DataNDC data(ordered_data.begin(), ordered_data.end()); + + data.sort(); + + bool is_equal = std::equal(data.begin(), + data.end(), + ordered_data.begin()); + + CHECK(is_equal); + CHECK(data.is_sorted()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_sort_default_order_from_reverse_ordered) + { + DataNDC data(ordered_data.rbegin(), ordered_data.rend()); + + data.sort(); + + bool is_equal = std::equal(data.begin(), + data.end(), + ordered_data.begin()); + + CHECK(is_equal); + CHECK(data.is_sorted()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_sort_default_order_from_unordered) + { + DataNDC data(unordered_data.begin(), unordered_data.end()); + + data.sort(); + + bool is_equal = std::equal(data.begin(), + data.end(), + ordered_data.begin()); + + CHECK(is_equal); + CHECK(data.is_sorted()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_sort_greater_order_from_reverse_ordered) + { + DataNDC data(ordered_data.rbegin(), ordered_data.rend()); + + data.sort(std::greater()); + + bool is_equal = std::equal(data.begin(), + data.end(), + ordered_data.rbegin()); + + CHECK(is_equal); + CHECK(data.is_sorted(std::greater())); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_sort_greater_order_from_unordered) + { + DataNDC data(unordered_data.begin(), unordered_data.end()); + + data.sort(std::greater()); + + bool is_equal = std::equal(data.begin(), + data.end(), + ordered_data.rbegin()); + + CHECK(is_equal); + CHECK(data.is_sorted(std::greater())); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_sort_default_partial_order_from_unordered) + { + DataNDC data(unordered_data.begin(), unordered_data.end()); + + data.sort(data.begin() + 2, data.end() - 2); + + bool is_equal = std::equal(data.begin(), + data.end(), + part_ordered_data.begin()); + + CHECK(is_equal); + CHECK((data.is_sorted(data.cbegin() + 2, data.cend() - 2))); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_sort_greater_partial_order_from_unordered) + { + DataNDC data(unordered_data.begin(), unordered_data.end()); + + data.sort(data.begin() + 2, data.end() - 2, std::greater()); + + bool is_equal = std::equal(data.begin(), + data.end(), + part_reverse_ordered_data.begin()); + + CHECK(is_equal); + CHECK((data.is_sorted(data.begin() + 2, data.end() - 2, std::greater()))); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_stable_sort_default_order_from_ordered) + { + DataNDC data(stable_default_ordered_data.begin(), stable_default_ordered_data.end()); + + data.stable_sort(); + + bool is_equal = std::equal(data.begin(), + data.end(), + stable_default_ordered_data.begin(), + NDC::are_identical); + + CHECK(is_equal); + CHECK(data.is_sorted()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_stable_sort_default_order_from_reverse_ordered) + { + DataNDC data(stable_default_ordered_data.rbegin(), stable_default_ordered_data.rend()); + + data.stable_sort(); + + bool is_equal = std::equal(data.begin(), + data.end(), + stable_reverse_ordered_data.begin(), + NDC::are_identical); + + CHECK(is_equal); + CHECK(data.is_sorted()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_stable_sort_default_order_from_unordered) + { + DataNDC data(unordered_data.begin(), unordered_data.end()); + + data.stable_sort(); + + bool is_equal = std::equal(data.begin(), + data.end(), + stable_default_ordered_data.begin(), + NDC::are_identical); + + CHECK(is_equal); + CHECK(data.is_sorted()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_stable_sort_greater_order_from_reverse_ordered) + { + DataNDC data(stable_default_ordered_data.rbegin(), stable_default_ordered_data.rend()); + + data.stable_sort(std::greater()); + + bool is_equal = std::equal(data.begin(), + data.end(), + stable_greater_reverse_ordered_data.begin(), + NDC::are_identical); + + CHECK(is_equal); + CHECK(data.is_sorted(std::greater())); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_stable_sort_greater_order_from_unordered) + { + DataNDC data(unordered_data.begin(), unordered_data.end()); + + data.stable_sort(std::greater()); + + bool is_equal = std::equal(data.begin(), + data.end(), + stable_greater_ordered_data.begin(), + NDC::are_identical); + + CHECK(is_equal); + CHECK(data.is_sorted(std::greater())); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_stable_sort_default_partial_order_from_unordered) + { + DataNDC data(unordered_data.begin(), unordered_data.end()); + + data.stable_sort(data.begin() + 2, data.end() - 2); + + bool is_equal = std::equal(data.begin(), + data.end(), + stable_part_ordered_data.begin(), + NDC::are_identical); + + CHECK(is_equal); + CHECK((data.is_sorted(data.cbegin() + 2, data.cend() - 2))); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_stable_sort_greater_partial_order_from_unordered) + { + DataNDC data(unordered_data.begin(), unordered_data.end()); + + data.stable_sort(data.begin() + 2, data.end() - 2, std::greater()); + + bool is_equal = std::equal(data.begin(), + data.end(), + stable_part_greater_ordered_data.begin(), + NDC::are_identical); + + CHECK(is_equal); + CHECK((data.is_sorted(data.begin() + 2, data.end() - 2, std::greater()))); + } + }; +} diff --git a/test/test_no_stl_algorithm.cpp b/test/test_no_stl_algorithm.cpp index 62ffa0cf..2f106a7d 100644 --- a/test/test_no_stl_algorithm.cpp +++ b/test/test_no_stl_algorithm.cpp @@ -741,5 +741,23 @@ namespace CHECK_EQUAL(4U, *(data2[3])); CHECK_EQUAL(5U, *(data2[4])); } + + //************************************************************************* + TEST(rotate) + { + std::vector initial_data = { 1, 2, 3, 4, 5, 6, 7 }; + + for (size_t i = 0; i < initial_data.size(); ++i) + { + std::vector data1(initial_data); + std::vector data2(initial_data); + + std::rotate(data1.data(), data1.data() + i, data1.data() + data1.size()); + etlstd::rotate(data2.data(), data2.data() + i, data2.data() + data2.size()); + + bool isEqual = std::equal(std::begin(data1), std::end(data1), std::begin(data2)); + CHECK(isEqual); + } + } }; } diff --git a/test/test_no_stl_iterator.cpp b/test/test_no_stl_iterator.cpp index 74edfd1b..3957e9fb 100644 --- a/test/test_no_stl_iterator.cpp +++ b/test/test_no_stl_iterator.cpp @@ -68,7 +68,7 @@ namespace { int* itr1 = std::begin(dataA); non_random_iterator itr2 = std::begin(dataA); - + std::advance(itr1, 4); etlstd::advance(itr2, 4); CHECK_EQUAL(*itr1, *itr2); @@ -92,5 +92,35 @@ namespace etlstd::advance(itr2, -3); CHECK_EQUAL(*itr1, *itr2); } + + //************************************************************************* + TEST(prev) + { + int data[] = { 1, 2, 3, 4, 5, 6, 7 }; + + size_t length = 6U; + + int* itr = &data[0] + length; + + for (size_t i = 1; i <= length; ++i) + { + CHECK_EQUAL(data[length - i], *etlstd::prev(itr, i)); + } + } + + //************************************************************************* + TEST(next) + { + int data[] = { 1, 2, 3, 4, 5, 6, 7 }; + + size_t length = 6U; + + int* itr = &data[0]; + + for (size_t i = 1; i <= length; ++i) + { + CHECK_EQUAL(data[i], *etlstd::next(itr, i)); + } + } }; } diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index b1055e22..f05a8bd9 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -28,6 +28,8 @@ SOFTWARE. #include "UnitTest++.h" +#define IN_TYPE_TRAITS_TEST + #if defined(ETL_COMPILER_GCC) namespace std { diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index 830b1e5f..b3cee6df 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -457,6 +457,7 @@ + @@ -672,6 +673,7 @@ + diff --git a/test/vs2017/etl.vcxproj.filters b/test/vs2017/etl.vcxproj.filters index 986060f8..d9d31a9d 100644 --- a/test/vs2017/etl.vcxproj.filters +++ b/test/vs2017/etl.vcxproj.filters @@ -786,6 +786,9 @@ ETL\STL + + ETL\Containers + @@ -1241,6 +1244,9 @@ Source Files + + Source Files +