///\file /****************************************************************************** The MIT License(MIT) 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 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_POLY_SPAN_INCLUDED #define ETL_POLY_SPAN_INCLUDED #include "platform.h" #include "iterator.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_STL && ETL_USING_CPP11 #include #endif ///\defgroup poly_span poly_span ///\ingroup containers namespace etl { template class poly_span; namespace private_poly_span { //************************************************************************* // Iterator //************************************************************************* template class iterator { public: template friend class etl::poly_span; template friend class const_iterator; typedef TBase value_type; typedef ptrdiff_t difference_type; typedef TBase* pointer; typedef TBase& reference; typedef ETL_OR_STD::random_access_iterator_tag iterator_category; //***************************************** iterator() : ptr(ETL_NULLPTR) , element_size(0U) { } //***************************************** iterator(const iterator& other) : ptr(other.ptr) , element_size(other.element_size) { } //***************************************** iterator& operator =(const iterator& rhs) { ptr = rhs.ptr; element_size = rhs.element_size; return *this; } //***************************************** TBase& operator *() const { return *ptr; } //***************************************** TBase* operator ->() const { return ptr; } //***************************************** iterator& operator ++() { ptr = reinterpret_cast(reinterpret_cast(ptr) + element_size); return *this; } //***************************************** iterator operator ++(int) { iterator temp(*this); ptr = reinterpret_cast(reinterpret_cast(ptr) + element_size); return temp; } //***************************************** iterator& operator --() { ptr = reinterpret_cast(reinterpret_cast(ptr) - element_size); return *this; } //***************************************** iterator operator --(int) { iterator temp(*this); ptr = reinterpret_cast(reinterpret_cast(ptr) - element_size); return temp; } //*************************************************** iterator& operator +=(difference_type offset) { ptr = reinterpret_cast(reinterpret_cast(ptr) + (offset * difference_type(element_size))); return *this; } //*************************************************** iterator& operator -=(difference_type offset) { ptr = reinterpret_cast(reinterpret_cast(ptr) - (offset * difference_type(element_size))); return *this; } //*************************************************** friend bool operator == (const iterator& lhs, const iterator& rhs) { return (lhs.ptr == rhs.ptr) && (lhs.element_size == rhs.element_size); } //*************************************************** friend bool operator != (const iterator& lhs, const iterator& rhs) { return !(lhs == rhs); } //*************************************************** friend bool operator < (const iterator& lhs, const iterator& rhs) { return lhs.ptr < rhs.ptr; } //*************************************************** friend bool operator <= (const iterator& lhs, const iterator& rhs) { return !(lhs > rhs); } //*************************************************** friend bool operator > (const iterator& lhs, const iterator& rhs) { return (rhs < lhs); } //*************************************************** friend bool operator >= (const iterator& lhs, const iterator& rhs) { return !(lhs < rhs); } //*************************************************** friend iterator operator + (const iterator& lhs, difference_type offset) { iterator temp(lhs); temp += offset; return temp; } //*************************************************** friend iterator operator + (difference_type offset, const iterator& rhs) { iterator temp(rhs); temp += offset; return temp; } //*************************************************** friend iterator operator - (const iterator& lhs, difference_type offset) { iterator temp(lhs); temp -= offset; return temp; } //*************************************************** friend iterator operator - (difference_type offset, const iterator& rhs) { iterator temp(rhs); temp -= offset; return temp; } //*************************************************** friend difference_type operator - (const iterator& lhs, const iterator& rhs) { return lhs.ptr - rhs.ptr; } private: //*************************************************** iterator(TBase* pbegin_, size_t index_, size_t element_size_) : element_size(element_size_) { ptr = reinterpret_cast(reinterpret_cast(pbegin_) + (index_ * element_size)); } TBase* ptr; size_t element_size; }; } //*************************************************************************** /// Poly Span - Fixed Extent //*************************************************************************** template class poly_span { public: 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 private_poly_span::iterator iterator; typedef ETL_OR_STD::reverse_iterator 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_)) , element_size(sizeof(typename etl::iterator_traits::value_type)) { typedef typename etl::iterator_traits::value_type data_type; 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"); } //************************************************************************* /// Construct from iterators //************************************************************************* template ETL_CONSTEXPR poly_span(const TIterator begin_, const TIterator /*end_*/) : pbegin(etl::addressof(*begin_)) , element_size(sizeof(typename etl::iterator_traits::value_type)) { 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"); } //************************************************************************* /// Construct from C array //************************************************************************* template ETL_CONSTEXPR poly_span(U(&begin_)[N]) ETL_NOEXCEPT : pbegin(begin_) , element_size(sizeof(U)) { 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"); } //************************************************************************* /// Construct from etl::array. //************************************************************************* template ETL_CONSTEXPR poly_span(etl::array& a) ETL_NOEXCEPT : pbegin(a.data()) , element_size(sizeof(U)) { 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"); } //************************************************************************* /// Construct from etl::array. //************************************************************************* template ETL_CONSTEXPR poly_span(const etl::array& a) ETL_NOEXCEPT : pbegin(a.data()) , element_size(sizeof(U)) { 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"); } #if ETL_USING_STL && ETL_USING_CPP11 //************************************************************************* /// Construct from std::array. //************************************************************************* template ETL_CONSTEXPR poly_span(std::array& a) ETL_NOEXCEPT : pbegin(a.data()) , element_size(sizeof(U)) { 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"); } //************************************************************************* /// Construct from std::array. //************************************************************************* template ETL_CONSTEXPR poly_span(const std::array& a) ETL_NOEXCEPT : pbegin(a.data()) , element_size(sizeof(U)) { 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"); } #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 *element_at(Extent - 1U); } //************************************************************************* /// 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(end()); } //************************************************************************* /// Returns a reverse iterator to the end of the poly_span. //************************************************************************* ETL_CONSTEXPR reverse_iterator rend() const ETL_NOEXCEPT { return reverse_iterator(begin()); } //************************************************************************* /// 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; element_size = other.element_size; return *this; } //************************************************************************* /// Assign from a poly_span. //************************************************************************* template ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT { pbegin = other.pbegin; element_size = other.element_size; 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_NODISCARD ETL_CONSTEXPR etl::poly_span first() const ETL_NOEXCEPT { return etl::poly_span(pbegin, 0U, COUNT, element_size); } //************************************************************************* /// Obtains a poly_span that is a view over the first count elements of this poly_span. //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR etl::poly_span first(size_t count) const { return etl::poly_span(pbegin, 0U, count, element_size); } //************************************************************************* /// Obtains a poly_span that is a view over the last COUNT elements of this poly_span. //************************************************************************* template ETL_NODISCARD ETL_CONSTEXPR etl::poly_span last() const ETL_NOEXCEPT { return etl::poly_span(pbegin, Extent - COUNT, COUNT, element_size); } //************************************************************************* /// Obtains a poly_span that is a view over the last count elements of this poly_span. //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR etl::poly_span last(size_t count) const ETL_NOEXCEPT { return etl::poly_span(pbegin, Extent - count, count, element_size); } #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_NODISCARD ETL_CONSTEXPR etl::poly_span subspan() const ETL_NOEXCEPT { return (COUNT == etl::dynamic_extent) ? etl::poly_span(pbegin, OFFSET, Extent, element_size) : etl::poly_span(pbegin, OFFSET, COUNT, element_size); } #else //************************************************************************* /// Obtains a poly_span that is a view from OFFSET over the next COUNT elements of this poly_span. //************************************************************************* template etl::poly_span subspan() const { if (COUNT == etl::dynamic_extent) { return etl::poly_span(pbegin, OFFSET, Extent, element_size); } else { return etl::poly_span(pbegin, OFFSET, element_size); } } #endif //************************************************************************* /// Obtains a poly_span that is a view from 'offset' over the next 'count' elements of this poly_span. //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR etl::poly_span subspan(size_t offset, size_t count = etl::dynamic_extent) const ETL_NOEXCEPT { return (count == etl::dynamic_extent) ? etl::poly_span(pbegin, offset, Extent, element_size) : etl::poly_span(pbegin, offset, count, element_size); } protected: //*************************************************************************** template struct char_ptr_type { typedef typename etl::conditional::value, const char*, char*>::type type; }; typedef typename char_ptr_type::type char_ptr_t; //*************************************************************************** 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 iterator + offset + element size /// extent_ is ignored. //************************************************************************* poly_span(TBase* pbegin_, size_t offset_, size_t /*extent_*/, size_t element_size_) ETL_NOEXCEPT : pbegin(reinterpret_cast(reinterpret_cast(pbegin_) + (offset_ * element_size_))) , element_size(element_size_) { } private: pointer pbegin; size_t element_size; }; template ETL_CONSTANT size_t poly_span::extent; //*************************************************************************** /// Poly Span - Dynamic Extent //*************************************************************************** template class poly_span { public: 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 etl::private_poly_span::iterator iterator; typedef ETL_OR_STD::reverse_iterator reverse_iterator; static ETL_CONSTANT size_t extent = etl::dynamic_extent; template friend class poly_span; //************************************************************************* /// Default constructor. //************************************************************************* ETL_CONSTEXPR poly_span() ETL_NOEXCEPT : pbegin(ETL_NULLPTR) , element_size(0U) , span_extent(0U) { } //************************************************************************* /// Construct from iterator + size //************************************************************************* template ETL_CONSTEXPR poly_span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT : pbegin(etl::addressof(*begin_)) , element_size(sizeof(typename etl::iterator_traits::value_type)) , span_extent(size_) { 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"); } //************************************************************************* /// Construct from iterators //************************************************************************* template ETL_CONSTEXPR poly_span(const TIterator begin_, const TIterator end_) : pbegin(etl::addressof(*begin_)) , element_size(sizeof(typename etl::iterator_traits::value_type)) , span_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"); } //************************************************************************* /// Construct from C array //************************************************************************* template ETL_CONSTEXPR poly_span(U(&begin_)[N]) ETL_NOEXCEPT : pbegin(begin_) , element_size(sizeof(U)) , span_extent(N) { ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); } //************************************************************************* /// Construct from etl::array. //************************************************************************* template ETL_CONSTEXPR poly_span(etl::array& a) ETL_NOEXCEPT : pbegin(a.data()) , element_size(sizeof(U)) , span_extent(N) { ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); } //************************************************************************* /// Construct from etl::array. //************************************************************************* template ETL_CONSTEXPR poly_span(const etl::array& a) ETL_NOEXCEPT : pbegin(a.data()) , element_size(sizeof(U)) , span_extent(N) { ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); } #if ETL_USING_STL && ETL_USING_CPP11 //************************************************************************* /// Construct from std::array. //************************************************************************* template ETL_CONSTEXPR poly_span(std::array& a) ETL_NOEXCEPT : pbegin(a.data()) , element_size(sizeof(U)) , span_extent(N) { ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of U"); } //************************************************************************* /// Construct from std::array. //************************************************************************* template ETL_CONSTEXPR poly_span(const std::array& a) ETL_NOEXCEPT : pbegin(a.data()) , element_size(sizeof(U)) , span_extent(N) { ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of U"); } #endif //************************************************************************* /// Copy constructor //************************************************************************* ETL_CONSTEXPR poly_span(const poly_span& other) ETL_NOEXCEPT : pbegin(other.pbegin) , element_size(other.element_size) , span_extent(other.span_extent) { } //************************************************************************* /// Copy constructor //************************************************************************* template ETL_CONSTEXPR poly_span(const poly_span& other) ETL_NOEXCEPT : pbegin(other.pbegin) , element_size(other.element_size) , span_extent(other.span_extent) { } //************************************************************************* /// 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 *element_at(span_extent - 1U); } //************************************************************************* /// 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, span_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(end()); } //************************************************************************* /// Returns a reverse iterator to the end of the poly_span. //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR reverse_iterator rend() const ETL_NOEXCEPT { return reverse_iterator(begin()); } //************************************************************************* /// Returns true if the poly_span size is zero. //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT { return (span_extent == 0); } //************************************************************************* /// Returns the size of the poly_span. //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT { return span_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 * span_extent; } //************************************************************************* /// Assign from a poly_span. //************************************************************************* ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT { pbegin = other.pbegin; element_size = other.element_size; span_extent = other.span_extent; return *this; } //************************************************************************* /// Assign from a poly_span. //************************************************************************* template ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT { pbegin = other.pbegin; element_size = other.element_size; span_extent = other.span_extent; 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_NODISCARD ETL_CONSTEXPR etl::poly_span first() const ETL_NOEXCEPT { return etl::poly_span(pbegin, 0U, COUNT, element_size); } //************************************************************************* /// Obtains a poly_span that is a view over the first count elements of this poly_span. //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR etl::poly_span first(size_t count) const ETL_NOEXCEPT { return etl::poly_span(pbegin, 0U, count, element_size); } //************************************************************************* /// Obtains a poly_span that is a view over the last COUNT elements of this poly_span. //************************************************************************* template ETL_NODISCARD ETL_CONSTEXPR etl::poly_span last() const ETL_NOEXCEPT { return etl::poly_span(pbegin, span_extent - COUNT, COUNT, element_size); } //************************************************************************* /// Obtains a poly_span that is a view over the last count elements of this poly_span. //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR etl::poly_span last(size_t count) const ETL_NOEXCEPT { return etl::poly_span(pbegin, span_extent - count, count, element_size); } #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_NODISCARD ETL_CONSTEXPR etl::poly_span subspan() const ETL_NOEXCEPT { return (COUNT == etl::dynamic_extent) ? etl::poly_span(pbegin, OFFSET, span_extent, element_size) : etl::poly_span(pbegin, OFFSET, COUNT, element_size); } #else //************************************************************************* /// Obtains a poly_span that is a view from OFFSET over the next COUNT elements of this poly_span. //************************************************************************* template etl::poly_span subspan() const { if (COUNT == etl::dynamic_extent) { return etl::poly_span(pbegin, OFFSET, span_extent, element_size); } else { return etl::poly_span(pbegin, OFFSET, span_extent, element_size); } } #endif //************************************************************************* /// Obtains a poly_span that is a view from 'offset' over the next 'count' elements of this poly_span. //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR etl::poly_span subspan(size_t offset, size_t count = etl::dynamic_extent) const ETL_NOEXCEPT { return (count == etl::dynamic_extent) ? etl::poly_span(pbegin, offset, span_extent - offset, element_size) : etl::poly_span(pbegin, offset, count, element_size); } protected: //************************************************************************* /// Construct from iterator + offset + size + element size //************************************************************************* poly_span(TBase* pbegin_, size_t offset_, size_t extent_, size_t element_size_) ETL_NOEXCEPT : pbegin(reinterpret_cast(reinterpret_cast(pbegin_) + (offset_ * element_size_))) , element_size(element_size_) , span_extent(extent_) { } private: //*************************************************************************** template struct char_ptr_type { typedef typename etl::conditional::value, const char*, char*>::type type; }; typedef typename char_ptr_type::type char_ptr_t; //*************************************************************************** pointer element_at(size_t index) const ETL_NOEXCEPT { char_ptr_t base = reinterpret_cast(pbegin); return reinterpret_cast(base + (index * element_size)); } pointer pbegin; size_t element_size; size_t span_extent; }; template ETL_CONSTANT size_t poly_span::extent; //************************************************************************* /// Template deduction guides. //************************************************************************* #if ETL_USING_CPP17 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>; template poly_span(T(&)[N]) ->poly_span; template poly_span(etl::array&) ->poly_span; template poly_span(const etl::array&) ->poly_span; #if ETL_USING_STL template poly_span(std::array&) ->poly_span; template poly_span(const std::array&) ->poly_span; #endif #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.data()), reinterpret_cast(view.data() + view.size())); } }; #endif } #endif