circular_span first draft

This commit is contained in:
John Wellbelove 2022-09-06 10:59:49 +01:00
parent 25adb3c68c
commit dc0ab72e09
10 changed files with 2991 additions and 369 deletions

View File

@ -216,7 +216,7 @@ namespace etl
typename etl::enable_if<etl::is_integral<T>::value || etl::is_floating_point<T>::value, void>::type
write_unchecked(const etl::span<T>& range)
{
typename etl::span<T>::const_iterator itr = range.begin();
typename etl::span<T>::iterator itr = range.begin();
while (itr != range.end())
{

View File

@ -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 <typename TIterator, typename TTag = typename etl::iterator_traits<TIterator>::iterator_category>
class circular_iterator_impl
{
ETL_STATIC_ASSERT((etl::is_same<TTag, ETL_OR_STD::input_iterator_tag>::value_type), "input_iterator_catagory is not supported by circular_iterator");
ETL_STATIC_ASSERT((etl::is_same<TTag, ETL_OR_STD::output_iterator_tag>::value_type), "output_iterator_catagory is not supported by circular_iterator");
};
//***************************************************************************
/// A circular iterator class.
/// Specialisation for forward iterators.
///\ingroup iterator
/// //***************************************************************************
template <typename TIterator>
class circular_iterator_impl<TIterator, ETL_OR_STD::forward_iterator_tag>
: public circular_iterator_common<TIterator>
{
private:
typedef circular_iterator_common<TIterator> 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 <typename T>
ETL_CONSTEXPR14 circular_iterator_impl(const etl::span<T>& span_)
: circular_iterator_common(span_.begin(), span_.end(), span_.begin())
{
}
//***************************************************************************
/// Construct from start + span.
//***************************************************************************
template <typename T>
ETL_CONSTEXPR14 circular_iterator_impl(const etl::span<T>& 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 <typename TIterator>
class circular_iterator_impl<TIterator, ETL_OR_STD::bidirectional_iterator_tag>
: public circular_iterator_common<TIterator>
{
private:
typedef circular_iterator_common<TIterator> 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 <typename T>
ETL_CONSTEXPR14 circular_iterator_impl(const etl::span<T>& span_)
: circular_iterator_common(span_.begin(), span_.end(), span_.begin())
{
}
//***************************************************************************
/// Construct from start + span.
//***************************************************************************
template <typename T>
ETL_CONSTEXPR14 circular_iterator_impl(const etl::span<T>& 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<TIterator> 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 <typename TIterator>
class circular_iterator_impl<TIterator, ETL_OR_STD::random_access_iterator_tag>
: public circular_iterator_common<TIterator>
{
private:
typedef circular_iterator_common<TIterator> 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 <typename T>
ETL_CONSTEXPR14 circular_iterator_impl(const etl::span<T>& span_)
: circular_iterator_common(span_.begin(), span_.end(), span_.begin())
{
}
//***************************************************************************
/// Construct from start + span.
//***************************************************************************
template <typename T>
ETL_CONSTEXPR14 circular_iterator_impl(const etl::span<T>& 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<TIterator> 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<TIterator>::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 <typename TIterator, typename TTag = typename etl::iterator_traits<TIterator>::iterator_category>
class circular_iterator
{
ETL_STATIC_ASSERT((etl::is_same<TTag, ETL_OR_STD::input_iterator_tag>::value_type), "input_iterator_catagory is not supported by circular_iterator");
ETL_STATIC_ASSERT((etl::is_same<TTag, ETL_OR_STD::output_iterator_tag>::value_type), "output_iterator_catagory is not supported by circular_iterator");
};
//***************************************************************************
/// A circular iterator class.
/// Specialisation for forward iterators.
///\ingroup iterator
/// //***************************************************************************
//**************************************************************************
template <typename TIterator>
class circular_iterator<TIterator, ETL_OR_STD::forward_iterator_tag>
: public etl::private_circular_iterator::circular_iterator_common<TIterator>
class circular_iterator ETL_FINAL
: public etl::private_circular_iterator::circular_iterator_impl<TIterator, typename etl::iterator_traits<TIterator>::iterator_category>
{
private:
typedef etl::private_circular_iterator::circular_iterator_common<TIterator> base_t;
typedef typename etl::private_circular_iterator::circular_iterator_impl<TIterator, typename etl::iterator_traits<TIterator>::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 <typename T>
ETL_CONSTEXPR14 circular_iterator(const etl::span<T>& 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 <typename T>
ETL_CONSTEXPR14 circular_iterator(const etl::span<T>& 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 <typename TIterator>
class circular_iterator<TIterator, ETL_OR_STD::bidirectional_iterator_tag>
: public etl::private_circular_iterator::circular_iterator_common<TIterator>
{
private:
typedef etl::private_circular_iterator::circular_iterator_common<TIterator> 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 <typename T>
ETL_CONSTEXPR14 circular_iterator(const etl::span<T>& span_)
: circular_iterator_common(span_.begin(), span_.end(), span_.begin())
{
}
//***************************************************************************
/// Construct from start + span.
//***************************************************************************
template <typename T>
ETL_CONSTEXPR14 circular_iterator(const etl::span<T>& 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<TIterator> 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 <typename TIterator>
class circular_iterator<TIterator, ETL_OR_STD::random_access_iterator_tag>
: public etl::private_circular_iterator::circular_iterator_common<TIterator>
{
private:
typedef etl::private_circular_iterator::circular_iterator_common<TIterator> 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 <typename T>
ETL_CONSTEXPR14 circular_iterator(const etl::span<T>& span_)
: circular_iterator_common(span_.begin(), span_.end(), span_.begin())
{
}
//***************************************************************************
/// Construct from start + span.
//***************************************************************************
template <typename T>
ETL_CONSTEXPR14 circular_iterator(const etl::span<T>& 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<TIterator> 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<TIterator>::difference_type offset)
{
return operator +=(-offset);
}
};
//*****************************************************************************

774
include/etl/circular_span.h Normal file
View File

@ -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 <array>
#endif
///\defgroup circular_span circular_span
///\ingroup containers
namespace etl
{
//***************************************************************************
/// Circular Span - Fixed Extent
//***************************************************************************
template <typename T, size_t Extent = etl::dynamic_extent>
class circular_span
{
public:
typedef T element_type;
typedef typename etl::remove_cv<T>::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<pointer> iterator;
typedef etl::circular_iterator<ETL_OR_STD::reverse_iterator<pointer> > reverse_iterator;
typedef typename etl::span<T>::iterator span_iterator;
typedef typename etl::span<T>::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 <typename TIterator, typename TSize>
ETL_CONSTEXPR circular_span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT
: linear_span(begin_, size_)
{
}
//*************************************************************************
/// Construct from iterators
//*************************************************************************
template <typename TIterator>
ETL_CONSTEXPR circular_span(const TIterator begin_, const TIterator end_)
: linear_span(begin_, end_)
{
}
//*************************************************************************
/// Construct from C array
//*************************************************************************
template<size_t ARRAY_SIZE>
ETL_CONSTEXPR circular_span(element_type(&begin_)[ARRAY_SIZE]) ETL_NOEXCEPT
: linear_span(begin_)
{
}
//*************************************************************************
/// Construct from etl::array.
//*************************************************************************
template <typename U, size_t N>
ETL_CONSTEXPR circular_span(etl::array<U, N>& a) ETL_NOEXCEPT
: linear_span(a)
{
}
//*************************************************************************
/// Construct from etl::array.
//*************************************************************************
template <typename U, size_t N>
ETL_CONSTEXPR circular_span(const etl::array<U, N>& a) ETL_NOEXCEPT
: linear_span(a)
{
}
#if ETL_USING_STL && ETL_USING_CPP11
//*************************************************************************
/// Construct from std::array.
//*************************************************************************
template <typename U, size_t N>
ETL_CONSTEXPR circular_span(std::array<U, N>& a) ETL_NOEXCEPT
: linear_span(a)
{
}
//*************************************************************************
/// Construct from std::array.
//*************************************************************************
template <typename U, size_t N>
ETL_CONSTEXPR circular_span(const std::array<U, N>& 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 <typename TContainer>
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 <typename TContainer>
circular_span(TContainer& a) ETL_NOEXCEPT
: linear_span(a)
{
}
//*************************************************************************
/// Construct from a container or other type that supports
/// data() and size() member functions.
//*************************************************************************
template <typename TContainer>
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 <b>true</b> 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 <size_t Count>
ETL_NODISCARD ETL_CONSTEXPR etl::circular_span<element_type, Count> first() const ETL_NOEXCEPT
{
return etl::circular_span<element_type, Count>(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<element_type, etl::dynamic_extent> first(size_t count) const ETL_NOEXCEPT
{
return etl::circular_span<element_type, etl::dynamic_extent>(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 <size_t Count>
ETL_NODISCARD ETL_CONSTEXPR etl::circular_span<element_type, Count> last() const ETL_NOEXCEPT
{
return etl::circular_span<element_type, Count>(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<element_type, etl::dynamic_extent> last(size_t count) const ETL_NOEXCEPT
{
return etl::circular_span<element_type, etl::dynamic_extent>((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 <const size_t Offset, size_t Count = etl::dynamic_extent>
ETL_NODISCARD ETL_CONSTEXPR
etl::circular_span<element_type, Count != etl::dynamic_extent ? Count : Extent - Offset> subspan() const ETL_NOEXCEPT
{
return (Count == etl::dynamic_extent) ? etl::circular_span<element_type, Count != etl::dynamic_extent ? Count : Extent - Offset>(linear_span.data() + Offset, (linear_span.data() + Extent))
: etl::circular_span<element_type, Count != etl::dynamic_extent ? Count : Extent - Offset>(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 <const size_t Offset, size_t Count>
etl::circular_span<element_type, Count != etl::dynamic_extent ? Count : Extent - Offset> subspan() const
{
if (Count == etl::dynamic_extent)
{
return etl::circular_span<element_type, (Count != etl::dynamic_extent ? Count : Extent - Offset)>(linear_span.data() + Offset, (linear_span.data() + Extent));
}
else
{
return etl::circular_span<element_type, Count != etl::dynamic_extent ? Count : Extent - Offset>(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<element_type, etl::dynamic_extent> subspan(size_t offset, size_t count = etl::dynamic_extent) const ETL_NOEXCEPT
{
return (count == etl::dynamic_extent) ? etl::circular_span<element_type, etl::dynamic_extent>(linear_span.begin() + offset, (linear_span.begin() + Extent))
: etl::circular_span<element_type, etl::dynamic_extent>(linear_span.begin() + offset, linear_span.begin() + offset + count);
}
private:
etl::span<T, Extent> linear_span;
};
//***************************************************************************
/// Circular Span - Dynamic Extent
//***************************************************************************
template <typename T>
class circular_span<T, etl::dynamic_extent>
{
public:
typedef T element_type;
typedef typename etl::remove_cv<T>::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<pointer> iterator;
typedef etl::circular_iterator<ETL_OR_STD::reverse_iterator<pointer> > reverse_iterator;
typedef typename etl::span<T>::iterator span_iterator;
typedef typename etl::span<T>::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 <typename TIterator, typename TSize>
ETL_CONSTEXPR circular_span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT
: linear_span(begin_, size_)
{
}
//*************************************************************************
/// Construct from iterators
//*************************************************************************
template <typename TIterator>
ETL_CONSTEXPR circular_span(const TIterator begin_, const TIterator end_)
: linear_span(begin_, end_)
{
}
//*************************************************************************
/// Construct from C array
//*************************************************************************
template<size_t ARRAY_SIZE>
ETL_CONSTEXPR circular_span(element_type(&begin_)[ARRAY_SIZE]) ETL_NOEXCEPT
: linear_span(begin_)
{
}
//*************************************************************************
/// Construct from etl::array.
//*************************************************************************
template <typename U, size_t N>
ETL_CONSTEXPR circular_span(etl::array<U, N>& a) ETL_NOEXCEPT
: linear_span(a)
{
}
//*************************************************************************
/// Construct from etl::array.
//*************************************************************************
template <typename U, size_t N>
ETL_CONSTEXPR circular_span(const etl::array<U, N>& a) ETL_NOEXCEPT
: linear_span(a)
{
}
#if ETL_USING_STL && ETL_USING_CPP11
//*************************************************************************
/// Construct from std::array.
//*************************************************************************
template <typename U, size_t N>
ETL_CONSTEXPR circular_span(std::array<U, N>& a) ETL_NOEXCEPT
: linear_span(a)
{
}
//*************************************************************************
/// Construct from std::array.
//*************************************************************************
template <typename U, size_t N>
ETL_CONSTEXPR circular_span(const std::array<U, N>& 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 <typename TContainer>
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 <typename TContainer>
circular_span(TContainer& a) ETL_NOEXCEPT
: linear_span(a)
{
}
//*************************************************************************
/// Construct from a container or other type that supports
/// data() and size() member functions.
//*************************************************************************
template <typename TContainer>
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 <b>true</b> 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 <size_t Count>
ETL_NODISCARD ETL_CONSTEXPR etl::circular_span<element_type, Count> first() const ETL_NOEXCEPT
{
return etl::circular_span<element_type, Count>(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<element_type, etl::dynamic_extent> first(size_t count) const ETL_NOEXCEPT
{
return etl::circular_span<element_type, etl::dynamic_extent>(linear_span.begin(), linear_span.begin() + count);
}
//*************************************************************************
/// Obtains a span that is a view over the last COUNT elements of this span.
//*************************************************************************
template <size_t Count>
ETL_NODISCARD ETL_CONSTEXPR etl::circular_span<element_type, Count> last() const ETL_NOEXCEPT
{
return etl::circular_span<element_type, Count>(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<element_type, etl::dynamic_extent> last(size_t count) const ETL_NOEXCEPT
{
return etl::circular_span<element_type, etl::dynamic_extent>(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 <const size_t Offset, size_t Count = etl::dynamic_extent>
ETL_NODISCARD ETL_CONSTEXPR
etl::circular_span<element_type, Count != etl::dynamic_extent ? Count : etl::dynamic_extent> subspan() const ETL_NOEXCEPT
{
return (Count == etl::dynamic_extent) ? etl::circular_span<element_type, Count != etl::dynamic_extent ? Count : etl::dynamic_extent>(linear_span.begin() + Offset, linear_span.end())
: etl::circular_span<element_type, Count != etl::dynamic_extent ? Count : etl::dynamic_extent>(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 <const size_t Offset, size_t Count>
etl::circular_span<element_type, Count != etl::dynamic_extent ? Count : etl::dynamic_extent> subspan() const
{
if (Count == etl::dynamic_extent)
{
return etl::circular_span<element_type, Count != etl::dynamic_extent ? Count : etl::dynamic_extent>(linear_span.begin() + Offset, linear_span.end());
}
else
{
return etl::circular_span<element_type, Count != etl::dynamic_extent ? Count : etl::dynamic_extent>(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<element_type, etl::dynamic_extent> subspan(size_t offset, size_t count = etl::dynamic_extent) const ETL_NOEXCEPT
{
return (count == etl::dynamic_extent) ? etl::circular_span<element_type, etl::dynamic_extent>(linear_span.begin() + offset, linear_span.end())
: etl::circular_span<element_type, etl::dynamic_extent>(linear_span.begin() + offset, linear_span.begin() + offset + count);
}
private:
etl::span<T, etl::dynamic_extent> linear_span;
};
//*************************************************************************
/// Template deduction guides.
//*************************************************************************
#if ETL_USING_CPP17
template <typename TIterator>
circular_span(const TIterator begin_, const TIterator end_)
->circular_span<etl::remove_pointer_t<TIterator>, etl::dynamic_extent>;
template <typename TIterator, typename TSize>
circular_span(const TIterator begin_, const TSize size_)
->circular_span<etl::remove_pointer_t<TIterator>, etl::dynamic_extent>;
template <typename T, size_t N>
circular_span(T(&)[N])
-> circular_span<T, N>;
template <typename T, size_t N>
circular_span(etl::array<T, N>&)
-> circular_span<T, N>;
template <typename T, size_t N>
circular_span(const etl::array<T, N>&)
-> circular_span<const T, N>;
#if ETL_USING_STL
template <typename T, size_t N>
circular_span(std::array<T, N>&)
->circular_span<T, N>;
template <typename T, size_t N>
circular_span(const std::array<T, N>&)
->circular_span<const T, N>;
#endif
#endif
//*************************************************************************
/// Hash function.
//*************************************************************************
#if ETL_USING_8BIT_TYPES
template <typename T, size_t Extent>
struct hash<etl::circular_span<T, Extent> >
{
size_t operator()(const etl::circular_span<T>& view) const
{
return etl::private_hash::generic_hash<size_t>(reinterpret_cast<const uint8_t*>(&view[0]),
reinterpret_cast<const uint8_t*>(&view[view.size()]));
}
};
#endif
}
#endif

View File

@ -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())
{

View File

@ -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<iterator> reverse_iterator;
typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
static ETL_CONSTANT size_t extent = etl::dynamic_extent;

View File

@ -30,7 +30,6 @@ SOFTWARE.
#include <list>
#include <forward_list>
#include <array>
#include <ostream>
#include "etl/circular_iterator.h"

View File

@ -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 <array>
#include <vector>
#include <algorithm>
#include <iterator>
namespace
{
SUITE(test_circular_span_dynamic_extent)
{
static const size_t SIZE = 10UL;
typedef etl::array<int, SIZE> EtlData;
typedef std::array<int, SIZE> StlData;
typedef std::vector<int> StlVData;
typedef etl::circular_span<int> View;
typedef etl::circular_span<const int> 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<int> original = { 1, 2, 3, 4, 5, 6, 7, 8 };
std::vector<int> 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<int> original = {1, 2, 3, 4, 5, 6, 7, 8};
std::vector<int> 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<int> original = { 1, 2, 3, 4, 5, 6, 7, 8 };
std::vector<int> 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<int> original = {1, 2, 3, 4, 5, 6, 7, 8};
std::vector<int> 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<int> original = { 1, 2, 3, 4, 5, 6, 7, 8 };
std::vector<int> sub1 = { 3, 4, 5, 6 };
std::vector<int> 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<size_t>(reinterpret_cast<const uint8_t*>(&etldata[0]),
reinterpret_cast<const uint8_t*>(&etldata[etldata.size()]));
size_t hashview = etl::hash<View>()(view);
size_t hashcview = etl::hash<CView>()(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<int, std::remove_reference_t<decltype(s.front())>>));
}
#if ETL_USING_STL
//*************************************************************************
TEST(test_template_deduction_guide_for_std_array)
{
std::array<int, 4U> 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<int, std::remove_reference_t<decltype(s.front())>>));
}
#endif
//*************************************************************************
TEST(test_template_deduction_guide_for_etl_array)
{
etl::array<int, 4U> 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<int, std::remove_reference_t<decltype(s.front())>>));
}
//*************************************************************************
TEST(test_template_deduction_guide_for_iterators)
{
etl::array<int, 4U> 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<int, std::remove_reference_t<decltype(s.front())>>));
}
//*************************************************************************
TEST(test_template_deduction_guide_for_iterator_and_size)
{
etl::array<int, 4U> 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<int, std::remove_reference_t<decltype(s.front())>>));
}
//*************************************************************************
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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::iterator csi = span.begin();
for (int i = 0; i < 20; i += step)
{
CHECK_EQUAL(expected[i % 10], *csi);
csi = csi - step;
}
}
}
};
}

View File

@ -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 <array>
#include <vector>
#include <algorithm>
#include <iterator>
namespace
{
SUITE(test_circular_span_fixed_extent)
{
static const size_t SIZE = 10UL;
typedef etl::array<int, SIZE> EtlData;
typedef std::array<int, SIZE> StlData;
typedef std::vector<int> StlVData;
typedef etl::circular_span<int, 10U> View;
typedef etl::circular_span<const int, 10U> 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<int> original = { 1, 2, 3, 4, 5, 6, 7, 8 };
std::vector<int> 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<int> original = {1, 2, 3, 4, 5, 6, 7, 8};
std::vector<int> 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<int> original = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::vector<int> 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<int> original = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::vector<int> 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<int> original = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::vector<int> sub1 = { 2, 3, 4, 5 };
std::vector<int> 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<size_t>(reinterpret_cast<const uint8_t*>(&etldata[0]),
reinterpret_cast<const uint8_t*>(&etldata[etldata.size()]));
size_t hashview = etl::hash<View>()(view);
size_t hashcview = etl::hash<CView>()(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<int, std::remove_reference_t<decltype(s.front())>>));
}
#if ETL_USING_STL
//*************************************************************************
TEST(test_template_deduction_guide_for_std_array)
{
std::array<int, 4U> 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<int, std::remove_reference_t<decltype(s.front())>>));
}
#endif
//*************************************************************************
TEST(test_template_deduction_guide_for_etl_array)
{
etl::array<int, 4U> 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<int, std::remove_reference_t<decltype(s.front())>>));
}
//*************************************************************************
TEST(test_template_deduction_guide_for_iterators)
{
etl::array<int, 4U> 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<int, std::remove_reference_t<decltype(s.front())>>));
}
//*************************************************************************
TEST(test_template_deduction_guide_for_iterator_and_size)
{
etl::array<int, 4U> 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<int, std::remove_reference_t<decltype(s.front())>>));
}
//*************************************************************************
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<int, 10U> span{ data };
etl::circular_span<int, 10U>::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<int, 10U> span{ data };
etl::circular_span<int, 4U> subspan = span.subspan<2, 4>();
etl::circular_span<int, 10U>::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<int, 10U> span{ data };
etl::circular_span<int, 10U>::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<int, 10U> span{ data };
etl::circular_span<int, 4U> subspan = span.subspan<2, 4>();
etl::circular_span<int, 10U>::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<int, 10U> span{ data };
etl::circular_span<int, 10U>::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<int, 10U> span{ data };
etl::circular_span<int, 4U> subspan = span.subspan<2, 4>();
etl::circular_span<int, 10U>::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<int, 10U> span{ data };
etl::circular_span<int, 10U>::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<int, 10U> span{ data };
etl::circular_span<int, 4U> subspan = span.subspan<2, 4>();
etl::circular_span<int, 10U>::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<int, 10U> span{ data };
for (int step = 1; step < 20; ++step)
{
etl::circular_span<int, 10U>::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<int, 10U> span{ data };
for (int step = 1; step < 20; ++step)
{
etl::circular_span<int, 10U>::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<int, 10U> span{ data };
for (int step = 1; step < 20; ++step)
{
etl::circular_span<int, 10U>::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<int, 10U> span{ data };
for (int step = 1; step < 20; ++step)
{
etl::circular_span<int, 10U>::iterator csi = span.begin();
for (int i = 0; i < 20; i += step)
{
CHECK_EQUAL(expected[i % 10], *csi);
csi = csi - step;
}
}
}
};
}

View File

@ -2387,6 +2387,7 @@
<ClInclude Include="..\..\include\etl\callback_timer_interrupt.h" />
<ClInclude Include="..\..\include\etl\callback_timer_locked.h" />
<ClInclude Include="..\..\include\etl\circular_buffer.h" />
<ClInclude Include="..\..\include\etl\circular_iterator.h" />
<ClInclude Include="..\..\include\etl\combinations.h" />
<ClInclude Include="..\..\include\etl\compare.h" />
<ClInclude Include="..\..\include\etl\constant.h" />
@ -11299,6 +11300,8 @@
<ClCompile Include="..\test_circular_buffer.cpp" />
<ClCompile Include="..\test_circular_buffer_external_buffer.cpp" />
<ClCompile Include="..\test_circular_iterator.cpp" />
<ClCompile Include="..\test_circular_span_dynamic_extent.cpp" />
<ClCompile Include="..\test_circular_span_fixed_extent.cpp" />
<ClCompile Include="..\test_compiler_settings.cpp" />
<ClCompile Include="..\test_correlation.cpp" />
<ClCompile Include="..\test_covariance.cpp" />

View File

@ -1332,6 +1332,9 @@
<ClInclude Include="..\..\include\etl\bitset.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\circular_iterator.h">
<Filter>ETL\Utilities</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\test_string_char.cpp">
@ -3359,6 +3362,12 @@
<ClCompile Include="..\sanity-check\circular_iterator.h.t.cpp">
<Filter>Tests\Sanity Checks\Source</Filter>
</ClCompile>
<ClCompile Include="..\test_circular_span_dynamic_extent.cpp">
<Filter>Tests\Containers</Filter>
</ClCompile>
<ClCompile Include="..\test_circular_span_fixed_extent.cpp">
<Filter>Tests\Containers</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\library.properties">