diff --git a/include/etl/poly_span.h b/include/etl/poly_span.h index 622c3d16..64083cf7 100644 --- a/include/etl/poly_span.h +++ b/include/etl/poly_span.h @@ -3,16 +3,15 @@ /****************************************************************************** The MIT License(MIT) -Copyright (c) 2020 Dr. Alexander Bulovyatov -https://github.com/mrshurik/poly_span - -Modifications: -Copyright(c) 2022 John Wellbelove - Embedded Template Library. https://github.com/ETLCPP/etl https://www.etlcpp.com +Copyright(c) 2022 John Wellbelove + +Inspired by the techniques used in https://github.com/mrshurik/poly_span +Copyright(c) 2020 Dr. Alexander Bulovyatov + 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 @@ -36,606 +35,790 @@ SOFTWARE. #define ETL_POLY_SPAN_INCLUDED #include "platform.h" -#include "type_traits.h" #include "iterator.h" -#include "exception.h" -#include "error_handler.h" +#include "nullptr.h" +#include "hash.h" +#include "type_traits.h" +#include "integral_limits.h" +#include "memory.h" +#include "array.h" + +#include "private/dynamic_extent.h" + +#if ETL_USING_CPP11 && ETL_USING_STL +#include +#endif + +///\defgroup poly_span poly_span +///\ingroup containers -#if ETL_CPP11_SUPPORTED namespace etl { //*************************************************************************** - /// The base class for poly_span exceptions. + /// Poly Span //*************************************************************************** - class poly_span_exception : public exception + template + class poly_span { public: - poly_span_exception(string_type reason_, string_type file_name_, numeric_type line_number_) - : exception(reason_, file_name_, line_number_) + typedef TBase element_type; + typedef typename etl::remove_cv::type value_type; + typedef size_t size_type; + typedef TBase& reference; + typedef const TBase& const_reference; + typedef TBase* pointer; + typedef const TBase* const_pointer; + //typedef TBase* iterator; + //typedef const TBase* const_iterator; + + //typedef ETL_OR_STD::reverse_iterator reverse_iterator; + //typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; + + static ETL_CONSTANT size_t extent = Extent; + + template + friend class poly_span; + + //************************************************************************* + /// Default constructor. + //************************************************************************* + ETL_CONSTEXPR poly_span() ETL_NOEXCEPT + : pbegin(ETL_NULLPTR) + , element_size(0U) { } + + //************************************************************************* + /// Construct from iterator + size + //************************************************************************* + template + ETL_CONSTEXPR poly_span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT + : pbegin(etl::addressof(*begin_)) + { + typedef typename etl::iterator_traits::value_type data_type; + typedef typename etl::iterator_traits::iterator_category iterator_category; + + ETL_STATIC_ASSERT((etl::is_same::iterator_category>::value), "Not a random access iterator"); + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); + + static ETL_CONSTANT size_t Element_Size = sizeof(data_type); + + element_size = Element_Size; + } + + //************************************************************************* + /// Construct from iterators + //************************************************************************* + template + ETL_CONSTEXPR poly_span(const TIterator begin_, const TIterator end_) + : pbegin(etl::addressof(*begin_)) + { + typedef typename etl::iterator_traits::value_type data_type; + typedef typename etl::iterator_traits::iterator_category iterator_category; + + ETL_STATIC_ASSERT((etl::is_same::value), "Not a random access iterator"); + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); + + static ETL_CONSTANT size_t Element_Size = sizeof(data_type); + + element_size = Element_Size; + } + + //************************************************************************* + /// Construct from C array + //************************************************************************* + template + ETL_CONSTEXPR poly_span(U(&begin_)[N]) ETL_NOEXCEPT + : pbegin(begin_) + { + ETL_STATIC_ASSERT(N <= Extent, "Array data overflow"); + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); + + static ETL_CONSTANT size_t Element_Size = sizeof(U); + + element_size = Element_Size; + } + + //************************************************************************* + /// Construct from etl::array. + //************************************************************************* + template + ETL_CONSTEXPR poly_span(etl::array& a) ETL_NOEXCEPT + : pbegin(a.data()) + { + ETL_STATIC_ASSERT(N <= Extent, "Array data overflow"); + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); + + static ETL_CONSTANT size_t Element_Size = sizeof(U); + + element_size = Element_Size; + } + + //************************************************************************* + /// Construct from etl::array. + //************************************************************************* + template + ETL_CONSTEXPR poly_span(const etl::array& a) ETL_NOEXCEPT + : pbegin(a.data()) + { + ETL_STATIC_ASSERT(N <= Extent, "Array data overflow"); + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); + + static ETL_CONSTANT size_t Element_Size = sizeof(U); + + element_size = Element_Size; + } + +#if ETL_USING_CPP11 && ETL_USING_STL + //************************************************************************* + /// Construct from std::array. + //************************************************************************* + template + ETL_CONSTEXPR poly_span(std::array& a) ETL_NOEXCEPT + : pbegin(a.data()) + { + ETL_STATIC_ASSERT(N <= Extent, "Array data overflow"); + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of U"); + + static ETL_CONSTANT size_t Element_Size = sizeof(U); + + element_size = Element_Size; + } + + //************************************************************************* + /// Construct from std::array. + //************************************************************************* + template + ETL_CONSTEXPR poly_span(const std::array& a) ETL_NOEXCEPT + : pbegin(a.data()) + { + ETL_STATIC_ASSERT(N <= Extent, "Array data overflow"); + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of U"); + + static ETL_CONSTANT size_t Element_Size = sizeof(U); + + element_size = Element_Size; + } +#endif + + //************************************************************************* + /// Copy constructor + //************************************************************************* + ETL_CONSTEXPR poly_span(const poly_span& other) ETL_NOEXCEPT + : pbegin(other.pbegin) + , element_size(other.element_size) + { + } + + //************************************************************************* + /// Copy constructor + //************************************************************************* + template + ETL_CONSTEXPR poly_span(const poly_span& other) ETL_NOEXCEPT + : pbegin(other.pbegin) + , element_size(other.element_size) + { + } +// +// //************************************************************************* +// /// Returns a reference to the first element. +// //************************************************************************* +// ETL_NODISCARD ETL_CONSTEXPR reference front() const ETL_NOEXCEPT +// { +// return *pbegin; +// } +// +// //************************************************************************* +// /// Returns a reference to the last element. +// //************************************************************************* +// ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT +// { +// return *(pend - 1); +// } +// + //************************************************************************* + /// Returns a pointer to the first element of the internal storage. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR pointer data() const ETL_NOEXCEPT + { + return pbegin; + } + + ////************************************************************************* + ///// Returns an iterator to the beginning of the poly_span. + ////************************************************************************* + //ETL_NODISCARD ETL_CONSTEXPR iterator begin() const ETL_NOEXCEPT + //{ + // return iterator(pbegin, 0U, element_size); + //} + + ////************************************************************************* + ///// Returns an iterator to the end of the poly_span. + ////************************************************************************* + //ETL_NODISCARD ETL_CONSTEXPR iterator end() const ETL_NOEXCEPT + //{ + // return iterator(pbegin, extent, element_size); + //} + +// //************************************************************************* +// // Returns an reverse iterator to the reverse beginning of the poly_span. +// //************************************************************************* +// ETL_CONSTEXPR reverse_iterator rbegin() const ETL_NOEXCEPT +// { +// return reverse_iterator(pend); +// } +// +// //************************************************************************* +// /// Returns a reverse iterator to the end of the poly_span. +// //************************************************************************* +// ETL_CONSTEXPR reverse_iterator rend() const ETL_NOEXCEPT +// { +// return reverse_iterator(pbegin); +// } +// + //************************************************************************* + /// Returns true if the poly_span size is zero. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT + { + return (Extent != 0U) + } + + //************************************************************************* + /// Returns the size of the poly_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT + { + return Extent; + } + + //************************************************************************* + /// Returns the size of the type stored in the poly_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR size_t size_of_element() const ETL_NOEXCEPT + { + return element_size; + } + + //************************************************************************* + /// Returns the size of the poly_span in bytes. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR size_t size_bytes() const ETL_NOEXCEPT + { + return Extent * element_size; + } + +// //************************************************************************* +// /// Assign from a poly_span. +// //************************************************************************* +// ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT +// { +// pbegin = other.pbegin; +// pend = other.pend; +// return *this; +// } +// +// //************************************************************************* +// /// Returns a reference to the indexed value. +// //************************************************************************* +// ETL_CONSTEXPR reference operator[](const size_t i) const +// { +// return pbegin[i]; +// } +// +// //************************************************************************* +// /// Obtains a poly_span that is a view over the first COUNT elements of this poly_span. +// //************************************************************************* +// template +// ETL_CONSTEXPR etl::poly_span first() const +// { +// return etl::poly_span(pbegin, pbegin + COUNT); +// } +// +// //************************************************************************* +// /// Obtains a poly_span that is a view over the first count elements of this poly_span. +// //************************************************************************* +// ETL_CONSTEXPR etl::poly_span first(size_t count) const +// { +// return etl::poly_span(pbegin, pbegin + count); +// } +// +// //************************************************************************* +// /// Obtains a poly_span that is a view over the last COUNT elements of this poly_span. +// //************************************************************************* +// template +// ETL_CONSTEXPR etl::poly_span last() const +// { +// return etl::poly_span(pend - COUNT, pend); +// } +// +// //************************************************************************* +// /// Obtains a poly_span that is a view over the last count elements of this poly_span. +// //************************************************************************* +// ETL_CONSTEXPR etl::poly_span last(size_t count) const +// { +// return etl::poly_span(pend - count, pend); +// } +// +//#if ETL_USING_CPP11 +// //************************************************************************* +// /// Obtains a poly_span that is a view from OFFSET over the next COUNT elements of this poly_span. +// //************************************************************************* +// template +// ETL_CONSTEXPR +// etl::poly_span subspan() const +// { +// if (COUNT == etl::dynamic_extent) +// { +// return etl::poly_span(pbegin + OFFSET, pend); +// } +// else +// { +// return etl::poly_span(pbegin + OFFSET, pbegin + OFFSET + COUNT); +// } +// } +//#else +// //************************************************************************* +// /// Obtains a poly_span that is a view from OFFSET over the next COUNT elements of this poly_span. +// //************************************************************************* +// template +// ETL_CONSTEXPR +// etl::poly_span subspan() const +// { +// if (COUNT == etl::dynamic_extent) +// { +// return etl::poly_span(pbegin + OFFSET, pend); +// } +// else +// { +// return etl::poly_span(pbegin + OFFSET, pbegin + OFFSET + COUNT); +// } +// } +//#endif +// +// //************************************************************************* +// /// Obtains a poly_span that is a view from 'offset' over the next 'count' elements of this poly_span. +// //************************************************************************* +// ETL_CONSTEXPR14 etl::poly_span subspan(size_t offset, size_t count = etl::dynamic_extent) const +// { +// if (count == etl::dynamic_extent) +// { +// return etl::poly_span(pbegin + offset, pend); +// } +// else +// { +// return etl::poly_span(pbegin + offset, pbegin + offset + count); +// } +// } + + private: + + pointer pbegin; + size_t element_size; }; //*************************************************************************** - /// The out of range exceptions. + /// Span specialisation //*************************************************************************** - class poly_span_out_of_range : public poly_span_exception + template + class poly_span { public: - poly_span_out_of_range(string_type file_name_, numeric_type line_number_) - : poly_span_exception("poly_span:out of range", file_name_, line_number_) + typedef TBase element_type; + typedef typename etl::remove_cv::type value_type; + typedef size_t size_type; + typedef TBase& reference; + typedef const TBase& const_reference; + typedef TBase* pointer; + typedef const TBase* const_pointer; + typedef TBase* iterator; + typedef const TBase* const_iterator; + typedef ETL_OR_STD::reverse_iterator reverse_iterator; + typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; + + template + friend class poly_span; + + //************************************************************************* + /// Default constructor. + //************************************************************************* + ETL_CONSTEXPR poly_span() ETL_NOEXCEPT + : pbegin(ETL_NULLPTR) + , extent(0U) + , element_size(0U) { } - }; - namespace private_poly_span - { - //*************************************************************************** - template - using HasSize = etl::is_integral().size())>; + //************************************************************************* + /// Construct from iterator + size + //************************************************************************* + template + ETL_CONSTEXPR poly_span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT + : pbegin(etl::addressof(*begin_)) + , extent(size_) + { + typedef typename etl::iterator_traits::value_type data_type; + typedef typename etl::iterator_traits::iterator_category iterator_category; - //*************************************************************************** - template - using DataType = decltype(etl::declval().data()); + ETL_STATIC_ASSERT((etl::is_same::value), "Not a random access iterator"); + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); - //*************************************************************************** - template - using HasData = etl::is_pointer>; + static ETL_CONSTANT size_t Element_Size = sizeof(data_type); + element_size = Element_Size; + } - //*************************************************************************** - template - using HasConvertibleData = etl::is_convertible, TType*>; + //************************************************************************* + /// Construct from iterators + //************************************************************************* + template + ETL_CONSTEXPR poly_span(const TIterator begin_, const TIterator end_) + : pbegin(etl::addressof(*begin_)) + , extent(size_t(etl::distance(begin_, end_))) + { + typedef typename etl::iterator_traits::value_type data_type; + typedef typename etl::iterator_traits::iterator_category iterator_category; + + ETL_STATIC_ASSERT((etl::is_same::value), "Not a random access iterator"); + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); + + static ETL_CONSTANT size_t Element_Size = sizeof(data_type); + element_size = Element_Size; + } + + //************************************************************************* + /// Construct from C array + //************************************************************************* + template + ETL_CONSTEXPR poly_span(U(&begin_)[N]) ETL_NOEXCEPT + : pbegin(begin_) + , extent(N) + { + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); + + static ETL_CONSTANT size_t Element_Size = sizeof(U); + element_size = Element_Size; + } + + //************************************************************************* + /// Construct from etl::array. + //************************************************************************* + template + ETL_CONSTEXPR poly_span(etl::array& a) ETL_NOEXCEPT + : pbegin(a.data()) + , extent(N) + { + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); + + static ETL_CONSTANT size_t Element_Size = sizeof(U); + element_size = Element_Size; + } + + //************************************************************************* + /// Construct from etl::array. + //************************************************************************* + template + ETL_CONSTEXPR poly_span(const etl::array& a) ETL_NOEXCEPT + : pbegin(a.data()) + , extent(N) + { + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); + + static ETL_CONSTANT size_t Element_Size = sizeof(U); + element_size = Element_Size; + } + +#if ETL_USING_CPP11 && ETL_USING_STL + //************************************************************************* + /// Construct from std::array. + //************************************************************************* + template + ETL_CONSTEXPR poly_span(std::array& a) ETL_NOEXCEPT + : pbegin(a.data()) + , extent(N) + { + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of U"); + + static ETL_CONSTANT size_t Element_Size = sizeof(U); + element_size = Element_Size; + } + + //************************************************************************* + /// Construct from std::array. + //************************************************************************* + template + ETL_CONSTEXPR poly_span(const std::array& a) ETL_NOEXCEPT + : pbegin(a.data()) + , extent(N) + { + ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of U"); + + static ETL_CONSTANT size_t Element_Size = sizeof(U); + element_size = Element_Size; + } +#endif + + //************************************************************************* + /// Copy constructor + //************************************************************************* + ETL_CONSTEXPR poly_span(const poly_span& other) ETL_NOEXCEPT + : pbegin(other.pbegin) + , extent(other.extent) + , element_size(other.element_size) + { + } + + //************************************************************************* + /// Copy constructor + //************************************************************************* + template + ETL_CONSTEXPR poly_span(const poly_span& other) ETL_NOEXCEPT + : pbegin(other.pbegin) + , extent(other.extent) + , element_size(other.element_size) + { + } +// +// //************************************************************************* +// /// Returns a reference to the first element. +// //************************************************************************* +// ETL_NODISCARD ETL_CONSTEXPR reference front() const ETL_NOEXCEPT +// { +// return *pbegin; +// } +// +// //************************************************************************* +// /// Returns a reference to the last element. +// //************************************************************************* +// ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT +// { +// return *(pend - 1); +// } +// + //************************************************************************* + /// Returns a pointer to the first element of the internal storage. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR pointer data() const ETL_NOEXCEPT + { + return pbegin; + } + + ////************************************************************************* + ///// Returns an iterator to the beginning of the poly_span. + ////************************************************************************* + //ETL_NODISCARD ETL_CONSTEXPR iterator begin() const ETL_NOEXCEPT + //{ + // return iterator(pbegin, 0U, element_size); + //} + + ////************************************************************************* + ///// Returns an iterator to the end of the poly_span. + ////************************************************************************* + //ETL_NODISCARD ETL_CONSTEXPR iterator end() const ETL_NOEXCEPT + //{ + // return iterator(pbegin, extent, element_size); + //} + +// //************************************************************************* +// // Returns an reverse iterator to the reverse beginning of the poly_span. +// //************************************************************************* +// ETL_NODISCARD ETL_CONSTEXPR reverse_iterator rbegin() const ETL_NOEXCEPT +// { +// return reverse_iterator(pend); +// } +// +// //************************************************************************* +// /// Returns a reverse iterator to the end of the poly_span. +// //************************************************************************* +// ETL_NODISCARD ETL_CONSTEXPR reverse_iterator rend() const ETL_NOEXCEPT +// { +// return reverse_iterator(pbegin); +// } +// + //************************************************************************* + /// Returns true if the poly_span size is zero. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT + { + return (extent == 0); + } + + //************************************************************************* + /// Returns the size of the poly_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT + { + return extent; + } + + //************************************************************************* + /// Returns the size of the type stored in the poly_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR size_t size_of_element() const ETL_NOEXCEPT + { + return element_size; + } + + //************************************************************************* + /// Returns the size of the poly_span in bytes. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR size_t size_bytes() const ETL_NOEXCEPT + { + return element_size * extent; + } + +// //************************************************************************* +// /// Assign from a poly_span. +// //************************************************************************* +// ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT +// { +// pbegin = other.pbegin; +// pend = other.pend; +// return *this; +// } + + //************************************************************************* + /// Returns a reference to the indexed value. + //************************************************************************* + ETL_CONSTEXPR reference operator[](size_t i) const + { + return *element_at(i); + } + +// //************************************************************************* +// /// Obtains a poly_span that is a view over the first COUNT elements of this poly_span. +// //************************************************************************* +// template +// ETL_CONSTEXPR etl::poly_span first() const +// { +// return etl::poly_span(pbegin, pbegin + COUNT); +// } +// +// //************************************************************************* +// /// Obtains a poly_span that is a view over the first count elements of this poly_span. +// //************************************************************************* +// ETL_CONSTEXPR etl::poly_span first(size_t count) const +// { +// return etl::poly_span(pbegin, pbegin + count); +// } +// +// //************************************************************************* +// /// Obtains a poly_span that is a view over the last COUNT elements of this poly_span. +// //************************************************************************* +// template +// ETL_CONSTEXPR etl::poly_span last() const +// { +// return etl::poly_span(pend - COUNT, pend); +// } +// +// //************************************************************************* +// /// Obtains a poly_span that is a view over the last count elements of this poly_span. +// //************************************************************************* +// ETL_CONSTEXPR etl::poly_span last(size_t count) const +// { +// return etl::poly_span(pend - count, pend); +// } +// +//#if ETL_USING_CPP11 +// //************************************************************************* +// /// Obtains a poly_span that is a view from OFFSET over the next COUNT elements of this poly_span. +// //************************************************************************* +// template +// ETL_CONSTEXPR +// etl::poly_span subspan() const +// { +// if (COUNT == etl::dynamic_extent) +// { +// return etl::poly_span(pbegin + OFFSET, pend); +// } +// else +// { +// return etl::poly_span(pbegin + OFFSET, pbegin + OFFSET + COUNT); +// } +// } +//#else +// //************************************************************************* +// /// Obtains a poly_span that is a view from OFFSET over the next COUNT elements of this poly_span. +// //************************************************************************* +// template +// ETL_CONSTEXPR +// etl::poly_span subspan() const +// { +// if (COUNT == etl::dynamic_extent) +// { +// return etl::poly_span(pbegin + OFFSET, pend); +// } +// else +// { +// return etl::poly_span(pbegin + OFFSET, pbegin + OFFSET + COUNT); +// } +// } +//#endif +// +// //************************************************************************* +// /// Obtains a poly_span that is a view from 'offset' over the next 'count' elements of this poly_span. +// //************************************************************************* +// ETL_CONSTEXPR14 etl::poly_span subspan(size_t offset, size_t count = etl::dynamic_extent) const +// { +// if (count == etl::dynamic_extent) +// { +// return etl::poly_span(pbegin + offset, pend); +// } +// return etl::poly_span(pbegin + offset, pbegin + offset + count); +// } +// + private: //*************************************************************************** template - using TransferConst = typename etl::conditional::value, - typename etl::add_const::type, - TTo>::type; + using transfer_const = typename etl::conditional::value, typename etl::add_const::type, TTo>::type; + + typedef transfer_const* char_ptr_t; //*************************************************************************** - template - class poly_span_iterator; - - //*************************************************************************** - template - struct IsPolySpanItImpl : etl::false_type {}; - - //*************************************************************************** - template - struct IsPolySpanItImpl> : etl::true_type {}; - - //*************************************************************************** - template - using IsPolySpanIterator = IsPolySpanItImpl; - - //*************************************************************************** - /// Iterator implementation - //*************************************************************************** - template - class poly_span_iterator : public etl::iterator - { - private: - - template - using EnableIfConversionToConst = etl::enable_if_t::value && etl::is_same::value>; - - public: - - //*************************************************************************** - poly_span_iterator() = default; - poly_span_iterator(const poly_span_iterator&) = default; - poly_span_iterator& operator=(const poly_span_iterator&) = default; - - //*************************************************************************** - poly_span_iterator(TType* ptr, size_t element_size) noexcept - : m_ptr(ptr), m_element_size(element_size) - { - } - - //*************************************************************************** - template > - poly_span_iterator(const poly_span_iterator& other) noexcept - : m_ptr(other.m_ptr) - , m_element_size(other.m_element_size) - { - } - - //*************************************************************************** - TType* operator ->() const noexcept - { - return m_ptr; - } - - //*************************************************************************** - TType& operator *() const noexcept - { - return *m_ptr; - } - - //*************************************************************************** - poly_span_iterator& operator ++() noexcept - { - from_char_ptr(to_char_ptr() + m_element_size); - return *this; - } - - //*************************************************************************** - poly_span_iterator& operator --() noexcept - { - from_char_ptr(to_char_ptr() - m_element_size); - return *this; - } - - //*************************************************************************** - poly_span_iterator& operator +=(ptrdiff_t n) noexcept - { - from_char_ptr(to_char_ptr() + (n * m_element_size)); - return *this; - } - - //*************************************************************************** - friend ptrdiff_t operator -(poly_span_iterator left, poly_span_iterator right) noexcept - { - return (left.to_char_ptr() - right.to_char_ptr()) / left.m_element_size; - } - - //*************************************************************************** - poly_span_iterator operator +(ptrdiff_t n) const noexcept - { - poly_span_iterator tmp = *this; - tmp += n; - return tmp; - } - - //*************************************************************************** - poly_span_iterator operator ++(int) noexcept - { - poly_span_iterator tmp = *this; - ++(*this); - return tmp; - } - - //*************************************************************************** - poly_span_iterator operator --(int) noexcept - { - poly_span_iterator tmp = *this; - --(*this); - return tmp; - } - - //*************************************************************************** - poly_span_iterator operator-(ptrdiff_t n) const noexcept - { - return *this + (-n); - } - - //*************************************************************************** - poly_span_iterator& operator-=(ptrdiff_t n) noexcept - { - return *this += -n; - } - - //*************************************************************************** - TType& operator[](ptrdiff_t n) const noexcept - { - return *(*this + n); - } - - //*************************************************************************** - friend poly_span_iterator operator+(ptrdiff_t n, poly_span_iterator other) noexcept - { - return other + n; - } - - //*************************************************************************** - friend bool operator==(poly_span_iterator left, poly_span_iterator right) noexcept - { - return left.m_ptr == right.m_ptr; - } - - //*************************************************************************** - friend bool operator!=(poly_span_iterator left, poly_span_iterator right) noexcept - { - return left.m_ptr != right.m_ptr; - } - - //*************************************************************************** - friend bool operator >(poly_span_iterator left, poly_span_iterator right) noexcept - { - return left.m_ptr > right.m_ptr; - } - - //*************************************************************************** - friend bool operator <(poly_span_iterator left, poly_span_iterator right) noexcept - { - return left.m_ptr < right.m_ptr; - } - - //*************************************************************************** - friend bool operator>=(poly_span_iterator left, poly_span_iterator right) noexcept - { - return left.m_ptr >= right.m_ptr; - } - - //*************************************************************************** - friend bool operator<=(poly_span_iterator left, poly_span_iterator right) noexcept - { - return left.m_ptr <= right.m_ptr; - } - - private: - - template - friend class poly_span_iterator; - - using void_ptr_t = TransferConst*; - using char_ptr_t = TransferConst*; - - //*************************************************************************** - char_ptr_t to_char_ptr() const noexcept - { - return static_cast(static_cast(m_ptr)); - } - - //*************************************************************************** - void from_char_ptr(char_ptr_t ptr) noexcept - { - m_ptr = static_cast(static_cast(ptr)); - } - - TType* m_ptr; - size_t m_element_size; - }; - } - - //*************************************************************************** - /// C++11 etl::span-like view with focus on polymorphic aspect of types. - /// Provides a base class / interface view. Type can be const or non-const. - /// The class behaves like etl::span, has O(1) index access and provides RandomAccess iterators. - /// Hints: - /// 1. NEVER assign to elements or apply mutable algorithms to a mutable view to a base class. Object slicing! - /// 2. Pay attention to lifetime of the source buffer. poly_span should mostly be used as an argument of functions. - /// 3. The view has no data() for reason. Pointer to the first byte of the first object is unknown in general. - //*************************************************************************** - template - class poly_span - { - private: - - //*************************************************************************** - template - using EnableIfConvertibleFromObject = etl::enable_if_t::value && - private_poly_span::HasData::value && - private_poly_span::HasConvertibleData::value>; - - //*************************************************************************** - template - using EnableIfTConvertibleType = etl::enable_if_t::value>; - - //*************************************************************************** - template - using IsTContiguousIterator = etl::integral_constant::iterator_category>::value// && - /*!private_poly_span::IsPolySpanIterator::value*/>; - - public: - - using element_type = TType; - using value_type = typename etl::remove_cv::type; - using size_type = size_t; - using difference_type = ptrdiff_t; - using pointer = TType*; - using reference = TType&; - using const_pointer = const TType*; - using const_reference = const TType&; - using iterator = private_poly_span::poly_span_iterator; - using const_iterator = private_poly_span::poly_span_iterator; - using reverse_iterator = etl::reverse_iterator; - using const_reverse_iterator = etl::reverse_iterator; - - static constexpr size_t npos = ~size_t(0); - - //*************************************************************************** - /// Default constructor - //*************************************************************************** - poly_span() = default; - - //*************************************************************************** - /// Copy constructor - //*************************************************************************** - poly_span(const poly_span&) = default; - - //*************************************************************************** - /// Assignment operator - //*************************************************************************** - poly_span& operator=(const poly_span&) = default; - - //*************************************************************************** - /// Construct from a compatible poly_span: convert mutable to const, derived to base type. - //*************************************************************************** - template - poly_span(const poly_span& span) noexcept - : poly_span(span.m_dataPtr, span.m_size, span.m_element_size) + ETL_CONSTEXPR pointer element_at(size_t index) const ETL_NOEXCEPT { + char_ptr_t base = reinterpret_cast(pbegin); + return reinterpret_cast(base + (index * element_size)); } - //*************************************************************************** - /// Construct from a range of iterators or pointers. - /// Iterators must Contiguous. - //*************************************************************************** - template - poly_span(TContiguousIterator begin, TContiguousIterator end) noexcept - : poly_span(&*begin, end - begin, ETL_NULLPTR) - { - static_assert(IsTContiguousIterator::value, "Not a contiguous iterator"); - } - - //*************************************************************************** - /// Construct from a range defined as iterator/pointer to begin and size. - /// Iterators must Contiguous. - //*************************************************************************** - template - poly_span(TContiguousIterator begin, size_t size) noexcept - : poly_span(&*begin, size, ETL_NULLPTR) - { - static_assert(IsTContiguousIterator::value, "Not a contiguous iterator"); - } - - //*************************************************************************** - /// Construct from a C-style array. - //*************************************************************************** - template - poly_span(TConvertibleType(&array)[N]) noexcept - : poly_span(array, N, ETL_NULLPTR) - { - } - - //*************************************************************************** - /// Construct from a buffer objects: etl::vector, etl::array, etl::span or any class with data() and size(). - //*************************************************************************** - template > - poly_span(TBufferLikeObj& buffer) noexcept - : poly_span(buffer.data() - , buffer.size() - , ETL_NULLPTR) - { - } - - //*************************************************************************** - /// Get the beginning of the span - //*************************************************************************** - iterator begin() const noexcept - { - return { m_dataPtr, m_element_size }; - } - - //*************************************************************************** - /// Get the end of the span - //*************************************************************************** - iterator end() const noexcept - { - return { element_at(m_size), m_element_size }; - } - - //*************************************************************************** - /// Get the beginning of the span - //*************************************************************************** - const_iterator cbegin() const noexcept - { - return begin(); - } - - //*************************************************************************** - /// Get the end of the span - //*************************************************************************** - const_iterator cend() const noexcept - { - return end(); - } - - //*************************************************************************** - /// Get the reverse beginning of the span - //*************************************************************************** - reverse_iterator rbegin() const noexcept - { - return reverse_iterator(end()); - } - - //*************************************************************************** - /// Get the end of the span - //*************************************************************************** - reverse_iterator rend() const noexcept - { - return reverse_iterator(begin()); - } - - //*************************************************************************** - /// Get the reverse beginning of the span - //*************************************************************************** - const_reverse_iterator crbegin() const noexcept - { - return rbegin(); - } - - //*************************************************************************** - /// Get the end of the span - //*************************************************************************** - const_reverse_iterator crend() const noexcept - { - return rend(); - } - - //*************************************************************************** - /// Returns true if the view has no elements. - //*************************************************************************** - bool empty() const noexcept - { - return m_size == 0; - } - - //*************************************************************************** - /// Number of elements in the view. - //*************************************************************************** - size_t size() const noexcept - { - return m_size; - } - - //*************************************************************************** - /// \brief sizeof(OriginalType) where OriginalType is type of the source buffer. - /// It's not sizeof(TType) for poly_span! - //*************************************************************************** - size_t element_size() const noexcept - { - return m_element_size; - } - - //*************************************************************************** - /// \brief Checks that other poly_span provides view to the same source buffer. - /// It's not like etl::span operator==() which checks for elements equality. - //*************************************************************************** - bool equal_view(const poly_span& other) const noexcept - { - return (m_dataPtr == other.m_dataPtr) && - (m_size == other.m_size) && - (m_element_size == other.m_element_size); - } - - //*************************************************************************** - /// Reference to the element with given index. No out of bounds check. - //*************************************************************************** - reference operator[](size_t index) const noexcept - { - return *element_at(index); - } - - //*************************************************************************** - /// \brief Index access with out of bounds checks. - /// \param index position of element in the view. - /// Asserts etl::poly_span_out_of_range if index >= size(). - /// \return reference to the element. - //*************************************************************************** - reference at(size_t index) const - { - ETL_ASSERT(index < m_size, ETL_ERROR(etl::poly_span_out_of_range)); - - return *element_at(index); - } - - //*************************************************************************** - /// Reference to the first element. The view must be non-empty. - //*************************************************************************** - reference front() const noexcept - { - return *m_dataPtr; - } - - //*************************************************************************** - /// Reference to the last element. The view must be non-empty. - //*************************************************************************** - reference back() const noexcept - { - return *element_at(m_size - 1); - } - - //*************************************************************************** - /// \brief Creates a new view as a subrange of this. - /// \param pos Starting offset for the new view. - /// \param count Number of elements to take into the new view. Default npos is to take all until the end. - /// Asserts etl::poly_span_out_of_range if pos > size(). - /// \return New sub-view. If count > number of elements before the end it's the same as npos, no error. - //*************************************************************************** - poly_span subspan(size_t pos, size_t count = npos) const - { - ETL_ASSERT(pos <= m_size, ETL_ERROR(etl::poly_span_out_of_range)); - - return { element_at(pos), min_impl(m_size - pos, count), m_element_size }; - } - - //*************************************************************************** - /// \brief Creates a new view from exactly N first elements. - /// \param count Exact number of elements to take. - /// Asserts etl::poly_span_out_of_range if count > size(). - /// \return New sub-view. - //*************************************************************************** - poly_span first(size_t count) const - { - ETL_ASSERT(count <= m_size, ETL_ERROR(etl::poly_span_out_of_range)); - - return { m_dataPtr, count, m_element_size }; - } - - //*************************************************************************** - /// \brief Creates a new view from exactly N last elements. - /// \param count Exact number of elements to take. - /// Asserts etl::poly_span_out_of_range if count > size(). - /// \return New sub-view. - //*************************************************************************** - poly_span last(size_t count) const - { - ETL_ASSERT(count <= m_size, ETL_ERROR(etl::poly_span_out_of_range)); - - return { element_at(m_size - count), count, m_element_size }; - } - - private: - - //*************************************************************************** - poly_span(TType* dataPtr, size_t size, size_t element_size) noexcept - : m_dataPtr(dataPtr) - , m_size(size) - , m_element_size(element_size) - { - } - -#if ETL_USING_STL - //*************************************************************************** - template - poly_span(TConvertibleType* dataPtr, size_t size, std::nullptr_t) noexcept - : m_dataPtr(dataPtr) - , m_size(size) - , m_element_size(sizeof(TConvertibleType)) - { - } -#else - //*************************************************************************** - template - poly_span(TConvertibleType* dataPtr, size_t size, void*) noexcept - : m_dataPtr(dataPtr) - , m_size(size) - , m_element_size(sizeof(TConvertibleType)) - { - } -#endif - - template - friend class poly_span; - - using void_ptr_t = private_poly_span::TransferConst*; - using char_ptr_t = private_poly_span::TransferConst*; - - //*************************************************************************** - TType* element_at(size_t ind) const noexcept - { - const auto base = static_cast(static_cast(m_dataPtr)); - return static_cast(static_cast(base + (ind * m_element_size))); - } - - //*************************************************************************** - template - static Value min_impl(Value a, Value b) noexcept - { - return (a < b) ? a : b; - } - - TType* m_dataPtr = ETL_NULLPTR; - size_t m_size = 0; - size_t m_element_size = 0; + pointer pbegin; + size_t extent; + size_t element_size; }; +// +// //************************************************************************* +// /// Template deduction guides. +// //************************************************************************* +//#if ETL_USING_CPP17 +// template +// poly_span(TArray& a) +// ->poly_span; +// +// template +// poly_span(const TIterator begin_, const TIterator end_) +// ->poly_span, etl::dynamic_extent>; +// +// template +// poly_span(const TIterator begin_, const TSize size_) +// ->poly_span, etl::dynamic_extent>; +//#endif +// +// //************************************************************************* +// /// Hash function. +// //************************************************************************* +//#if ETL_USING_8BIT_TYPES +// template +// struct hash > +// { +// size_t operator()(const etl::poly_span& view) const +// { +// return etl::private_hash::generic_hash(reinterpret_cast(&view[0]), +// reinterpret_cast(&view[view.size()])); +// } +// }; +//#endif } #endif - -#endif diff --git a/include/etl/private/dynamic_extent.h b/include/etl/private/dynamic_extent.h new file mode 100644 index 00000000..afcc9687 --- /dev/null +++ b/include/etl/private/dynamic_extent.h @@ -0,0 +1,42 @@ +///\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_DYNAMIC_EXTENT_INCLUDED +#define ETL_DYNAMIC_EXTENT_INCLUDED + +#include "../platform.h" +#include "../integral_limits.h" + +namespace etl +{ + static ETL_CONSTANT size_t dynamic_extent = etl::integral_limits::max; +} + +#endif diff --git a/include/etl/span.h b/include/etl/span.h index 9556fea5..2da3264c 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -40,6 +40,8 @@ SOFTWARE. #include "memory.h" #include "array.h" +#include "private/dynamic_extent.h" + #if ETL_USING_CPP11 && ETL_USING_STL #include #endif @@ -49,36 +51,34 @@ SOFTWARE. namespace etl { - static ETL_CONSTANT size_t dynamic_extent = etl::integral_limits::max; - //*************************************************************************** /// Span //*************************************************************************** - template + template class span { public: - typedef T element_type; - typedef typename etl::remove_cv::type value_type; - typedef size_t size_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - typedef T* iterator; - typedef const T* const_iterator; + typedef T element_type; + typedef typename etl::remove_cv::type value_type; + typedef size_t size_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef T* iterator; + typedef const T* const_iterator; + typedef ETL_OR_STD::reverse_iterator reverse_iterator; typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; - static ETL_CONSTANT size_t extent = EXTENT; + static ETL_CONSTANT size_t extent = Extent; //************************************************************************* /// Default constructor. //************************************************************************* ETL_CONSTEXPR span() ETL_NOEXCEPT - : mbegin(ETL_NULLPTR) - , mend(ETL_NULLPTR) + : pbegin(ETL_NULLPTR) { } @@ -87,8 +87,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT - : mbegin(etl::addressof(*begin_)) - , mend(etl::addressof(*begin_) + size_) + : pbegin(etl::addressof(*begin_)) { } @@ -97,8 +96,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR span(const TIterator begin_, const TIterator end_) - : mbegin(etl::addressof(*begin_)) - , mend(etl::addressof(*begin_) + etl::distance(begin_, end_)) + : pbegin(etl::addressof(*begin_)) { } @@ -107,8 +105,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR span(element_type(&begin_)[ARRAY_SIZE]) ETL_NOEXCEPT - : mbegin(begin_) - , mend(begin_ + ARRAY_SIZE) + : pbegin(begin_) { } @@ -116,20 +113,18 @@ namespace etl //************************************************************************* /// Construct from etl::array. //************************************************************************* - template , etl::remove_cv_t>::value, void>::type> + template , etl::remove_cv_t>::value, void>::type> ETL_CONSTEXPR span(etl::array& a) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) { } //************************************************************************* /// Construct from etl::array. //************************************************************************* - template , etl::remove_cv_t>::value, void>::type> + template , etl::remove_cv_t>::value, void>::type> ETL_CONSTEXPR span(const etl::array& a) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) { } #else @@ -137,9 +132,8 @@ namespace etl /// Construct from etl::array. //************************************************************************* template - ETL_CONSTEXPR span(etl::array& a, typename etl::enable_if<(N == EXTENT) && etl::is_same::type, typename etl::remove_cv::type>::value, void>::type) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + ETL_CONSTEXPR span(etl::array& a, typename etl::enable_if<(N == Extent) && etl::is_same::type, typename etl::remove_cv::type>::value, void>::type) ETL_NOEXCEPT + : pbegin(a.data()) { } @@ -147,9 +141,8 @@ namespace etl /// Construct from etl::array. //************************************************************************* template - ETL_CONSTEXPR span(const etl::array& a, typename etl::enable_if<(N == EXTENT) && etl::is_same::type, typename etl::remove_cv::type>::value, void>::type) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + ETL_CONSTEXPR span(const etl::array& a, typename etl::enable_if<(N == Extent) && etl::is_same::type, typename etl::remove_cv::type>::value, void>::type) ETL_NOEXCEPT + : pbegin(a.data()) { } #endif @@ -158,20 +151,18 @@ namespace etl //************************************************************************* /// Construct from std::array. //************************************************************************* - template , etl::remove_cv_t>::value, void>::type> + template , etl::remove_cv_t>::value, void>::type> ETL_CONSTEXPR span(std::array& a) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) { } //************************************************************************* /// Construct from std::array. //************************************************************************* - template , etl::remove_cv_t>::value, void>::type> + template , etl::remove_cv_t>::value, void>::type> ETL_CONSTEXPR span(const std::array& a) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) { } #endif @@ -180,8 +171,7 @@ namespace etl /// Copy constructor //************************************************************************* ETL_CONSTEXPR span(const span& other) ETL_NOEXCEPT - : mbegin(other.mbegin) - , mend(other.mend) + : pbegin(other.pbegin) { } @@ -190,7 +180,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR reference front() const ETL_NOEXCEPT { - return *mbegin; + return *pbegin; } //************************************************************************* @@ -198,7 +188,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR reference back() const ETL_NOEXCEPT { - return *(mend - 1); + return *((pbegin + Extent) - 1); } //************************************************************************* @@ -206,7 +196,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR pointer data() const ETL_NOEXCEPT { - return mbegin; + return pbegin; } //************************************************************************* @@ -214,7 +204,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR iterator begin() const ETL_NOEXCEPT { - return mbegin; + return pbegin; } //************************************************************************* @@ -222,7 +212,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR iterator end() const ETL_NOEXCEPT { - return mend; + return (pbegin + Extent); } //************************************************************************* @@ -230,7 +220,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR reverse_iterator rbegin() const ETL_NOEXCEPT { - return reverse_iterator(mend); + return reverse_iterator((pbegin + Extent)); } //************************************************************************* @@ -238,7 +228,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR reverse_iterator rend() const ETL_NOEXCEPT { - return reverse_iterator(mbegin); + return reverse_iterator(pbegin); } //************************************************************************* @@ -246,7 +236,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT { - return (mbegin == mend); + return false; } //************************************************************************* @@ -254,7 +244,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT { - return (mend - mbegin); + return Extent; } //************************************************************************* @@ -262,7 +252,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR size_t size_bytes() const ETL_NOEXCEPT { - return sizeof(element_type) * (mend - mbegin); + return sizeof(element_type) * Extent; } //************************************************************************* @@ -278,8 +268,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 span& operator =(const span& other) ETL_NOEXCEPT { - mbegin = other.mbegin; - mend = other.mend; + pbegin = other.pbegin; return *this; } @@ -288,7 +277,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR reference operator[](const size_t i) const { - return mbegin[i]; + return pbegin[i]; } //************************************************************************* @@ -297,7 +286,7 @@ namespace etl template ETL_CONSTEXPR etl::span first() const { - return etl::span(mbegin, mbegin + COUNT); + return etl::span(pbegin, pbegin + COUNT); } //************************************************************************* @@ -305,7 +294,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR etl::span first(size_t count) const { - return etl::span(mbegin, mbegin + count); + return etl::span(pbegin, pbegin + count); } //************************************************************************* @@ -314,7 +303,7 @@ namespace etl template ETL_CONSTEXPR etl::span last() const { - return etl::span(mend - COUNT, mend); + return etl::span((pbegin + Extent) - COUNT, (pbegin + Extent)); } //************************************************************************* @@ -322,7 +311,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR etl::span last(size_t count) const { - return etl::span(mend - count, mend); + return etl::span((pbegin + Extent) - count, (pbegin + Extent)); } #if ETL_USING_CPP11 @@ -331,15 +320,15 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR - etl::span subspan() const + etl::span subspan() const { if (COUNT == etl::dynamic_extent) { - return etl::span(mbegin + OFFSET, mend); + return etl::span(pbegin + OFFSET, (pbegin + Extent)); } else { - return etl::span(mbegin + OFFSET, mbegin + OFFSET + COUNT); + return etl::span(pbegin + OFFSET, pbegin + OFFSET + COUNT); } } #else @@ -348,15 +337,15 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR - etl::span subspan() const + etl::span subspan() const { if (COUNT == etl::dynamic_extent) { - return etl::span(mbegin + OFFSET, mend); + return etl::span(pbegin + OFFSET, (pbegin + Extent)); } else { - return etl::span(mbegin + OFFSET, mbegin + OFFSET + COUNT); + return etl::span(pbegin + OFFSET, pbegin + OFFSET + COUNT); } } #endif @@ -368,18 +357,17 @@ namespace etl { if (count == etl::dynamic_extent) { - return etl::span(mbegin + offset, mend); + return etl::span(pbegin + offset, (pbegin + Extent)); } else { - return etl::span(mbegin + offset, mbegin + offset + count); + return etl::span(pbegin + offset, pbegin + offset + count); } } private: - element_type* mbegin; - element_type* mend; + pointer pbegin; }; //*************************************************************************** @@ -408,8 +396,8 @@ namespace etl /// Default constructor. //************************************************************************* ETL_CONSTEXPR span() ETL_NOEXCEPT - : mbegin(ETL_NULLPTR) - , mend(ETL_NULLPTR) + : pbegin(ETL_NULLPTR) + , pend(ETL_NULLPTR) { } @@ -418,8 +406,8 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT - : mbegin(etl::addressof(*begin_)) - , mend(etl::addressof(*begin_) + size_) + : pbegin(etl::addressof(*begin_)) + , pend(etl::addressof(*begin_) + size_) { } @@ -428,8 +416,8 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR span(const TIterator begin_, const TIterator end_) - : mbegin(etl::addressof(*begin_)) - , mend(etl::addressof(*begin_) + etl::distance(begin_, end_)) + : pbegin(etl::addressof(*begin_)) + , pend(etl::addressof(*begin_) + etl::distance(begin_, end_)) { } @@ -438,8 +426,8 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR span(element_type(&begin_)[ARRAY_SIZE]) ETL_NOEXCEPT - : mbegin(begin_) - , mend(begin_ + ARRAY_SIZE) + : pbegin(begin_) + , pend(begin_ + ARRAY_SIZE) { } @@ -449,8 +437,8 @@ namespace etl //************************************************************************* template , etl::remove_cv_t>::value, void>::type> ETL_CONSTEXPR span(etl::array& a) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) + , pend(a.data() + a.size()) { } @@ -459,8 +447,8 @@ namespace etl //************************************************************************* template , etl::remove_cv_t>::value, void>::type> ETL_CONSTEXPR span(const etl::array& a) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) + , pend(a.data() + a.size()) { } #else @@ -469,8 +457,8 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR span(etl::array& a, typename etl::enable_if::type, typename etl::remove_cv::type>::value, void>::type) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) + , pend(a.data() + a.size()) { } @@ -479,8 +467,8 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR span(const etl::array& a, typename etl::enable_if::type, typename etl::remove_cv::type>::value, void>::type) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) + , pend(a.data() + a.size()) { } #endif @@ -491,8 +479,8 @@ namespace etl //************************************************************************* template , etl::remove_cv_t>::value, void>::type> ETL_CONSTEXPR span(std::array& a) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) + , pend(a.data() + a.size()) { } @@ -501,8 +489,8 @@ namespace etl //************************************************************************* template , etl::remove_cv_t>::value, void>::type> ETL_CONSTEXPR span(const std::array& a) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) + , pend(a.data() + a.size()) { } #endif @@ -516,8 +504,8 @@ namespace etl !etl::is_array>::value && etl::is_same, etl::remove_cv_t::value_type>>::value, void>::type> ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) + , pend(a.data() + a.size()) { } #else @@ -529,8 +517,8 @@ namespace etl ETL_CONSTEXPR span(TContainer& a, typename etl::enable_if::type>::value && !etl::is_array::value && etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) + , pend(a.data() + a.size()) { } @@ -542,8 +530,8 @@ namespace etl ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if::type>::value && !etl::is_array::value && etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type) ETL_NOEXCEPT - : mbegin(a.data()) - , mend(a.data() + a.size()) + : pbegin(a.data()) + , pend(a.data() + a.size()) { } #endif @@ -552,8 +540,8 @@ namespace etl /// Copy constructor //************************************************************************* ETL_CONSTEXPR span(const span& other) ETL_NOEXCEPT - : mbegin(other.mbegin) - , mend(other.mend) + : pbegin(other.pbegin) + , pend(other.pend) { } @@ -562,7 +550,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR reference front() const ETL_NOEXCEPT { - return *mbegin; + return *pbegin; } //************************************************************************* @@ -570,7 +558,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR reference back() const ETL_NOEXCEPT { - return *(mend - 1); + return *(pend - 1); } //************************************************************************* @@ -578,7 +566,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR pointer data() const ETL_NOEXCEPT { - return mbegin; + return pbegin; } //************************************************************************* @@ -586,7 +574,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR iterator begin() const ETL_NOEXCEPT { - return mbegin; + return pbegin; } //************************************************************************* @@ -594,7 +582,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR iterator end() const ETL_NOEXCEPT { - return mend; + return pend; } //************************************************************************* @@ -602,7 +590,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR reverse_iterator rbegin() const ETL_NOEXCEPT { - return reverse_iterator(mend); + return reverse_iterator(pend); } //************************************************************************* @@ -610,7 +598,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR reverse_iterator rend() const ETL_NOEXCEPT { - return reverse_iterator(mbegin); + return reverse_iterator(pbegin); } //************************************************************************* @@ -618,7 +606,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT { - return (mbegin == mend); + return (pbegin == pend); } //************************************************************************* @@ -626,7 +614,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT { - return (mend - mbegin); + return (pend - pbegin); } //************************************************************************* @@ -634,7 +622,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR size_t size_bytes() const ETL_NOEXCEPT { - return sizeof(element_type) * (mend - mbegin); + return sizeof(element_type) * (pend - pbegin); } //************************************************************************* @@ -650,8 +638,8 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 span& operator =(const span& other) ETL_NOEXCEPT { - mbegin = other.mbegin; - mend = other.mend; + pbegin = other.pbegin; + pend = other.pend; return *this; } @@ -660,7 +648,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR reference operator[](const size_t i) const { - return mbegin[i]; + return pbegin[i]; } //************************************************************************* @@ -669,7 +657,7 @@ namespace etl template ETL_CONSTEXPR etl::span first() const { - return etl::span(mbegin, mbegin + COUNT); + return etl::span(pbegin, pbegin + COUNT); } //************************************************************************* @@ -677,7 +665,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR etl::span first(size_t count) const { - return etl::span(mbegin, mbegin + count); + return etl::span(pbegin, pbegin + count); } //************************************************************************* @@ -686,7 +674,7 @@ namespace etl template ETL_CONSTEXPR etl::span last() const { - return etl::span(mend - COUNT, mend); + return etl::span(pend - COUNT, pend); } //************************************************************************* @@ -694,7 +682,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR etl::span last(size_t count) const { - return etl::span(mend - count, mend); + return etl::span(pend - count, pend); } #if ETL_USING_CPP11 @@ -707,11 +695,11 @@ namespace etl { if (COUNT == etl::dynamic_extent) { - return etl::span(mbegin + OFFSET, mend); + return etl::span(pbegin + OFFSET, pend); } else { - return etl::span(mbegin + OFFSET, mbegin + OFFSET + COUNT); + return etl::span(pbegin + OFFSET, pbegin + OFFSET + COUNT); } } #else @@ -724,11 +712,11 @@ namespace etl { if (COUNT == etl::dynamic_extent) { - return etl::span(mbegin + OFFSET, mend); + return etl::span(pbegin + OFFSET, pend); } else { - return etl::span(mbegin + OFFSET, mbegin + OFFSET + COUNT); + return etl::span(pbegin + OFFSET, pbegin + OFFSET + COUNT); } } #endif @@ -740,15 +728,15 @@ namespace etl { if (count == etl::dynamic_extent) { - return etl::span(mbegin + offset, mend); + return etl::span(pbegin + offset, pend); } - return etl::span(mbegin + offset, mbegin + offset + count); + return etl::span(pbegin + offset, pbegin + offset + count); } private: - element_type* mbegin; - element_type* mend; + pointer pbegin; + pointer pend; }; //************************************************************************* diff --git a/test/test_poly_span.cpp b/test/test_poly_span.cpp deleted file mode 100644 index 8d695088..00000000 --- a/test/test_poly_span.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2020 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/poly_span.h" - -#include -#include -#include -#include -#include - -namespace -{ - //*************************************************************************** - struct Base - { - virtual int value() const = 0; - - virtual bool operator==(const Base& o) const { return value() == o.value(); } - }; - - //*************************************************************************** - struct Derived : Base - { - Derived(int v) : m_value(v) {} - - int value() const override { return m_value; } - - int m_value; - }; - - //*************************************************************************** - struct AnotherBase - { - virtual double another_value() const { return v; }; - - double v = 0; - }; - - //*************************************************************************** - struct MultiDerived : AnotherBase, Base - { - MultiDerived(int v) : m_value(v) {} - - int value() const override { return m_value; } - - int m_value; - }; - - //*************************************************************************** - template - bool equal(const TSpan& span, TSource& source) - { - auto sb = std::begin(source); - return (span.size() == (std::end(source) - sb)) && std::equal(span.begin(), span.end(), sb); - } - - SUITE(test_poly_span) - { - //************************************************************************* - TEST(test_poly_span_defaultConstruct) - { - etl::poly_span s{}; - CHECK(s.empty()); - CHECK_EQUAL(0, s.size()); - CHECK(s.begin() == s.end()); - } - - //************************************************************************* - TEST(test_poly_span_constructFromVec) - { - std::vector v = { 1, 2, 3 }; - - etl::poly_span s = v; - CHECK_EQUAL(s[0], v[0]); - CHECK_EQUAL(s[1], v[1]); - CHECK_EQUAL(s[2], v[2]); - CHECK_EQUAL(v.size(), s.size()); - CHECK_EQUAL(sizeof(v[0]), s.element_size()); - CHECK(!s.empty()); - } - - //************************************************************************* - TEST(test_poly_span_constructFromVecRespectConst) - { - std::vector v; - const auto& cv = v; - etl::poly_span s1 = v; - etl::poly_span{v}; - etl::poly_span s2 = cv; - etl::poly_span{cv}; - etl::poly_span s3 = v; - etl::poly_span{v}; - // The line below shouldn't work if uncommented - // etl::poly_span{cv}; - } - - //************************************************************************* - TEST(test_poly_span_constructFromCArray) - { - int a[] = { 1, 2, 3 }; - etl::poly_span s = a; - CHECK_EQUAL(s[0], a[0]); - CHECK_EQUAL(s[1], a[1]); - CHECK_EQUAL(s[2], a[2]); - CHECK_EQUAL(3, s.size()); - CHECK_EQUAL(sizeof(a[0]), s.element_size()); - } - - //************************************************************************* - TEST(test_poly_span_constructFromCArrayRespectConst) - { - Derived ar[2] = { 1, 2 }; - const auto& car = ar; - etl::poly_span s1 = ar; - etl::poly_span{ar}; - etl::poly_span s2 = car; - etl::poly_span{car}; - etl::poly_span s3 = ar; - etl::poly_span{ar}; - // The line below shouldn't work if uncommented - // etl::poly_span{car}; - } - - //************************************************************************* - TEST(test_poly_span_constructFromArray) - { - std::array a = { 1, 2, 3 }; - - etl::poly_span s = a; - CHECK_EQUAL(s[0], a[0]); - CHECK_EQUAL(s[1], a[1]); - CHECK_EQUAL(s[2], a[2]); - } - - //************************************************************************* - TEST(test_poly_span_constructFromPolySpan) - { - std::array a = { 1, 2, 3 }; - etl::poly_span s1 = a; - etl::poly_span s2 = s1; - etl::poly_span{s2}; - CHECK(equal(s1, s2)); - } - - //************************************************************************* - TEST(test_poly_span_constructFromIterator) - { - std::vector v = { 1, 2, 3, 4 }; - - etl::poly_span s1{ v.begin() + 1, v.end() }; - CHECK_EQUAL(v.size() - 1, s1.size()); - CHECK_EQUAL(s1[0], v[1]); - CHECK_EQUAL(s1[1], v[2]); - CHECK_EQUAL(s1[2], v[3]); - - etl::poly_span s2{ v.data() + 1, v.data() + v.size() }; - CHECK(equal(s1, s2)); - - etl::poly_span s3{ v.cbegin(), v.size() }; - CHECK(equal(s3, v)); - } - - //************************************************************************* - TEST(test_poly_span_constructFromInitializerList) - { - const int data[] = { 1, 2, 3, 4, 5 }; - etl::poly_span s(data); - - CHECK_EQUAL(5, s.size()); - - for (int i = 0; i < 5; ++i) - { - //int x = s[i]; - //CHECK_EQUAL(i + 1, s[i]); - } - } - - //************************************************************************* - TEST(test_poly_span_DerivedToBase) - { - std::vector v1 = { 0, 1, 2 }; - - Derived a1[] = { 0, 1, 2 }; - CHECK(sizeof(Derived) > sizeof(Base)); - - etl::poly_span s1 = v1; - CHECK_EQUAL(sizeof(Derived), s1.element_size()); - etl::poly_span s2 = a1; - - auto it1 = s1.begin(); - auto it2 = s2.begin(); - - for (int i = 0; i < 3; ++i, ++it1, ++it2) - { - CHECK_EQUAL(i, s1[i].value()); - CHECK_EQUAL(i, s2[i].value()); - CHECK_EQUAL(i, it1->value()); - CHECK_EQUAL(i, it2->value()); - } - } - - //************************************************************************* - TEST(test_poly_span_MultiDerivedToBase) - { - std::vector v1 = { 0, 1, 2 }; - - etl::poly_span s1 = v1; - CHECK(static_cast(v1.data()) != static_cast(&s1.front())); - CHECK(equal(s1, v1)); - } - - //************************************************************************* - TEST(test_poly_span_typeProperties) - { - CHECK(std::is_trivial::iterator>::value); - CHECK(std::is_trivial::iterator>::value); - CHECK(std::is_trivial::const_iterator>::value); - CHECK(bool(std::is_base_of::iterator::iterator_category>::value)); - CHECK(std::is_trivially_copy_constructible>::value); - CHECK(std::is_trivially_copy_assignable>::value); - } - - //************************************************************************* - //TEST(test_poly_span_iterators) - //{ - // std::vector v = { 1, 2, 3 }; - // etl::poly_span s = v; - // using iterator = etl::poly_span::iterator; - // - // CHECK_EQUAL(s.end() - s.begin(), s.size()); - // CHECK_EQUAL(s.rend() - s.rbegin(), s.size()); - // - // iterator b = s.begin(); - // CHECK(b + s.size() == s.end()); - // CHECK_EQUAL(b[0], 1); - // CHECK(b < s.end()); - // CHECK(b != s.end()); - // CHECK(b + 2 > s.end() - 1); - - // etl::poly_span::const_iterator bc = b; - // CHECK(bc <= s.end()); - // CHECK_EQUAL(s.back(), *s.crbegin()); - // CHECK_EQUAL(s.front(), s.crend()[-1]); - // - // bc += 1; - // bc -= 1; - // CHECK(bc == s.cbegin()); - // CHECK(std::is_sorted(s.cbegin(), s.cend())); - //} - - //************************************************************************* - TEST(test_poly_span_randomAccessIteratorUse) - { - int data[] = { 25, 4, 3, -2, 1 }; - etl::poly_span s = data; - - std::sort(s.begin(), s.end()); - CHECK(std::is_sorted(std::begin(data), std::end(data))); - } - - //************************************************************************* - TEST(test_poly_span_subspan) - { - const int data[] = { 1, 2, 3, 4, 5 }; - etl::poly_span s(data); - - auto s1 = s.subspan(1, 2); - CHECK_EQUAL(2, s1.size()); - CHECK_EQUAL(s[1], s1[0]); - CHECK_EQUAL(s[2], s1[1]); - - auto s2 = s.subspan(2); - CHECK_EQUAL(3, s2.size()); - CHECK_EQUAL(s[2], s2[0]); - CHECK_EQUAL(s[4], s2[2]); - - auto s3 = s.subspan(0, 10); - CHECK_EQUAL(s.size(), s3.size()); - CHECK_THROW(s.subspan(6, 1), etl::poly_span_out_of_range); - } - - //************************************************************************* - TEST(test_poly_span_first) - { - const int data[] = { 1, 2, 3, 4, 5 }; - etl::poly_span s(data); - - CHECK_THROW(s.first(6), etl::poly_span_out_of_range); - CHECK_EQUAL(s.first(5).size(), 5); - CHECK(s.first(0).empty()); - - auto s1 = s.first(3); - CHECK_EQUAL(3, s1.size()); - CHECK_EQUAL(1, s1[0]); - CHECK_EQUAL(3, s1[2]); - } - - //************************************************************************* - TEST(test_poly_span_last) - { - const int data[] = { 1, 2, 3, 4, 5 }; - etl::poly_span s(data); - - CHECK_THROW(s.last(6), etl::poly_span_out_of_range); - CHECK_EQUAL(s.last(5).size(), 5); - - auto s2 = s.last(2); - CHECK_EQUAL(2, s2.size()); - CHECK_EQUAL(4, s2[0]); - CHECK_EQUAL(5, s2[1]); - } - - //************************************************************************* - TEST(test_poly_span_equal_view) - { - std::vector v = { 1.0, 2.0, 3.0 }; - etl::poly_span s1 = v; - etl::poly_span cs2 = v; - - CHECK(!etl::poly_span{}.equal_view(s1)); - CHECK(s1.equal_view(cs2)); - CHECK(s1.last(2).equal_view(cs2.subspan(1))); - } - - //************************************************************************* - TEST(test_poly_span_at) - { - const int data[] = { 1, 2, 3 }; - etl::poly_span s(data); - - CHECK_EQUAL(s.at(0), 1); - CHECK_EQUAL(s.at(2), 3); - CHECK_THROW(s.at(3), etl::poly_span_out_of_range); - CHECK_THROW(s.at(-1), etl::poly_span_out_of_range); - } - } -} diff --git a/test/test_poly_span_dynamic_extent.cpp b/test/test_poly_span_dynamic_extent.cpp new file mode 100644 index 00000000..a86ed306 --- /dev/null +++ b/test/test_poly_span_dynamic_extent.cpp @@ -0,0 +1,381 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2020 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/poly_span.h" + +#include +#include +#include +#include +#include + +namespace +{ + //*************************************************************************** + struct Base + { + virtual int value() const = 0; + + virtual bool operator ==(const Base& rhs) const + { + return value() == rhs.value(); + } + }; + + //*************************************************************************** + struct AnotherBase + { + virtual double another_value() const = 0; + + virtual bool operator ==(const AnotherBase& rhs) const + { + return another_value() == rhs.another_value(); + } + }; + + //*************************************************************************** + struct Derived : Base + { + Derived(int v_) + : v1(v_) + { + } + + int value() const override + { + return v1; + } + + int v1; + }; + + //*************************************************************************** + struct MultiDerived : AnotherBase, Base + { + MultiDerived(int v1_, double v2_) + : v1(v1_) + , v2(v2_) + { + } + + int value() const override + { + return v1; + } + + double another_value() const override + { + return v2; + } + + int v1; + double v2; + }; + + //*************************************************************************** + template + bool equal(const TSpan& span, TSource& source) + { + auto sb = std::begin(source); + return (span.size() == (std::end(source) - sb)) && std::equal(span.begin(), span.end(), sb); + } + + SUITE(test_poly_span_dynamic_extent) + { + //************************************************************************* + TEST(test_poly_span_default_construct) + { + etl::poly_span s; + CHECK_EQUAL(0U, s.size_of_element()); + CHECK(s.empty()); + CHECK_EQUAL(0U, s.size()); + CHECK_EQUAL(0U, s.size_bytes()); + //CHECK(s.begin() == s.end()); + } + + //************************************************************************* + TEST(test_poly_span_construct_from_iterators) + { + std::vector data = { 1, 2, 3, 4 }; + + etl::poly_span s(data.begin(), data.end()); + CHECK_EQUAL(sizeof(Derived), s.size_of_element()); + CHECK(!s.empty()); + CHECK_EQUAL(data.size(), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + + //************************************************************************* + TEST(test_poly_span_construct_from_c_array) + { + Derived data[] = { 1, 2, 3, 4 }; + etl::poly_span s(data); + CHECK_EQUAL(sizeof(Derived), s.size_of_element()); + CHECK(!s.empty()); + CHECK_EQUAL(std::size(data), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + + //************************************************************************* + TEST(test_poly_span_construct_from_const_c_array) + { + const Derived data[] = { 1, 2, 3, 4 }; + etl::poly_span s(data); + CHECK_EQUAL(sizeof(Derived), s.size_of_element()); + CHECK(!s.empty()); + CHECK_EQUAL(std::size(data), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + + //************************************************************************* + TEST(test_poly_span_construct_from_std_array) + { + std::array data{ Derived(1), Derived(2), Derived(3), Derived(4) }; + etl::poly_span s(data); + CHECK(!s.empty()); + CHECK_EQUAL(data.size(), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + + //************************************************************************* + TEST(test_poly_span_construct_from_const_std_array) + { + const std::array data{ Derived(1), Derived(2), Derived(3), Derived(4) }; + etl::poly_span s(data); + CHECK(!s.empty()); + CHECK_EQUAL(data.size(), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + + //************************************************************************* + TEST(test_poly_span_construct_from_etl_array) + { + etl::array data{ Derived(1), Derived(2), Derived(3), Derived(4) }; + etl::poly_span s(data); + CHECK(!s.empty()); + CHECK_EQUAL(data.size(), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + + //************************************************************************* + TEST(test_poly_span_construct_from_const_etl_array) + { + const etl::array data{ Derived(1), Derived(2), Derived(3), Derived(4) }; + etl::poly_span s(data); + CHECK(!s.empty()); + CHECK_EQUAL(data.size(), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + + //************************************************************************* + TEST(test_poly_span_copy_construct) + { + std::array a = { 1, 2, 3, 4 }; + etl::poly_span s1 = a; + etl::poly_span s2 = s1; + const etl::poly_span s3 = s1; + //CHECK(equal(s1, s2)); + CHECK(!s2.empty()); + CHECK(!s3.empty()); + } + + //************************************************************************* + TEST(test_poly_span_multi_derived) + { + std::vector data = { { 0, 1.2 }, { 1, 2.3 }, { 2, 3.4 }, { 3, 4.5 } }; + + etl::poly_span s1(data.begin(), data.end()); + etl::poly_span s2(data.begin(), data.end()); + + CHECK_EQUAL(data[0].value(), s1[0].value()); + CHECK_EQUAL(data[1].value(), s1[1].value()); + CHECK_EQUAL(data[2].value(), s1[2].value()); + CHECK_EQUAL(data[3].value(), s1[3].value()); + + CHECK_EQUAL(data[0].another_value(), s2[0].another_value()); + CHECK_EQUAL(data[1].another_value(), s2[1].another_value()); + CHECK_EQUAL(data[2].another_value(), s2[2].another_value()); + CHECK_EQUAL(data[3].another_value(), s2[3].another_value()); + } + + ////************************************************************************* + //TEST(test_poly_span_typeProperties) + //{ + // CHECK(std::is_trivial::iterator>::value); + // CHECK(std::is_trivial::iterator>::value); + // CHECK(std::is_trivial::const_iterator>::value); + // CHECK(bool(std::is_base_of::iterator::iterator_category>::value)); + // CHECK(std::is_trivially_copy_constructible>::value); + // CHECK(std::is_trivially_copy_assignable>::value); + //} + + ////************************************************************************* + ////TEST(test_poly_span_iterators) + ////{ + //// std::vector v = { 1, 2, 3 }; + //// etl::poly_span s = v; + //// using iterator = etl::poly_span::iterator; + //// + //// CHECK_EQUAL(s.end() - s.begin(), s.size()); + //// CHECK_EQUAL(s.rend() - s.rbegin(), s.size()); + //// + //// iterator b = s.begin(); + //// CHECK(b + s.size() == s.end()); + //// CHECK_EQUAL(b[0], 1); + //// CHECK(b < s.end()); + //// CHECK(b != s.end()); + //// CHECK(b + 2 > s.end() - 1); + + //// etl::poly_span::const_iterator bc = b; + //// CHECK(bc <= s.end()); + //// CHECK_EQUAL(s.back(), *s.crbegin()); + //// CHECK_EQUAL(s.front(), s.crend()[-1]); + //// + //// bc += 1; + //// bc -= 1; + //// CHECK(bc == s.cbegin()); + //// CHECK(std::is_sorted(s.cbegin(), s.cend())); + ////} + + //************************************************************************* + TEST(test_poly_span_randomAccessIteratorUse) + { + int data[] = { 25, 4, 3, -2, 1 }; + etl::poly_span s = data; + +// std::sort(s.begin(), s.end()); +// CHECK(std::is_sorted(std::begin(data), std::end(data))); + } + + //************************************************************************* + TEST(test_poly_span_subspan) + { + const Derived data[] = { 1, 2, 3, 4, 5 }; + // etl::poly_span s(data); + + // auto s1 = s.subspan(1, 2); + // CHECK_EQUAL(2, s1.size()); + // CHECK_EQUAL(s[1], s1[0]); + // CHECK_EQUAL(s[2], s1[1]); + + // auto s2 = s.subspan(2); + // CHECK_EQUAL(3, s2.size()); + // CHECK_EQUAL(s[2], s2[0]); + // CHECK_EQUAL(s[4], s2[2]); + + // auto s3 = s.subspan(0, 10); + // CHECK_EQUAL(s.size(), s3.size()); + // CHECK_THROW(s.subspan(6, 1), etl::poly_span_out_of_range); + } + + ////************************************************************************* + //TEST(test_poly_span_first) + //{ + // const int data[] = { 1, 2, 3, 4, 5 }; + // etl::poly_span s(data); + // + // CHECK_THROW(s.first(6), etl::poly_span_out_of_range); + // CHECK_EQUAL(s.first(5).size(), 5); + // CHECK(s.first(0).empty()); + // + // auto s1 = s.first(3); + // CHECK_EQUAL(3, s1.size()); + // CHECK_EQUAL(1, s1[0]); + // CHECK_EQUAL(3, s1[2]); + //} + + ////************************************************************************* + //TEST(test_poly_span_last) + //{ + // const int data[] = { 1, 2, 3, 4, 5 }; + // etl::poly_span s(data); + // + // CHECK_THROW(s.last(6), etl::poly_span_out_of_range); + // CHECK_EQUAL(s.last(5).size(), 5); + // + // auto s2 = s.last(2); + // CHECK_EQUAL(2, s2.size()); + // CHECK_EQUAL(4, s2[0]); + // CHECK_EQUAL(5, s2[1]); + //} + + ////************************************************************************* + //TEST(test_poly_span_equal_view) + //{ + // std::vector v = { 1.0, 2.0, 3.0 }; + // etl::poly_span s1 = v; + // etl::poly_span cs2 = v; + + // CHECK(!etl::poly_span{}.equal_view(s1)); + // CHECK(s1.equal_view(cs2)); + // CHECK(s1.last(2).equal_view(cs2.subspan(1))); + //} + + ////************************************************************************* + //TEST(test_poly_span_at) + //{ + // const int data[] = { 1, 2, 3 }; + // etl::poly_span s(data); + // + // CHECK_EQUAL(s.at(0), 1); + // CHECK_EQUAL(s.at(2), 3); + // CHECK_THROW(s.at(3), etl::poly_span_out_of_range); + // CHECK_THROW(s.at(-1), etl::poly_span_out_of_range); + //} + } +} diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index eb377325..8f8958b1 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -5313,7 +5313,34 @@ true true - + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true true @@ -10975,7 +11002,7 @@ - + diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index 82a0e6dc..bcf9d2df 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -3266,7 +3266,7 @@ Tests\Sanity Checks\Source - + Tests\Containers