From dc0ab72e09f86da431e62280eec1cb74aae0a9e7 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 6 Sep 2022 10:59:49 +0100 Subject: [PATCH] circular_span first draft --- include/etl/byte_stream.h | 2 +- include/etl/circular_iterator.h | 800 +++++++++--------- include/etl/circular_span.h | 774 ++++++++++++++++++ include/etl/message_broker.h | 4 +- include/etl/span.h | 2 - test/test_circular_iterator.cpp | 1 - test/test_circular_span_dynamic_extent.cpp | 906 +++++++++++++++++++++ test/test_circular_span_fixed_extent.cpp | 859 +++++++++++++++++++ test/vs2019/etl.vcxproj | 3 + test/vs2019/etl.vcxproj.filters | 9 + 10 files changed, 2991 insertions(+), 369 deletions(-) create mode 100644 include/etl/circular_span.h create mode 100644 test/test_circular_span_dynamic_extent.cpp create mode 100644 test/test_circular_span_fixed_extent.cpp diff --git a/include/etl/byte_stream.h b/include/etl/byte_stream.h index 4aca9663..83bc521b 100644 --- a/include/etl/byte_stream.h +++ b/include/etl/byte_stream.h @@ -216,7 +216,7 @@ namespace etl typename etl::enable_if::value || etl::is_floating_point::value, void>::type write_unchecked(const etl::span& range) { - typename etl::span::const_iterator itr = range.begin(); + typename etl::span::iterator itr = range.begin(); while (itr != range.end()) { diff --git a/include/etl/circular_iterator.h b/include/etl/circular_iterator.h index fec96cea..64079d56 100644 --- a/include/etl/circular_iterator.h +++ b/include/etl/circular_iterator.h @@ -93,8 +93,8 @@ namespace etl ETL_CONSTEXPR14 circular_iterator_common& operator =(const circular_iterator_common& other) { itr_begin = other.itr_begin; - itr_end = other.itr_end; - itr = other.itr; + itr_end = other.itr_end; + itr = other.itr; return *this; } @@ -185,32 +185,444 @@ namespace etl TIterator itr_end; ///< The underlying end iterator. TIterator itr; ///< The underlying iterator. }; + + //*************************************************************************** + /// A circular iterator class. + /// This iterator can be given a pair of iterator values, which will loop if the start or end of the range is reached. + ///\ingroup iterator + //*************************************************************************** + template ::iterator_category> + class circular_iterator_impl + { + ETL_STATIC_ASSERT((etl::is_same::value_type), "input_iterator_catagory is not supported by circular_iterator"); + ETL_STATIC_ASSERT((etl::is_same::value_type), "output_iterator_catagory is not supported by circular_iterator"); + }; + + //*************************************************************************** + /// A circular iterator class. + /// Specialisation for forward iterators. + ///\ingroup iterator + /// //*************************************************************************** + template + class circular_iterator_impl + : public circular_iterator_common + { + private: + + typedef circular_iterator_common base_t; + + public: + + using base_t::operator=; + + typedef typename base_t::value_type value_type; + typedef typename base_t::difference_type difference_type; + typedef typename base_t::pointer pointer; + typedef typename base_t::reference reference; + typedef typename base_t::iterator_category iterator_category; + + //*************************************************************************** + /// Default constructor. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl() + : circular_iterator_common() + { + } + + //*************************************************************************** + /// Construct from iterators. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl(TIterator itr_begin_, TIterator itr_end_) + : circular_iterator_common(itr_begin_, itr_end_, itr_begin_) + { + } + + //*************************************************************************** + /// Construct from start + iterators. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl(TIterator itr_begin_, TIterator itr_end_, TIterator start_) + : circular_iterator_common(itr_begin_, itr_end_, start_) + { + } + + //*************************************************************************** + /// Construct from span. + //*************************************************************************** + template + ETL_CONSTEXPR14 circular_iterator_impl(const etl::span& span_) + : circular_iterator_common(span_.begin(), span_.end(), span_.begin()) + { + } + + //*************************************************************************** + /// Construct from start + span. + //*************************************************************************** + template + ETL_CONSTEXPR14 circular_iterator_impl(const etl::span& span_, TIterator start_) + : circular_iterator_common(span_.begin(), span_.end(), start_) + { + } + + //*************************************************************************** + /// Copy constructor + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl(const circular_iterator_impl& other) + : circular_iterator_common(other) + { + } + + //*************************************************************************** + /// Increment. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl& operator ++() + { + if (++this->itr == this->itr_end) + { + this->itr = this->itr_begin; + } + + return *this; + } + + //*************************************************************************** + /// Increment. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl operator ++(int) + { + circular_iterator_impl original(*this); + + ++(*this); + + return (original); + } + }; + + //*************************************************************************** + /// A circular iterator class. + /// Specialisation for random access iterators. + ///\ingroup iterator + /// //*************************************************************************** + template + class circular_iterator_impl + : public circular_iterator_common + { + private: + + typedef circular_iterator_common base_t; + + public: + + using base_t::operator=; + + typedef typename base_t::value_type value_type; + typedef typename base_t::difference_type difference_type; + typedef typename base_t::pointer pointer; + typedef typename base_t::reference reference; + typedef typename base_t::iterator_category iterator_category; + + //*************************************************************************** + /// Default constructor. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl() + : circular_iterator_common() + { + } + + //*************************************************************************** + /// Construct from iterators. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl(TIterator itr_begin_, TIterator itr_end_) + : circular_iterator_common(itr_begin_, itr_end_, itr_begin_) + { + } + + //*************************************************************************** + /// Construct from start + iterators. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl(TIterator itr_begin_, TIterator itr_end_, TIterator start_) + : circular_iterator_common(itr_begin_, itr_end_, start_) + { + } + + //*************************************************************************** + /// Construct from span. + //*************************************************************************** + template + ETL_CONSTEXPR14 circular_iterator_impl(const etl::span& span_) + : circular_iterator_common(span_.begin(), span_.end(), span_.begin()) + { + } + + //*************************************************************************** + /// Construct from start + span. + //*************************************************************************** + template + ETL_CONSTEXPR14 circular_iterator_impl(const etl::span& span_, TIterator start_) + : circular_iterator_common(span_.begin(), span_.end(), start_) + { + } + + //*************************************************************************** + /// Copy constructor + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl(const circular_iterator_impl& other) + : circular_iterator_common(other) + { + } + + //*************************************************************************** + /// Increment. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl& operator ++() + { + if (++itr == itr_end) + { + itr = itr_begin; + } + + return *this; + } + + //*************************************************************************** + /// Increment. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl operator ++(int) + { + circular_iterator_impl original(*this); + + ++(*this); + + return (original); + } + + //*************************************************************************** + /// Decrement. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl& operator --() + { + if (itr == itr_begin) + { + typename etl::reverse_iterator ritr(itr_end); + ++ritr; + itr = ritr.base(); + } + else + { + --itr; + } + + return *this; + } + + //*************************************************************************** + /// Decrement. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl operator --(int) + { + circular_iterator_impl original(*this); + + --(*this); + + return (original); + } + }; + + //*************************************************************************** + /// A circular iterator class. + /// Specialisation for random access iterators. + ///\ingroup iterator + //*************************************************************************** + template + class circular_iterator_impl + : public circular_iterator_common + { + private: + + typedef circular_iterator_common base_t; + + public: + + using base_t::operator=; + + typedef typename base_t::value_type value_type; + typedef typename base_t::difference_type difference_type; + typedef typename base_t::pointer pointer; + typedef typename base_t::reference reference; + typedef typename base_t::iterator_category iterator_category; + + //*************************************************************************** + /// Default constructor. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl() + : circular_iterator_common() + { + } + + //*************************************************************************** + /// Construct from iterators. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl(TIterator itr_begin_, TIterator itr_end_) + : circular_iterator_common(itr_begin_, itr_end_, itr_begin_) + { + } + + //*************************************************************************** + /// Construct from start + iterators. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl(TIterator itr_begin_, TIterator itr_end_, TIterator start_) + : circular_iterator_common(itr_begin_, itr_end_, start_) + { + } + + //*************************************************************************** + /// Construct from span. + //*************************************************************************** + template + ETL_CONSTEXPR14 circular_iterator_impl(const etl::span& span_) + : circular_iterator_common(span_.begin(), span_.end(), span_.begin()) + { + } + + //*************************************************************************** + /// Construct from start + span. + //*************************************************************************** + template + ETL_CONSTEXPR14 circular_iterator_impl(const etl::span& span_, TIterator start_) + : circular_iterator_common(span_.begin(), span_.end(), start_) + { + } + + //*************************************************************************** + /// Copy constructor + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl(const circular_iterator_impl& other) + : circular_iterator_common(other) + { + } + + //*************************************************************************** + /// Increment. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl& operator ++() + { + if (++itr == itr_end) + { + itr = itr_begin; + } + + return *this; + } + + //*************************************************************************** + /// Increment. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl operator ++(int) + { + circular_iterator_impl original(*this); + + ++(*this); + + return (original); + } + + //*************************************************************************** + /// Decrement. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl& operator --() + { + if (itr == itr_begin) + { + typename etl::reverse_iterator ritr(itr_end); + ++ritr; + itr = ritr.base(); + } + else + { + --itr; + } + + return *this; + } + + //*************************************************************************** + /// Decrement. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl operator --(int) + { + circular_iterator_impl original(*this); + + --(*this); + + return (original); + } + + //*************************************************************************** + /// += operator. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl& operator +=(difference_type offset) + { + const difference_type length = difference_type(size()); + offset %= length; + + if (offset != 0) + { + const difference_type distance_from_begin = etl::distance(itr_begin, itr); + const difference_type distance_to_end = etl::distance(itr, itr_end); + + if (offset > 0) + { + if (distance_to_end > offset) + { + offset = distance_from_begin + offset; + } + else + { + offset = offset - distance_to_end; + } + } + else + { + offset = -offset; + + if (distance_from_begin >= offset) + { + offset = distance_from_begin - offset; + } + else + { + offset = offset - distance_from_begin; + offset = length - offset; + } + } + + itr = itr_begin + offset; + } + + return *this; + } + + //*************************************************************************** + /// -= operator. + //*************************************************************************** + ETL_CONSTEXPR14 circular_iterator_impl& operator -=(typename etl::iterator_traits::difference_type offset) + { + return operator +=(-offset); + } + }; } //*************************************************************************** /// A circular iterator class. /// This iterator can be given a pair of iterator values, which will loop if the start or end of the range is reached. ///\ingroup iterator - //*************************************************************************** - template ::iterator_category> - class circular_iterator - { - ETL_STATIC_ASSERT((etl::is_same::value_type), "input_iterator_catagory is not supported by circular_iterator"); - ETL_STATIC_ASSERT((etl::is_same::value_type), "output_iterator_catagory is not supported by circular_iterator"); - }; - - //*************************************************************************** - /// A circular iterator class. - /// Specialisation for forward iterators. - ///\ingroup iterator - /// //*************************************************************************** + //************************************************************************** template - class circular_iterator - : public etl::private_circular_iterator::circular_iterator_common + class circular_iterator ETL_FINAL + : public etl::private_circular_iterator::circular_iterator_impl::iterator_category> { private: - typedef etl::private_circular_iterator::circular_iterator_common base_t; + typedef typename etl::private_circular_iterator::circular_iterator_impl::iterator_category> base_t; public: @@ -226,7 +638,7 @@ namespace etl /// Default constructor. //*************************************************************************** ETL_CONSTEXPR14 circular_iterator() - : circular_iterator_common() + : circular_iterator_impl() { } @@ -234,7 +646,7 @@ namespace etl /// Construct from iterators. //*************************************************************************** ETL_CONSTEXPR14 circular_iterator(TIterator itr_begin_, TIterator itr_end_) - : circular_iterator_common(itr_begin_, itr_end_, itr_begin_) + : circular_iterator_impl(itr_begin_, itr_end_, itr_begin_) { } @@ -242,7 +654,7 @@ namespace etl /// Construct from start + iterators. //*************************************************************************** ETL_CONSTEXPR14 circular_iterator(TIterator itr_begin_, TIterator itr_end_, TIterator start_) - : circular_iterator_common(itr_begin_, itr_end_, start_) + : circular_iterator_impl(itr_begin_, itr_end_, start_) { } @@ -251,7 +663,7 @@ namespace etl //*************************************************************************** template ETL_CONSTEXPR14 circular_iterator(const etl::span& span_) - : circular_iterator_common(span_.begin(), span_.end(), span_.begin()) + : circular_iterator_impl(span_.begin(), span_.end(), span_.begin()) { } @@ -260,355 +672,17 @@ namespace etl //*************************************************************************** template ETL_CONSTEXPR14 circular_iterator(const etl::span& span_, TIterator start_) - : circular_iterator_common(span_.begin(), span_.end(), start_) + : circular_iterator_impl(span_.begin(), span_.end(), start_) { } //*************************************************************************** /// Copy constructor //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator(const circular_iterator& other) - : circular_iterator_common(other) + ETL_CONSTEXPR14 circular_iterator(const circular_iterator_impl& other) + : circular_iterator_impl(other) { } - - //*************************************************************************** - /// Increment. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator& operator ++() - { - if (++this->itr == this->itr_end) - { - this->itr = this->itr_begin; - } - - return *this; - } - - //*************************************************************************** - /// Increment. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator operator ++(int) - { - circular_iterator original(*this); - - ++(*this); - - return (original); - } - }; - - //*************************************************************************** - /// A circular iterator class. - /// Specialisation for random access iterators. - ///\ingroup iterator - /// //*************************************************************************** - template - class circular_iterator - : public etl::private_circular_iterator::circular_iterator_common - { - private: - - typedef etl::private_circular_iterator::circular_iterator_common base_t; - - public: - - using base_t::operator=; - - typedef typename base_t::value_type value_type; - typedef typename base_t::difference_type difference_type; - typedef typename base_t::pointer pointer; - typedef typename base_t::reference reference; - typedef typename base_t::iterator_category iterator_category; - - //*************************************************************************** - /// Default constructor. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator() - : circular_iterator_common() - { - } - - //*************************************************************************** - /// Construct from iterators. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator(TIterator itr_begin_, TIterator itr_end_) - : circular_iterator_common(itr_begin_, itr_end_, itr_begin_) - { - } - - //*************************************************************************** - /// Construct from start + iterators. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator(TIterator itr_begin_, TIterator itr_end_, TIterator start_) - : circular_iterator_common(itr_begin_, itr_end_, start_) - { - } - - //*************************************************************************** - /// Construct from span. - //*************************************************************************** - template - ETL_CONSTEXPR14 circular_iterator(const etl::span& span_) - : circular_iterator_common(span_.begin(), span_.end(), span_.begin()) - { - } - - //*************************************************************************** - /// Construct from start + span. - //*************************************************************************** - template - ETL_CONSTEXPR14 circular_iterator(const etl::span& span_, TIterator start_) - : circular_iterator_common(span_.begin(), span_.end(), start_) - { - } - - //*************************************************************************** - /// Copy constructor - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator(const circular_iterator& other) - : circular_iterator_common(other) - { - } - - //*************************************************************************** - /// Increment. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator& operator ++() - { - if (++itr == itr_end) - { - itr = itr_begin; - } - - return *this; - } - - //*************************************************************************** - /// Increment. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator operator ++(int) - { - circular_iterator original(*this); - - ++(*this); - - return (original); - } - - //*************************************************************************** - /// Decrement. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator& operator --() - { - if (itr == itr_begin) - { - typename etl::reverse_iterator ritr(itr_end); - ++ritr; - itr = ritr.base(); - } - else - { - --itr; - } - - return *this; - } - - //*************************************************************************** - /// Decrement. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator operator --(int) - { - circular_iterator original(*this); - - --(*this); - - return (original); - } - }; - - //*************************************************************************** - /// A circular iterator class. - /// Specialisation for random access iterators. - ///\ingroup iterator - //*************************************************************************** - template - class circular_iterator - : public etl::private_circular_iterator::circular_iterator_common - { - private: - - typedef etl::private_circular_iterator::circular_iterator_common base_t; - - public: - - using base_t::operator=; - - typedef typename base_t::value_type value_type; - typedef typename base_t::difference_type difference_type; - typedef typename base_t::pointer pointer; - typedef typename base_t::reference reference; - typedef typename base_t::iterator_category iterator_category; - - //*************************************************************************** - /// Default constructor. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator() - : circular_iterator_common() - { - } - - //*************************************************************************** - /// Construct from iterators. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator(TIterator itr_begin_, TIterator itr_end_) - : circular_iterator_common(itr_begin_, itr_end_, itr_begin_) - { - } - - //*************************************************************************** - /// Construct from start + iterators. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator(TIterator itr_begin_, TIterator itr_end_, TIterator start_) - : circular_iterator_common(itr_begin_, itr_end_, start_) - { - } - - //*************************************************************************** - /// Construct from span. - //*************************************************************************** - template - ETL_CONSTEXPR14 circular_iterator(const etl::span& span_) - : circular_iterator_common(span_.begin(), span_.end(), span_.begin()) - { - } - - //*************************************************************************** - /// Construct from start + span. - //*************************************************************************** - template - ETL_CONSTEXPR14 circular_iterator(const etl::span& span_, TIterator start_) - : circular_iterator_common(span_.begin(), span_.end(), start_) - { - } - - //*************************************************************************** - /// Copy constructor - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator(const circular_iterator& other) - : circular_iterator_common(other) - { - } - - //*************************************************************************** - /// Increment. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator& operator ++() - { - if (++itr == itr_end) - { - itr = itr_begin; - } - - return *this; - } - - //*************************************************************************** - /// Increment. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator operator ++(int) - { - circular_iterator original(*this); - - ++(*this); - - return (original); - } - - //*************************************************************************** - /// Decrement. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator& operator --() - { - if (itr == itr_begin) - { - typename etl::reverse_iterator ritr(itr_end); - ++ritr; - itr = ritr.base(); - } - else - { - --itr; - } - - return *this; - } - - //*************************************************************************** - /// Decrement. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator operator --(int) - { - circular_iterator original(*this); - - --(*this); - - return (original); - } - - //*************************************************************************** - /// += operator. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator& operator +=(difference_type offset) - { - const difference_type length = difference_type(size()); - offset %= length; - - if (offset != 0) - { - const difference_type distance_from_begin = etl::distance(itr_begin, itr); - const difference_type distance_to_end = etl::distance(itr, itr_end); - - if (offset > 0) - { - if (distance_to_end > offset) - { - offset = distance_from_begin + offset; - } - else - { - offset = offset - distance_to_end; - } - } - else - { - offset = -offset; - - if (distance_from_begin >= offset) - { - offset = distance_from_begin - offset; - } - else - { - offset = offset - distance_from_begin; - offset = length - offset; - } - } - - itr = itr_begin + offset; - } - - return *this; - } - - //*************************************************************************** - /// -= operator. - //*************************************************************************** - ETL_CONSTEXPR14 circular_iterator& operator -=(typename etl::iterator_traits::difference_type offset) - { - return operator +=(-offset); - } }; //***************************************************************************** diff --git a/include/etl/circular_span.h b/include/etl/circular_span.h new file mode 100644 index 00000000..e8515ecb --- /dev/null +++ b/include/etl/circular_span.h @@ -0,0 +1,774 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2022 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CIRCULAR_SPAN_INCLUDED +#define ETL_CIRCULAR_SPAN_INCLUDED + +#include "platform.h" +#include "iterator.h" +#include "hash.h" +#include "array.h" +#include "circular_iterator.h" +#include "span.h" + +#include "private/dynamic_extent.h" + +#if ETL_USING_STL && ETL_USING_CPP11 + #include +#endif + +///\defgroup circular_span circular_span +///\ingroup containers + +namespace etl +{ + //*************************************************************************** + /// Circular Span - Fixed Extent + //*************************************************************************** + template + class circular_span + { + public: + + typedef T element_type; + typedef typename etl::remove_cv::type value_type; + typedef size_t size_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + + typedef etl::circular_iterator iterator; + typedef etl::circular_iterator > reverse_iterator; + + typedef typename etl::span::iterator span_iterator; + typedef typename etl::span::reverse_iterator span_reverse_iterator; + + static ETL_CONSTANT size_t extent = Extent; + + //************************************************************************* + /// Default constructor. + //************************************************************************* + ETL_CONSTEXPR circular_span() ETL_NOEXCEPT + : linear_span() + { + } + + //************************************************************************* + /// Construct from pointer + size + //************************************************************************* + template + ETL_CONSTEXPR circular_span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT + : linear_span(begin_, size_) + { + } + + //************************************************************************* + /// Construct from iterators + //************************************************************************* + template + ETL_CONSTEXPR circular_span(const TIterator begin_, const TIterator end_) + : linear_span(begin_, end_) + { + } + + //************************************************************************* + /// Construct from C array + //************************************************************************* + template + ETL_CONSTEXPR circular_span(element_type(&begin_)[ARRAY_SIZE]) ETL_NOEXCEPT + : linear_span(begin_) + { + } + + //************************************************************************* + /// Construct from etl::array. + //************************************************************************* + template + ETL_CONSTEXPR circular_span(etl::array& a) ETL_NOEXCEPT + : linear_span(a) + { + } + + //************************************************************************* + /// Construct from etl::array. + //************************************************************************* + template + ETL_CONSTEXPR circular_span(const etl::array& a) ETL_NOEXCEPT + : linear_span(a) + { + } + +#if ETL_USING_STL && ETL_USING_CPP11 + //************************************************************************* + /// Construct from std::array. + //************************************************************************* + template + ETL_CONSTEXPR circular_span(std::array& a) ETL_NOEXCEPT + : linear_span(a) + { + } + + //************************************************************************* + /// Construct from std::array. + //************************************************************************* + template + ETL_CONSTEXPR circular_span(const std::array& a) ETL_NOEXCEPT + : linear_span(a) + { + } +#endif + +#if ETL_USING_CPP11 + //************************************************************************* + /// Construct from a container or other type that supports + /// data() and size() member functions. + //************************************************************************* + template + ETL_CONSTEXPR circular_span(TContainer&& a) ETL_NOEXCEPT + : linear_span(a) + { + } +#else + //************************************************************************* + /// Construct from a container or other type that supports + /// data() and size() member functions. + //************************************************************************* + template + circular_span(TContainer& a) ETL_NOEXCEPT + : linear_span(a) + { + } + + //************************************************************************* + /// Construct from a container or other type that supports + /// data() and size() member functions. + //************************************************************************* + template + ETL_CONSTEXPR circular_span(const TContainer& a) ETL_NOEXCEPT + : linear_span(a) + { + } +#endif + + //************************************************************************* + /// Copy constructor + //************************************************************************* + ETL_CONSTEXPR circular_span(const circular_span& other) ETL_NOEXCEPT + : linear_span(other.linear_span) + { + } + + //************************************************************************* + /// Returns a reference to the first element. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR reference front() const ETL_NOEXCEPT + { + return linear_span.front(); + } + + //************************************************************************* + /// Returns a reference to the last element. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT + { + return linear_span.back(); + } + + //************************************************************************* + /// Returns a pointer to the first element of the internal storage. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR pointer data() const ETL_NOEXCEPT + { + return linear_span.data(); + } + + //************************************************************************* + /// Returns an iterator to the beginning of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR iterator begin() const ETL_NOEXCEPT + { + return iterator(linear_span.begin(), linear_span.end(), linear_span.begin()); + } + + //************************************************************************* + // Returns an reverse iterator to the reverse beginning of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR reverse_iterator rbegin() const ETL_NOEXCEPT + { + return reverse_iterator(linear_span.rbegin(), linear_span.rend()); + } + + //************************************************************************* + /// Returns an iterator to the beginning of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR span_iterator span_begin() const ETL_NOEXCEPT + { + return linear_span.begin(); + } + + //************************************************************************* + /// Returns a reverse iterator to the reverse beginning of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR span_reverse_iterator span_rbegin() const ETL_NOEXCEPT + { + return linear_span.rbegin(); + } + + //************************************************************************* + /// Returns an iterator to the end of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR span_iterator span_end() const ETL_NOEXCEPT + { + return linear_span.end(); + } + + //************************************************************************* + /// Returns a reverse iterator to the reverse end of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR span_reverse_iterator span_rend() const ETL_NOEXCEPT + { + return linear_span.rend(); + } + + //************************************************************************* + /// Returns true if the circular_span size is zero. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT + { + return linear_span.empty(); + } + + //************************************************************************* + /// Returns the size of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT + { + return linear_span.size(); + } + + //************************************************************************* + /// Returns the size of the circular_span in bytes. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR size_t size_bytes() const ETL_NOEXCEPT + { + return linear_span.size_bytes(); + } + + //************************************************************************* + /// Returns the maximum possible size of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR size_t max_size() const ETL_NOEXCEPT + { + return linear_span.max_size(); + } + + //************************************************************************* + /// Assign from a circular_span. + //************************************************************************* + ETL_CONSTEXPR14 circular_span& operator =(const circular_span& other) ETL_NOEXCEPT + { + linear_span = other.linear_span; + + return *this; + } + + //************************************************************************* + /// Returns a reference to the indexed value. + //************************************************************************* + ETL_CONSTEXPR reference operator[](const size_t i) const + { + return linear_span.operator[](i); + } + + //************************************************************************* + /// Obtains a circular_span that is a view over the first Count elements of this circular_span. + //************************************************************************* + template + ETL_NODISCARD ETL_CONSTEXPR etl::circular_span first() const ETL_NOEXCEPT + { + return etl::circular_span(linear_span.data(), linear_span.data() + Count); + } + + //************************************************************************* + /// Obtains a circular_span that is a view over the first count elements of this circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR etl::circular_span first(size_t count) const ETL_NOEXCEPT + { + return etl::circular_span(linear_span.data(), linear_span.data() + count); + } + + //************************************************************************* + /// Obtains a circular_span that is a view over the last Count elements of this circular_span. + //************************************************************************* + template + ETL_NODISCARD ETL_CONSTEXPR etl::circular_span last() const ETL_NOEXCEPT + { + return etl::circular_span(linear_span.data() + Extent - Count, (linear_span.data() + Extent)); + } + + //************************************************************************* + /// Obtains a circular_span that is a view over the last count elements of this circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR etl::circular_span last(size_t count) const ETL_NOEXCEPT + { + return etl::circular_span((linear_span.data() + Extent) - count, (linear_span.data() + Extent)); + } + +#if ETL_USING_CPP11 + //************************************************************************* + /// Obtains a circular_span that is a view from Offset over the next Count elements of this circular_span. + //************************************************************************* + template + ETL_NODISCARD ETL_CONSTEXPR + etl::circular_span subspan() const ETL_NOEXCEPT + { + return (Count == etl::dynamic_extent) ? etl::circular_span(linear_span.data() + Offset, (linear_span.data() + Extent)) + : etl::circular_span(linear_span.data() + Offset, linear_span.data() + Offset + Count); + } +#else + //************************************************************************* + /// Obtains a circular_span that is a view from Offset over the next Count elements of this circular_span. + //************************************************************************* + template + etl::circular_span subspan() const + { + if (Count == etl::dynamic_extent) + { + return etl::circular_span(linear_span.data() + Offset, (linear_span.data() + Extent)); + } + else + { + return etl::circular_span(linear_span.data() + Offset, linear_span.data() + Offset + Count); + } + } +#endif + + //************************************************************************* + /// Obtains a circular span that is a view from 'offset' over the next 'count' elements of this span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR etl::circular_span subspan(size_t offset, size_t count = etl::dynamic_extent) const ETL_NOEXCEPT + { + return (count == etl::dynamic_extent) ? etl::circular_span(linear_span.begin() + offset, (linear_span.begin() + Extent)) + : etl::circular_span(linear_span.begin() + offset, linear_span.begin() + offset + count); + } + + private: + + etl::span linear_span; + }; + + //*************************************************************************** + /// Circular Span - Dynamic Extent + //*************************************************************************** + template + class circular_span + { + public: + + typedef T element_type; + typedef typename etl::remove_cv::type value_type; + typedef size_t size_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + + typedef etl::circular_iterator iterator; + typedef etl::circular_iterator > reverse_iterator; + + typedef typename etl::span::iterator span_iterator; + typedef typename etl::span::reverse_iterator span_reverse_iterator; + + static ETL_CONSTANT size_t extent = etl::dynamic_extent; + + //************************************************************************* + /// Default constructor. + //************************************************************************* + ETL_CONSTEXPR circular_span() ETL_NOEXCEPT + : linear_span() + { + } + + //************************************************************************* + /// Construct from pointer + size + //************************************************************************* + template + ETL_CONSTEXPR circular_span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT + : linear_span(begin_, size_) + { + } + + //************************************************************************* + /// Construct from iterators + //************************************************************************* + template + ETL_CONSTEXPR circular_span(const TIterator begin_, const TIterator end_) + : linear_span(begin_, end_) + { + } + + //************************************************************************* + /// Construct from C array + //************************************************************************* + template + ETL_CONSTEXPR circular_span(element_type(&begin_)[ARRAY_SIZE]) ETL_NOEXCEPT + : linear_span(begin_) + { + } + + //************************************************************************* + /// Construct from etl::array. + //************************************************************************* + template + ETL_CONSTEXPR circular_span(etl::array& a) ETL_NOEXCEPT + : linear_span(a) + { + } + + //************************************************************************* + /// Construct from etl::array. + //************************************************************************* + template + ETL_CONSTEXPR circular_span(const etl::array& a) ETL_NOEXCEPT + : linear_span(a) + { + } + +#if ETL_USING_STL && ETL_USING_CPP11 + //************************************************************************* + /// Construct from std::array. + //************************************************************************* + template + ETL_CONSTEXPR circular_span(std::array& a) ETL_NOEXCEPT + : linear_span(a) + { + } + + //************************************************************************* + /// Construct from std::array. + //************************************************************************* + template + ETL_CONSTEXPR circular_span(const std::array& a) ETL_NOEXCEPT + : linear_span(a) + { + } +#endif + +#if ETL_USING_CPP11 + //************************************************************************* + /// Construct from a container or other type that supports + /// data() and size() member functions. + //************************************************************************* + template + ETL_CONSTEXPR circular_span(TContainer&& a) ETL_NOEXCEPT + : linear_span(a) + { + } +#else + //************************************************************************* + /// Construct from a container or other type that supports + /// data() and size() member functions. + //************************************************************************* + template + circular_span(TContainer& a) ETL_NOEXCEPT + : linear_span(a) + { + } + + //************************************************************************* + /// Construct from a container or other type that supports + /// data() and size() member functions. + //************************************************************************* + template + ETL_CONSTEXPR circular_span(const TContainer& a) ETL_NOEXCEPT + : linear_span(a) + { + } +#endif + + //************************************************************************* + /// Copy constructor + //************************************************************************* + ETL_CONSTEXPR circular_span(const circular_span& other) ETL_NOEXCEPT + : linear_span(other.linear_span) + { + } + + //************************************************************************* + /// Returns a reference to the first element. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR reference front() const ETL_NOEXCEPT + { + return linear_span.front(); + } + + //************************************************************************* + /// Returns a reference to the last element. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT + { + return linear_span.back(); + } + + //************************************************************************* + /// Returns a pointer to the first element of the internal storage. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR pointer data() const ETL_NOEXCEPT + { + return linear_span.data(); + } + + //************************************************************************* + /// Returns an iterator to the beginning of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR iterator begin() const ETL_NOEXCEPT + { + return iterator(linear_span.begin(), linear_span.end(), linear_span.begin()); + } + + //************************************************************************* + // Returns an reverse iterator to the reverse beginning of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR reverse_iterator rbegin() const ETL_NOEXCEPT + { + return reverse_iterator(linear_span.end(), linear_span.begin(), linear_span.end()); + } + + //************************************************************************* + /// Returns an iterator to the beginning of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR span_iterator span_begin() const ETL_NOEXCEPT + { + return linear_span.begin(); + } + + //************************************************************************* + /// Returns a reverse iterator to the reverse beginning of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR span_reverse_iterator span_rbegin() const ETL_NOEXCEPT + { + return linear_span.rbegin(); + } + + //************************************************************************* + /// Returns an iterator to the end of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR span_iterator span_end() const ETL_NOEXCEPT + { + return linear_span.end(); + } + + //************************************************************************* + /// Returns a reverse iterator to the reverse end of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR span_reverse_iterator span_rend() const ETL_NOEXCEPT + { + return linear_span.rend(); + } + + //************************************************************************* + /// Returns true if the circular_span size is zero. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT + { + return linear_span.empty(); + } + + //************************************************************************* + /// Returns the size of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT + { + return linear_span.size(); + } + + //************************************************************************* + /// Returns the size of the circular_span in bytes. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR size_t size_bytes() const ETL_NOEXCEPT + { + return linear_span.size_bytes(); + } + + //************************************************************************* + /// Returns the maximum possible size of the circular_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR size_t max_size() const ETL_NOEXCEPT + { + return linear_span.max_size(); + } + + //************************************************************************* + /// Assign from a circular_span. + //************************************************************************* + ETL_CONSTEXPR14 circular_span& operator =(const circular_span& other) ETL_NOEXCEPT + { + linear_span = other.linear_span; + + return *this; + } + + //************************************************************************* + /// Returns a reference to the indexed value. + //************************************************************************* + ETL_CONSTEXPR reference operator[](const size_t i) const + { + return linear_span.operator[](i); + } + + //************************************************************************* + /// Obtains a span that is a view over the first COUNT elements of this span. + //************************************************************************* + template + ETL_NODISCARD ETL_CONSTEXPR etl::circular_span first() const ETL_NOEXCEPT + { + return etl::circular_span(linear_span.begin(), linear_span.begin() + Count); + } + + //************************************************************************* + /// Obtains a span that is a view over the first count elements of this span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR etl::circular_span first(size_t count) const ETL_NOEXCEPT + { + return etl::circular_span(linear_span.begin(), linear_span.begin() + count); + } + + //************************************************************************* + /// Obtains a span that is a view over the last COUNT elements of this span. + //************************************************************************* + template + ETL_NODISCARD ETL_CONSTEXPR etl::circular_span last() const ETL_NOEXCEPT + { + return etl::circular_span(linear_span.end() - Count, linear_span.end()); + } + + //************************************************************************* + /// Obtains a span that is a view over the last count elements of this span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR etl::circular_span last(size_t count) const ETL_NOEXCEPT + { + return etl::circular_span(linear_span.end() - count, linear_span.end()); + } + +#if ETL_USING_CPP11 + //************************************************************************* + /// Obtains a circular span that is a view from Offset over the next COUNT elements of this span. + //************************************************************************* + template + ETL_NODISCARD ETL_CONSTEXPR + etl::circular_span subspan() const ETL_NOEXCEPT + { + return (Count == etl::dynamic_extent) ? etl::circular_span(linear_span.begin() + Offset, linear_span.end()) + : etl::circular_span(linear_span.begin() + Offset, linear_span.begin() + Offset + Count); + } +#else + //************************************************************************* + /// Obtains a circular span that is a view from Offset over the next Count elements of this span. + //************************************************************************* + template + etl::circular_span subspan() const + { + if (Count == etl::dynamic_extent) + { + return etl::circular_span(linear_span.begin() + Offset, linear_span.end()); + } + else + { + return etl::circular_span(linear_span.begin() + Offset, linear_span.begin() + Offset + Count); } + } +#endif + + //************************************************************************* + /// Obtains a circular span that is a view from 'offset' over the next 'count' elements of this span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR14 etl::circular_span subspan(size_t offset, size_t count = etl::dynamic_extent) const ETL_NOEXCEPT + { + return (count == etl::dynamic_extent) ? etl::circular_span(linear_span.begin() + offset, linear_span.end()) + : etl::circular_span(linear_span.begin() + offset, linear_span.begin() + offset + count); + } + + private: + + etl::span linear_span; + }; + + //************************************************************************* + /// Template deduction guides. + //************************************************************************* +#if ETL_USING_CPP17 + template + circular_span(const TIterator begin_, const TIterator end_) + ->circular_span, etl::dynamic_extent>; + + template + circular_span(const TIterator begin_, const TSize size_) + ->circular_span, etl::dynamic_extent>; + + template + circular_span(T(&)[N]) + -> circular_span; + + template + circular_span(etl::array&) + -> circular_span; + + template + circular_span(const etl::array&) + -> circular_span; + +#if ETL_USING_STL + template + circular_span(std::array&) + ->circular_span; + + template + circular_span(const std::array&) + ->circular_span; +#endif +#endif + + //************************************************************************* + /// Hash function. + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template + struct hash > + { + size_t operator()(const etl::circular_span& view) const + { + return etl::private_hash::generic_hash(reinterpret_cast(&view[0]), + reinterpret_cast(&view[view.size()])); + } + }; +#endif +} + +#endif diff --git a/include/etl/message_broker.h b/include/etl/message_broker.h index c34a212a..b2988243 100644 --- a/include/etl/message_broker.h +++ b/include/etl/message_broker.h @@ -196,7 +196,7 @@ namespace etl { message_id_span_t message_ids = sub->message_id_list(); - message_id_span_t::const_iterator itr = etl::find(message_ids.begin(), message_ids.end(), id); + message_id_span_t::iterator itr = etl::find(message_ids.begin(), message_ids.end(), id); if (itr != message_ids.end()) { @@ -230,7 +230,7 @@ namespace etl { message_id_span_t message_ids = sub->message_id_list(); - message_id_span_t::const_iterator itr = etl::find(message_ids.begin(), message_ids.end(), id); + message_id_span_t::iterator itr = etl::find(message_ids.begin(), message_ids.end(), id); if (itr != message_ids.end()) { diff --git a/include/etl/span.h b/include/etl/span.h index 2198d7c3..138fbfd0 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -411,9 +411,7 @@ namespace etl typedef T* pointer; typedef const T* const_pointer; typedef T* iterator; - typedef const T* const_iterator; typedef ETL_OR_STD::reverse_iterator reverse_iterator; - typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; static ETL_CONSTANT size_t extent = etl::dynamic_extent; diff --git a/test/test_circular_iterator.cpp b/test/test_circular_iterator.cpp index e325c39a..b8e35494 100644 --- a/test/test_circular_iterator.cpp +++ b/test/test_circular_iterator.cpp @@ -30,7 +30,6 @@ SOFTWARE. #include #include #include -#include #include "etl/circular_iterator.h" diff --git a/test/test_circular_span_dynamic_extent.cpp b/test/test_circular_span_dynamic_extent.cpp new file mode 100644 index 00000000..e51da3f3 --- /dev/null +++ b/test/test_circular_span_dynamic_extent.cpp @@ -0,0 +1,906 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2022 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/circular_span.h" +#include "etl/array.h" + +#include +#include +#include +#include + +namespace +{ + SUITE(test_circular_span_dynamic_extent) + { + static const size_t SIZE = 10UL; + + typedef etl::array EtlData; + typedef std::array StlData; + typedef std::vector StlVData; + + typedef etl::circular_span View; + typedef etl::circular_span CView; + + EtlData etldata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + StlData stldata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + StlVData stlvdata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + EtlData etldatasmaller = { 0, 1, 2, 3, 4, 5, 5, 7, 8, 9 }; + + EtlData etloriginal = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + EtlData etlmodified = { 0, 1, 10, 10, 10, 10, 10, 10, 8, 9 }; + + const EtlData cetldata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + const StlData cstldata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + const StlVData cstlvdata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + int cdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int* pcdata = cdata; + + const int ccdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + const int* pccdata = ccdata; + + //************************************************************************* + TEST(test_default_constructor) + { + View view; + + CHECK_EQUAL(0U, view.size()); + CHECK_EQUAL(0U, view.max_size()); + CHECK(view.empty()); + } + + //************************************************************************* + TEST(test_constructor_etl_array_1) + { + View view(etldata); + + CHECK_EQUAL(etldata.size(), view.size()); + CHECK_EQUAL(etldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_etl_array_1_const) + { + CView view(cetldata); + + CHECK_EQUAL(cetldata.size(), view.size()); + CHECK_EQUAL(cetldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), cetldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_etl_array_2) + { + View view(etldata.begin(), etldata.end()); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_etl_array_2_const) + { + CView view(cetldata.begin(), cetldata.end()); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), cetldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_array_1) + { + View view(stldata); + + CHECK_EQUAL(stldata.size(), view.size()); + CHECK_EQUAL(stldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), stldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_array_1_const) + { + CView view(cstldata); + + CHECK_EQUAL(cstldata.size(), view.size()); + CHECK_EQUAL(cstldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), cstldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_array_2) + { + View view(stldata.begin(), stldata.end()); + + CHECK_EQUAL(stldata.size(), view.size()); + CHECK_EQUAL(stldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), stldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_array_2_const) + { + CView view(cstldata.begin(), cstldata.end()); + + CHECK_EQUAL(cstldata.size(), view.size()); + CHECK_EQUAL(cstldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), cstldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_vector_1) + { + View view(stlvdata); + + CHECK_EQUAL(stlvdata.size(), view.size()); + CHECK_EQUAL(stlvdata.size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), stlvdata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_vector_1_const) + { + CView view(cstlvdata); + + CHECK_EQUAL(cstlvdata.size(), view.size()); + CHECK_EQUAL(cstlvdata.size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), cstlvdata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_c_array_1) + { + View view(pcdata, SIZE); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), pcdata); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_c_array_1_const) + { + CView view(pccdata, SIZE); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), pccdata); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_c_array_2) + { + View view(cdata); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), cdata); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_c_array_2_const) + { + CView view(ccdata); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), ccdata); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_implicit_constructor_c_array_2) + { + CView view; + + view = ccdata; + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), ccdata); + CHECK(isEqual); + } + +#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED) + //************************************************************************* + TEST(test_cpp17_deduced_constructor) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + etl::circular_span span1{ data }; + etl::circular_span span2{ data.begin(), data.end() }; + etl::circular_span span3{ data.begin(), data.size() }; + etl::circular_span span4{ span1 }; + + int c_array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::circular_span span5{ c_array }; + + bool isEqual = false; + + isEqual = std::equal(span1.span_begin(), span1.span_end(), data.begin()); + CHECK(isEqual); + + isEqual = std::equal(span2.span_begin(), span2.span_end(), data.begin()); + CHECK(isEqual); + + isEqual = std::equal(span3.span_begin(), span3.span_end(), data.begin()); + CHECK(isEqual); + + isEqual = std::equal(span4.span_begin(), span4.span_end(), data.begin()); + CHECK(isEqual); + + isEqual = std::equal(span5.span_begin(), span5.span_end(), c_array); + CHECK(isEqual); + } +#endif + + //************************************************************************* + TEST(test_constructor_range) + { + View view(etldata.begin() + 2, etldata.end() - 2); + + CHECK_EQUAL(etldata.size() - 4, view.size()); + CHECK_EQUAL(etldata.size() - 4, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), etldata.begin() + 2); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_assign_from_span) + { + View view1(etldata); + View view2; + + CView cview1(etldata); + CView cview2; + + view2 = view1; + cview2 = cview1; + + CHECK_EQUAL(view1.size(), view2.size()); + CHECK_EQUAL(view1.max_size(), view2.max_size()); + + CHECK_EQUAL(cview1.size(), cview2.size()); + CHECK_EQUAL(cview1.max_size(), cview2.max_size()); + + bool isEqual; + + isEqual = std::equal(view1.span_begin(), view1.span_end(), view2.begin()); + CHECK(isEqual); + + isEqual = std::equal(cview1.span_begin(), cview1.span_end(), cview2.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_modify_range) + { + View view(etloriginal.begin() + 2, etloriginal.end() - 2); + + CHECK_EQUAL(etloriginal.size() - 4, view.size()); + CHECK_EQUAL(etloriginal.size() - 4, view.max_size()); + + std::fill(view.span_begin(), view.span_end(), 10); + + bool isEqual; + + isEqual = std::equal(etloriginal.begin(), etloriginal.end(), etlmodified.begin()); + CHECK(isEqual); + + isEqual = std::equal(etldata.begin(), etldata.end(), etlmodified.begin()); + CHECK(!isEqual); + } + + //************************************************************************* + TEST(test_span_begin_span_end) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + CHECK_EQUAL(etldata.begin(), view.span_begin()); + CHECK_EQUAL(etldata.begin(), cview.begin()); + + CHECK_EQUAL(etldata.end(), view.span_rbegin().base()); + CHECK_EQUAL(etldata.end(), cview.span_rbegin().base()); + + CHECK_EQUAL(etldata.end(), view.span_end()); + CHECK_EQUAL(etldata.end(), cview.span_end()); + + CHECK_EQUAL(etldata.begin(), view.span_rend().base()); + CHECK_EQUAL(etldata.begin(), cview.span_rend().base()); + } + + //************************************************************************* + TEST(test_front_back) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + CHECK_EQUAL(etldata.front(), view.front()); + CHECK_EQUAL(etldata.front(), cview.front()); + + CHECK_EQUAL(etldata.back(), view.back()); + CHECK_EQUAL(etldata.back(), cview.back()); + } + + //************************************************************************* + TEST(test_data) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + CHECK_EQUAL(etldata.data(), view.data()); + CHECK_EQUAL(etldata.data(), cview.data()); + } + + //************************************************************************* + TEST(test_index_operator) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + for (size_t i = 0UL; i < etldata.size(); ++i) + { + CHECK_EQUAL(etldata[i], view[i]); + CHECK_EQUAL(etldata[i], cview[i]); + } + } + + //************************************************************************* + TEST(test_assignment_operator) + { + View view(etldata); + CView cview = view; + + CHECK_EQUAL(etldata.size(), cview.size()); + CHECK_EQUAL(etldata.max_size(), cview.max_size()); + + bool isEqual = std::equal(cview.span_begin(), cview.span_end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_empty) + { + View view1(etldata.begin(), etldata.begin()); + CHECK(view1.empty()); + + View view2(etldata.begin(), etldata.begin() + 1); + CHECK(!view2.empty()); + } + + //************************************************************************* + TEST(test_size) + { + View view(etldata); + + CHECK_EQUAL(etldata.size(), view.size()); + } + + //************************************************************************* + TEST(test_size_bytes) + { + View view(etldata); + + CHECK_EQUAL(etldata.size() * sizeof(EtlData::value_type), view.size_bytes()); + } + + //************************************************************************* + TEST(test_swap) + { + View view1(etldata); + View view2(etldatasmaller); + + std::swap(view1, view2); + + CHECK_EQUAL(etldata.size(), view1.size()); + CHECK_EQUAL(etldatasmaller.size(), view2.size()); + + bool isEqual; + + isEqual = std::equal(view1.span_begin(), view1.span_end(), etldatasmaller.begin()); + CHECK(isEqual); + + isEqual = std::equal(view2.span_begin(), view2.span_end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_first) + { + std::vector original = { 1, 2, 3, 4, 5, 6, 7, 8 }; + std::vector first = { 1, 2, 3, 4, 5, 6 }; + View view(original); + CView cview(original); + + bool isEqual; + + auto result = view.first<6>(); + isEqual = std::equal(result.span_begin(), result.span_end(), first.begin()); + CHECK(isEqual); + CHECK_EQUAL(first.size(), result.extent); + CHECK_EQUAL(first.size(), result.size()); + + auto cresult = cview.first<6>(); + isEqual = std::equal(cresult.span_begin(), cresult.span_end(), first.begin()); + CHECK(isEqual); + CHECK_EQUAL(first.size(), cresult.extent); + CHECK_EQUAL(first.size(), cresult.size()); + } + + //************************************************************************* + TEST(test_first_2) + { + std::vector original = {1, 2, 3, 4, 5, 6, 7, 8}; + std::vector first = {1, 2, 3, 4, 5, 6}; + View view(original); + CView cview(original); + + bool isEqual; + + auto result = view.first(6); + isEqual = std::equal(result.span_begin(), result.span_end(), first.begin()); + CHECK(isEqual); + CHECK_EQUAL(first.size(), result.size()); + + auto cresult = cview.first(6); + isEqual = std::equal(cresult.span_begin(), cresult.span_end(), first.begin()); + CHECK(isEqual); + CHECK_EQUAL(first.size(), cresult.size()); + } + + //************************************************************************* + TEST(test_last) + { + std::vector original = { 1, 2, 3, 4, 5, 6, 7, 8 }; + std::vector last = { 3, 4, 5, 6, 7, 8 }; + View view(original); + CView cview(original); + + bool isEqual; + + auto result = view.last<6>(); + isEqual = std::equal(result.span_begin(), result.span_end(), last.begin()); + CHECK(isEqual); + CHECK_EQUAL(last.size(), result.extent); + CHECK_EQUAL(last.size(), result.size()); + + auto cresult = cview.last<6>(); + isEqual = std::equal(cresult.span_begin(), cresult.span_end(), last.begin()); + CHECK(isEqual); + CHECK_EQUAL(last.size(), cresult.extent); + CHECK_EQUAL(last.size(), cresult.size()); + } + + //************************************************************************* + TEST(test_last_2) + { + std::vector original = {1, 2, 3, 4, 5, 6, 7, 8}; + std::vector last = {3, 4, 5, 6, 7, 8}; + View view(original); + CView cview(original); + + bool isEqual; + + auto result = view.last(6); + isEqual = std::equal(result.span_begin(), result.span_end(), last.begin()); + CHECK(isEqual); + CHECK_EQUAL(last.size(), result.size()); + + auto cresult = cview.last(6); + isEqual = std::equal(cresult.span_begin(), cresult.span_end(), last.begin()); + CHECK(isEqual); + CHECK_EQUAL(last.size(), cresult.size()); + } + + //************************************************************************* + TEST(test_subspan) + { + std::vector original = { 1, 2, 3, 4, 5, 6, 7, 8 }; + std::vector sub1 = { 3, 4, 5, 6 }; + std::vector sub2 = { 3, 4, 5, 6, 7, 8 }; + View view(original); + CView cview(original); + + bool isEqual; + + auto span1 = view.subspan<2, 4>(); + isEqual = std::equal(span1.span_begin(), span1.span_end(), sub1.begin()); + CHECK(isEqual); + CHECK_EQUAL(sub1.size(), span1.extent); + CHECK_EQUAL(sub1.size(), span1.size()); + + auto cspan1 = cview.subspan<2, 4>(); + isEqual = std::equal(cspan1.span_begin(), cspan1.span_end(), sub1.begin()); + CHECK(isEqual); + CHECK_EQUAL(sub1.size(), cspan1.extent); + CHECK_EQUAL(sub1.size(), cspan1.size()); + + auto span2 = view.subspan<2>(); + isEqual = std::equal(span2.span_begin(), span2.span_end(), sub2.begin()); + CHECK(isEqual); + CHECK_EQUAL(etl::dynamic_extent, span2.extent); + CHECK_EQUAL(sub2.size(), span2.size()); + + auto cspan2 = cview.subspan<2>(); + isEqual = std::equal(cspan2.span_begin(), cspan2.span_end(), sub2.begin()); + CHECK(isEqual); + CHECK_EQUAL(etl::dynamic_extent, cspan2.extent); + CHECK_EQUAL(sub2.size(), cspan2.size()); + + auto span3 = view.subspan(2, 4); + isEqual = std::equal(span3.span_begin(), span3.span_end(), sub1.begin()); + CHECK(isEqual); + CHECK_EQUAL(etl::dynamic_extent, span3.extent); + CHECK_EQUAL(sub1.size(), span3.size()); + + auto cspan3 = cview.subspan(2, 4); + isEqual = std::equal(cspan3.span_begin(), cspan3.span_end(), sub1.begin()); + CHECK(isEqual); + CHECK_EQUAL(etl::dynamic_extent, cspan3.extent); + CHECK_EQUAL(sub1.size(), cspan3.size()); + + auto span4 = view.subspan(2); + isEqual = std::equal(span4.span_begin(), span4.span_end(), sub2.begin()); + CHECK(isEqual); + CHECK_EQUAL(etl::dynamic_extent, span4.extent); + CHECK_EQUAL(sub2.size(), span4.size()); + + auto cspan4 = cview.subspan(2); + isEqual = std::equal(cspan4.span_begin(), cspan4.span_end(), sub2.begin()); + CHECK(isEqual); + CHECK_EQUAL(etl::dynamic_extent, cspan4.extent); + CHECK_EQUAL(sub2.size(), cspan4.size()); + } + + //************************************************************************* + TEST(test_hash) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + size_t hashdata = etl::private_hash::generic_hash(reinterpret_cast(&etldata[0]), + reinterpret_cast(&etldata[etldata.size()])); + + size_t hashview = etl::hash()(view); + size_t hashcview = etl::hash()(cview); + + CHECK_EQUAL(hashdata, hashview); + CHECK_EQUAL(hashdata, hashcview); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_c_array) + { + int data[] = { 1, 2, 3, 4 }; + + etl::circular_span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_template_deduction_guide_for_std_array) + { + std::array data = { 1, 2, 3, 4 }; + + etl::circular_span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } +#endif + + //************************************************************************* + TEST(test_template_deduction_guide_for_etl_array) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::circular_span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_iterators) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::circular_span s{ data.begin(), data.end() }; + + CHECK_EQUAL(etl::dynamic_extent, s.extent); + CHECK_EQUAL(4U, s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_iterator_and_size) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::circular_span s{ data.begin(), data.size() }; + + CHECK_EQUAL(etl::dynamic_extent, s.extent); + CHECK_EQUAL(4U, s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_circular_iterator_pre_increment) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + etl::circular_span span{ data }; + + etl::circular_span::iterator csi = span.begin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i], *++csi); + } + } + + //************************************************************************* + TEST(test_circular_iterator_pre_increment_for_subspan) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2 }; + + etl::circular_span span{ data }; + etl::circular_span subspan = span.subspan<2, 4>(); + + etl::circular_span::iterator csi = subspan.begin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i], *++csi); + } + } + + //************************************************************************* + TEST(test_circular_iterator_post_increment) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + etl::circular_span span{ data }; + + etl::circular_span::iterator csi = span.begin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i % std::size(expected)], *csi++); + } + } + + //************************************************************************* + TEST(test_circular_iterator_post_increment_for_subspan) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5 }; + + etl::circular_span span{ data }; + etl::circular_span subspan = span.subspan<2, 4>(); + + etl::circular_span::iterator csi = subspan.begin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i], *csi++); + } + } + + //************************************************************************* + TEST(test_circular_reverse_iterator_pre_increment) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9 }; + + etl::circular_span span{ data }; + + etl::circular_span::reverse_iterator csi = span.rbegin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i % std::size(expected)], *++csi); + } + } + + //************************************************************************* + TEST(test_circular_reverse_iterator_pre_increment_for_subspan) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5 }; + + etl::circular_span span{ data }; + etl::circular_span subspan = span.subspan<2, 4>(); + + etl::circular_span::reverse_iterator csi = subspan.rbegin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i % std::size(expected)], *++csi); + } + } + + //************************************************************************* + TEST(test_circular_reverse_iterator_post_increment) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + + etl::circular_span span{ data }; + + etl::circular_span::reverse_iterator csi = span.rbegin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i % std::size(expected)], *csi++); + } + } + + //************************************************************************* + TEST(test_circular_reverse_iterator_post_increment_for_subspan) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2 }; + + etl::circular_span span{ data }; + etl::circular_span subspan = span.subspan<2, 4>(); + + etl::circular_span::reverse_iterator csi = subspan.rbegin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i % std::size(expected)], *csi++); + } + } + + //************************************************************************* + TEST(test_operator_plus_equals) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + etl::circular_span span{ data }; + + for (int step = 1; step < 20; ++step) + { + etl::circular_span::iterator csi = span.begin(); + + for (int i = 0; i < 20; i += step) + { + CHECK_EQUAL(expected[i % 10], *csi); + csi += step; + } + } + } + + //************************************************************************* + TEST(test_operator_plus) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + etl::circular_span span{ data }; + + for (int step = 1; step < 20; ++step) + { + etl::circular_span::iterator csi = span.begin(); + + for (int i = 0; i < 20; i += step) + { + CHECK_EQUAL(expected[i % 10], *csi); + csi = csi + step; + } + } + } + + //************************************************************************* + TEST(test_operator_minus_equals) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 0, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + + etl::circular_span span{ data }; + + for (int step = 1; step < 20; ++step) + { + etl::circular_span::iterator csi = span.begin(); + + for (int i = 0; i < 20; i += step) + { + CHECK_EQUAL(expected[i % 10], *csi); + csi -= step; + } + } + } + + //************************************************************************* + TEST(test_operator_minus) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 0, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + + etl::circular_span span{ data }; + + for (int step = 1; step < 20; ++step) + { + etl::circular_span::iterator csi = span.begin(); + + for (int i = 0; i < 20; i += step) + { + CHECK_EQUAL(expected[i % 10], *csi); + csi = csi - step; + } + } + } + }; +} diff --git a/test/test_circular_span_fixed_extent.cpp b/test/test_circular_span_fixed_extent.cpp new file mode 100644 index 00000000..c13ebd94 --- /dev/null +++ b/test/test_circular_span_fixed_extent.cpp @@ -0,0 +1,859 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2022 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/circular_span.h" +#include "etl/array.h" + +#include +#include +#include +#include + +namespace +{ + SUITE(test_circular_span_fixed_extent) + { + static const size_t SIZE = 10UL; + + typedef etl::array EtlData; + typedef std::array StlData; + typedef std::vector StlVData; + + typedef etl::circular_span View; + typedef etl::circular_span CView; + + EtlData etldata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + StlData stldata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + StlVData stlvdata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + EtlData etldatasmaller = { 0, 1, 2, 3, 4, 5, 5, 7, 8, 9 }; + + EtlData etloriginal = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + EtlData etlmodified = { 0, 1, 10, 10, 10, 10, 10, 10, 8, 9 }; + + const EtlData cetldata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + const StlData cstldata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + const StlVData cstlvdata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + int cdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int* pcdata = cdata; + + const int ccdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + const int* pccdata = ccdata; + + //************************************************************************* + TEST(test_default_constructor) + { + View view; + + CHECK_EQUAL(10U, view.size()); + CHECK_EQUAL(10U, view.max_size()); + CHECK(!view.empty()); + } + + //************************************************************************* + TEST(test_constructor_etl_array_1) + { + View view(etldata); + + CHECK_EQUAL(etldata.size(), view.size()); + CHECK_EQUAL(etldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_etl_array_1_const) + { + CView view(cetldata); + + CHECK_EQUAL(cetldata.size(), view.size()); + CHECK_EQUAL(cetldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), cetldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_etl_array_2) + { + View view(etldata.begin(), etldata.end()); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_etl_array_2_const) + { + CView view(cetldata.begin(), cetldata.end()); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), cetldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_array_1) + { + View view(stldata); + + CHECK_EQUAL(stldata.size(), view.size()); + CHECK_EQUAL(stldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), stldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_array_1_const) + { + CView view(cstldata); + + CHECK_EQUAL(cstldata.size(), view.size()); + CHECK_EQUAL(cstldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), cstldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_array_2) + { + View view(stldata.begin(), stldata.end()); + + CHECK_EQUAL(stldata.size(), view.size()); + CHECK_EQUAL(stldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), stldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_array_2_const) + { + CView view(cstldata.begin(), cstldata.end()); + + CHECK_EQUAL(cstldata.size(), view.size()); + CHECK_EQUAL(cstldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), cstldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_vector_1) + { + View view(stlvdata); + + CHECK_EQUAL(stlvdata.size(), view.size()); + CHECK_EQUAL(stlvdata.size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), stlvdata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_vector_1_const) + { + CView view(cstlvdata); + + CHECK_EQUAL(cstlvdata.size(), view.size()); + CHECK_EQUAL(cstlvdata.size(), view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), cstlvdata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_c_array_1) + { + View view(pcdata, SIZE); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), pcdata); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_c_array_1_const) + { + CView view(pccdata, SIZE); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), pccdata); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_c_array_2) + { + View view(cdata); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), cdata); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_c_array_2_const) + { + CView view(ccdata); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), ccdata); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_implicit_constructor_c_array_2) + { + CView view; + + view = ccdata; + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.span_begin(), view.span_end(), ccdata); + CHECK(isEqual); + } + +#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED) + //************************************************************************* + TEST(test_cpp17_deduced_constructor) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + etl::circular_span span1{ data }; + etl::circular_span span2{ data.begin(), data.end() }; + etl::circular_span span3{ data.begin(), data.size() }; + etl::circular_span span4{ span1 }; + + int c_array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::circular_span span5{ c_array }; + + bool isEqual = false; + + isEqual = std::equal(span1.span_begin(), span1.span_end(), data.begin()); + CHECK(isEqual); + + isEqual = std::equal(span2.span_begin(), span2.span_end(), data.begin()); + CHECK(isEqual); + + isEqual = std::equal(span3.span_begin(), span3.span_end(), data.begin()); + CHECK(isEqual); + + isEqual = std::equal(span4.span_begin(), span4.span_end(), data.begin()); + CHECK(isEqual); + + isEqual = std::equal(span5.span_begin(), span5.span_end(), c_array); + CHECK(isEqual); + } +#endif + + //************************************************************************* + TEST(test_assign_from_span) + { + View view1(etldata); + View view2; + + CView cview1(etldata); + CView cview2; + + view2 = view1; + cview2 = cview1; + + CHECK_EQUAL(view1.size(), view2.size()); + CHECK_EQUAL(view1.max_size(), view2.max_size()); + + CHECK_EQUAL(cview1.size(), cview2.size()); + CHECK_EQUAL(cview1.max_size(), cview2.max_size()); + + bool isEqual; + + isEqual = std::equal(view1.span_begin(), view1.span_end(), view2.begin()); + CHECK(isEqual); + + isEqual = std::equal(cview1.span_begin(), cview1.span_end(), cview2.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_span_begin_span_end) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + CHECK_EQUAL(etldata.begin(), view.span_begin()); + CHECK_EQUAL(etldata.begin(), cview.begin()); + + CHECK_EQUAL(etldata.end(), view.span_rbegin().base()); + CHECK_EQUAL(etldata.end(), cview.span_rbegin().base()); + + CHECK_EQUAL(etldata.end(), view.span_end()); + CHECK_EQUAL(etldata.end(), cview.span_end()); + + CHECK_EQUAL(etldata.begin(), view.span_rend().base()); + CHECK_EQUAL(etldata.begin(), cview.span_rend().base()); + } + + //************************************************************************* + TEST(test_front_back) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + CHECK_EQUAL(etldata.front(), view.front()); + CHECK_EQUAL(etldata.front(), cview.front()); + + CHECK_EQUAL(etldata.back(), view.back()); + CHECK_EQUAL(etldata.back(), cview.back()); + } + + //************************************************************************* + TEST(test_data) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + CHECK_EQUAL(etldata.data(), view.data()); + CHECK_EQUAL(etldata.data(), cview.data()); + } + + //************************************************************************* + TEST(test_index_operator) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + for (size_t i = 0UL; i < etldata.size(); ++i) + { + CHECK_EQUAL(etldata[i], view[i]); + CHECK_EQUAL(etldata[i], cview[i]); + } + } + + //************************************************************************* + TEST(test_assignment_operator) + { + View view(etldata); + CView cview = view; + + CHECK_EQUAL(etldata.size(), cview.size()); + CHECK_EQUAL(etldata.max_size(), cview.max_size()); + + bool isEqual = std::equal(cview.span_begin(), cview.span_end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_empty) + { + View view1(etldata.begin(), etldata.begin()); + CHECK(!view1.empty()); + + View view2(etldata.begin(), etldata.begin() + 1); + CHECK(!view2.empty()); + } + + //************************************************************************* + TEST(test_size) + { + View view(etldata); + + CHECK_EQUAL(etldata.size(), view.size()); + } + + //************************************************************************* + TEST(test_size_bytes) + { + View view(etldata); + + CHECK_EQUAL(etldata.size() * sizeof(EtlData::value_type), view.size_bytes()); + } + + //************************************************************************* + TEST(test_swap) + { + View view1(etldata); + View view2(etldatasmaller); + + std::swap(view1, view2); + + CHECK_EQUAL(etldata.size(), view1.size()); + CHECK_EQUAL(etldatasmaller.size(), view2.size()); + + bool isEqual; + + isEqual = std::equal(view1.span_begin(), view1.span_end(), etldatasmaller.begin()); + CHECK(isEqual); + + isEqual = std::equal(view2.span_begin(), view2.span_end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_first) + { + std::vector original = { 1, 2, 3, 4, 5, 6, 7, 8 }; + std::vector first = { 1, 2, 3, 4, 5, 6 }; + View view(original); + CView cview(original); + + bool isEqual; + + auto result = view.first<6>(); + isEqual = std::equal(result.span_begin(), result.span_end(), first.begin()); + CHECK(isEqual); + CHECK_EQUAL(first.size(), result.extent); + CHECK_EQUAL(first.size(), result.size()); + + auto cresult = cview.first<6>(); + isEqual = std::equal(cresult.span_begin(), cresult.span_end(), first.begin()); + CHECK(isEqual); + CHECK_EQUAL(first.size(), cresult.extent); + CHECK_EQUAL(first.size(), cresult.size()); + } + + //************************************************************************* + TEST(test_first_2) + { + std::vector original = {1, 2, 3, 4, 5, 6, 7, 8}; + std::vector first = {1, 2, 3, 4, 5, 6}; + View view(original); + CView cview(original); + + bool isEqual; + + auto result = view.first(6); + isEqual = std::equal(result.span_begin(), result.span_end(), first.begin()); + CHECK(isEqual); + CHECK_EQUAL(first.size(), result.size()); + + auto cresult = cview.first(6); + isEqual = std::equal(cresult.span_begin(), cresult.span_end(), first.begin()); + CHECK(isEqual); + CHECK_EQUAL(first.size(), cresult.size()); + } + + //************************************************************************* + TEST(test_last) + { + std::vector original = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector last = { 4, 5, 6, 7, 8, 9 }; + View view(original); + CView cview(original); + + bool isEqual; + + auto result = view.last<6>(); + isEqual = std::equal(result.span_begin(), result.span_end(), last.begin()); + CHECK(isEqual); + CHECK_EQUAL(last.size(), result.extent); + CHECK_EQUAL(last.size(), result.size()); + + auto cresult = cview.last<6>(); + isEqual = std::equal(cresult.span_begin(), cresult.span_end(), last.begin()); + CHECK(isEqual); + CHECK_EQUAL(last.size(), cresult.extent); + CHECK_EQUAL(last.size(), cresult.size()); + } + + //************************************************************************* + TEST(test_last_2) + { + std::vector original = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector last = { 4, 5, 6, 7, 8, 9 }; + View view(original); + CView cview(original); + + bool isEqual; + + auto result = view.last(6); + isEqual = std::equal(result.span_begin(), result.span_end(), last.begin()); + CHECK(isEqual); + CHECK_EQUAL(last.size(), result.size()); + + auto cresult = cview.last(6); + isEqual = std::equal(cresult.span_begin(), cresult.span_end(), last.begin()); + CHECK(isEqual); + CHECK_EQUAL(last.size(), cresult.size()); + } + + //************************************************************************* + TEST(test_subspan) + { + std::vector original = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector sub1 = { 2, 3, 4, 5 }; + std::vector sub2 = { 2, 3, 4, 5, 6, 7 }; + View view(original); + CView cview(original); + + bool isEqual; + + auto span1 = view.subspan<2, 4>(); + isEqual = std::equal(span1.span_begin(), span1.span_begin() + sub1.size(), sub1.begin()); + CHECK(isEqual); + + auto cspan1 = cview.subspan<2, 4>(); + isEqual = std::equal(cspan1.span_begin(), cspan1.span_begin() + sub1.size(), sub1.begin()); + CHECK(isEqual); + + auto span2 = view.subspan<2>(); + isEqual = std::equal(span2.span_begin(), span2.span_begin() + sub2.size(), sub2.begin()); + CHECK(isEqual); + + auto cspan2 = cview.subspan<2>(); + isEqual = std::equal(cspan2.span_begin(), cspan2.span_begin() + sub2.size(), sub2.begin()); + CHECK(isEqual); + + auto span3 = view.subspan(2, 4); + isEqual = std::equal(span3.span_begin(), span3.span_begin() + sub1.size(), sub1.begin()); + CHECK(isEqual); + + auto cspan3 = cview.subspan(2, 4); + isEqual = std::equal(cspan3.span_begin(), cspan3.span_begin() + sub1.size(), sub1.begin()); + CHECK(isEqual); + + auto span4 = view.subspan(2); + isEqual = std::equal(span4.span_begin(), span4.span_begin() + sub2.size(), sub2.begin()); + CHECK(isEqual); + + auto cspan4 = cview.subspan(2); + isEqual = std::equal(cspan4.span_begin(), cspan4.span_begin() + sub2.size(), sub2.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_hash) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + size_t hashdata = etl::private_hash::generic_hash(reinterpret_cast(&etldata[0]), + reinterpret_cast(&etldata[etldata.size()])); + + size_t hashview = etl::hash()(view); + size_t hashcview = etl::hash()(cview); + + CHECK_EQUAL(hashdata, hashview); + CHECK_EQUAL(hashdata, hashcview); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_c_array) + { + int data[] = { 1, 2, 3, 4 }; + + etl::circular_span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_template_deduction_guide_for_std_array) + { + std::array data = { 1, 2, 3, 4 }; + + etl::circular_span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } +#endif + + //************************************************************************* + TEST(test_template_deduction_guide_for_etl_array) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::circular_span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_iterators) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::circular_span s{ data.begin(), data.end() }; + + CHECK_EQUAL(etl::dynamic_extent, s.extent); + CHECK_EQUAL(4U, s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_iterator_and_size) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::circular_span s{ data.begin(), data.size() }; + + CHECK_EQUAL(etl::dynamic_extent, s.extent); + CHECK_EQUAL(4U, s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_circular_iterator_pre_increment) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + etl::circular_span span{ data }; + + etl::circular_span::iterator csi = span.begin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i], *++csi); + } + } + + //************************************************************************* + TEST(test_circular_iterator_pre_increment_for_subspan) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2 }; + + etl::circular_span span{ data }; + etl::circular_span subspan = span.subspan<2, 4>(); + + etl::circular_span::iterator csi = subspan.begin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i], *++csi); + } + } + + //************************************************************************* + TEST(test_circular_iterator_post_increment) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + etl::circular_span span{ data }; + + etl::circular_span::iterator csi = span.begin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i % std::size(expected)], *csi++); + } + } + + //************************************************************************* + TEST(test_circular_iterator_post_increment_for_subspan) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5 }; + + etl::circular_span span{ data }; + etl::circular_span subspan = span.subspan<2, 4>(); + + etl::circular_span::iterator csi = subspan.begin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i], *csi++); + } + } + + //************************************************************************* + TEST(test_circular_reverse_iterator_pre_increment) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9 }; + + etl::circular_span span{ data }; + + etl::circular_span::reverse_iterator csi = span.rbegin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i % std::size(expected)], *++csi); + } + } + + //************************************************************************* + TEST(test_circular_reverse_iterator_pre_increment_for_subspan) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5 }; + + etl::circular_span span{ data }; + etl::circular_span subspan = span.subspan<2, 4>(); + + etl::circular_span::reverse_iterator csi = subspan.rbegin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i % std::size(expected)], *++csi); + } + } + + //************************************************************************* + TEST(test_circular_reverse_iterator_post_increment) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + + etl::circular_span span{ data }; + + etl::circular_span::reverse_iterator csi = span.rbegin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i % std::size(expected)], *csi++); + } + } + + //************************************************************************* + TEST(test_circular_reverse_iterator_post_increment_for_subspan) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2 }; + + etl::circular_span span{ data }; + etl::circular_span subspan = span.subspan<2, 4>(); + + etl::circular_span::reverse_iterator csi = subspan.rbegin(); + + for (int i = 0; i < 20; ++i) + { + CHECK_EQUAL(expected[i % std::size(expected)], *csi++); + } + } + + //************************************************************************* + TEST(test_operator_plus_equals) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + etl::circular_span span{ data }; + + for (int step = 1; step < 20; ++step) + { + etl::circular_span::iterator csi = span.begin(); + + for (int i = 0; i < 20; i += step) + { + CHECK_EQUAL(expected[i % 10], *csi); + csi += step; + } + } + } + + //************************************************************************* + TEST(test_operator_plus) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + etl::circular_span span{ data }; + + for (int step = 1; step < 20; ++step) + { + etl::circular_span::iterator csi = span.begin(); + + for (int i = 0; i < 20; i += step) + { + CHECK_EQUAL(expected[i % 10], *csi); + csi = csi + step; + } + } + } + + //************************************************************************* + TEST(test_operator_minus_equals) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 0, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + + etl::circular_span span{ data }; + + for (int step = 1; step < 20; ++step) + { + etl::circular_span::iterator csi = span.begin(); + + for (int i = 0; i < 20; i += step) + { + CHECK_EQUAL(expected[i % 10], *csi); + csi -= step; + } + } + } + + //************************************************************************* + TEST(test_operator_minus) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::array expected{ 0, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + + etl::circular_span span{ data }; + + for (int step = 1; step < 20; ++step) + { + etl::circular_span::iterator csi = span.begin(); + + for (int i = 0; i < 20; i += step) + { + CHECK_EQUAL(expected[i % 10], *csi); + csi = csi - step; + } + } + } + }; +} diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index c0fab783..1500d2ea 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -2387,6 +2387,7 @@ + @@ -11299,6 +11300,8 @@ + + diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index 5ca5a2fb..898d19c0 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -1332,6 +1332,9 @@ ETL\Containers + + ETL\Utilities + @@ -3359,6 +3362,12 @@ Tests\Sanity Checks\Source + + Tests\Containers + + + Tests\Containers +