Skip to content

Commit fc638a9

Browse files
rolandreichweinbmwJohn Wellbelove
authored andcommitted
etl::span: Add advance(), copy(), reinterpret_as() (#1024)
* etl::span: Add advance(), copy(), reinterpret_as() * Added further tests for span::reinterpret_as * Fix size of unaligned_type on Windows Multiple inheritance leads to additional 1 byte for the second base class. Fixing it by not inheriting but aggregating via typedef.
1 parent 071a983 commit fc638a9

File tree

6 files changed

+330
-17
lines changed

6 files changed

+330
-17
lines changed

include/etl/file_error_numbers.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,6 @@ SOFTWARE.
105105
#define ETL_BASE64_FILE_ID "72"
106106
#define ETL_SINGLETON_BASE_FILE_ID "73"
107107
#define ETL_UNALIGNED_TYPE_FILE_ID "74"
108+
#define ETL_SPAN_FILE_ID "75"
109+
108110
#endif

include/etl/span.h

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ SOFTWARE.
3232
#define ETL_SPAN_INCLUDED
3333

3434
#include "platform.h"
35+
36+
#include "error_handler.h"
37+
#include "exception.h"
38+
#include "alignment.h"
3539
#include "iterator.h"
3640
#include "algorithm.h"
3741
#include "circular_iterator.h"
@@ -55,6 +59,34 @@ SOFTWARE.
5559

5660
namespace etl
5761
{
62+
//***************************************************************************
63+
///\ingroup span
64+
/// Exception base for span
65+
//***************************************************************************
66+
class span_exception : public exception
67+
{
68+
public:
69+
70+
span_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
71+
: exception(reason_, file_name_, line_number_)
72+
{
73+
}
74+
};
75+
76+
//***************************************************************************
77+
///\ingroup span
78+
/// Bad alignment exception.
79+
//***************************************************************************
80+
class span_alignment_exception : public span_exception
81+
{
82+
public:
83+
84+
span_alignment_exception(string_type file_name_, numeric_type line_number_)
85+
: span_exception(ETL_ERROR_TEXT("span:alignment", ETL_SPAN_FILE_ID"A"), file_name_, line_number_)
86+
{
87+
}
88+
};
89+
5890
//***************************************************************************
5991
/// Span - Fixed Extent
6092
//***************************************************************************
@@ -426,6 +458,18 @@ namespace etl
426458
: etl::span<element_type, etl::dynamic_extent>(pbegin + offset, pbegin + offset + count);
427459
}
428460

461+
//*************************************************************************
462+
/// Reinterpret the span as a span with different element type.
463+
//*************************************************************************
464+
template<typename TNew>
465+
ETL_NODISCARD ETL_CONSTEXPR14 etl::span<TNew, etl::dynamic_extent> reinterpret_as() const
466+
{
467+
ETL_ASSERT(etl::is_aligned<etl::alignment_of<TNew>::value>(pbegin), ETL_ERROR(span_alignment_exception));
468+
469+
return etl::span<TNew, etl::dynamic_extent>(reinterpret_cast<TNew*>(pbegin),
470+
Extent * sizeof(element_type) / sizeof(TNew));
471+
}
472+
429473
private:
430474

431475
pointer pbegin;
@@ -812,6 +856,28 @@ namespace etl
812856
: etl::span<element_type, etl::dynamic_extent>(pbegin + offset, pbegin + offset + count);
813857
}
814858

859+
//*************************************************************************
860+
/// Moves the pointer to the first element of the span further by a specified number of elements.
861+
///\tparam elements Number of elements to move forward
862+
//*************************************************************************
863+
void advance(size_t elements) ETL_NOEXCEPT
864+
{
865+
elements = etl::min(elements, size());
866+
pbegin += elements;
867+
}
868+
869+
//*************************************************************************
870+
/// Reinterpret the span as a span with different element type.
871+
//*************************************************************************
872+
template<typename TNew>
873+
ETL_NODISCARD ETL_CONSTEXPR14 etl::span<TNew, etl::dynamic_extent> reinterpret_as() const
874+
{
875+
ETL_ASSERT(etl::is_aligned<etl::alignment_of<TNew>::value>(pbegin), ETL_ERROR(span_alignment_exception));
876+
877+
return etl::span<TNew, etl::dynamic_extent>(reinterpret_cast<TNew*>(pbegin),
878+
(pend - pbegin) * sizeof(element_type) / sizeof(TNew));
879+
}
880+
815881
private:
816882

817883
pointer pbegin;
@@ -884,6 +950,33 @@ namespace etl
884950
etl::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
885951
}
886952

953+
//*************************************************************************
954+
/// Copy complete element data from one span to another. If the destination
955+
/// span is bigger than the source span, only the initial part of
956+
/// destination span is overwritten.
957+
///\param src Source
958+
///\param dst Destination
959+
///\return true, if copy was successful (including empty source span, or
960+
/// spans pointing to the same address)
961+
///\return false, if the destination span is shorter than the source span.
962+
//*************************************************************************
963+
template <typename T1, size_t N1, typename T2, size_t N2>
964+
typename etl::enable_if<etl::is_same<typename etl::remove_cv<T1>::type, typename etl::remove_cv<T2>::type>::value &&
965+
!etl::is_const<T2>::value, bool>::type
966+
copy(const etl::span<T1, N1>& src, const etl::span<T2, N2>& dst)
967+
{
968+
if (src.empty() || (src.begin() == dst.begin()))
969+
{
970+
return true;
971+
}
972+
if (src.size() > dst.size())
973+
{
974+
return false;
975+
}
976+
(void) etl::copy(src.begin(), src.end(), dst.begin());
977+
return true;
978+
}
979+
887980
//*************************************************************************
888981
/// Template deduction guides.
889982
//*************************************************************************

include/etl/unaligned_type.h

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -449,14 +449,15 @@ namespace etl
449449
//*************************************************************************
450450
template <typename T, int Endian_>
451451
ETL_PACKED_CLASS(unaligned_type) : public private_unaligned_type::unaligned_type_storage<sizeof(T)>
452-
, public private_unaligned_type::unaligned_copy<sizeof(T), Endian_, etl::is_floating_point<T>::value ? false : true>
453452
{
454453
public:
455454

456455
ETL_STATIC_ASSERT(etl::is_integral<T>::value || etl::is_floating_point<T>::value, "Unaligned type must be integral or floating point");
457456

458457
typedef T value_type;
459458

459+
typedef private_unaligned_type::unaligned_copy<sizeof(T), Endian_, etl::is_floating_point<T>::value ? false : true> unaligned_copy;
460+
460461
typedef typename private_unaligned_type::unaligned_type_storage<sizeof(T)>::storage_type storage_type;
461462
typedef typename private_unaligned_type::unaligned_type_storage<sizeof(T)>::pointer pointer;
462463
typedef typename private_unaligned_type::unaligned_type_storage<sizeof(T)>::const_pointer const_pointer;
@@ -480,7 +481,7 @@ namespace etl
480481
//*************************************************************************
481482
unaligned_type(T value)
482483
{
483-
this->copy_value_to_store(value, this->storage);
484+
unaligned_copy::copy_value_to_store(value, this->storage);
484485
}
485486

486487
//*************************************************************************
@@ -506,7 +507,7 @@ namespace etl
506507
//*************************************************************************
507508
unaligned_type(const unaligned_type<T, Endian>& other)
508509
{
509-
this->copy_store_to_store(other.data(), Endian, this->storage);
510+
unaligned_copy::copy_store_to_store(other.data(), Endian, this->storage);
510511
}
511512

512513
//*************************************************************************
@@ -515,15 +516,15 @@ namespace etl
515516
template <int Endian_Other>
516517
unaligned_type(const unaligned_type<T, Endian_Other>& other)
517518
{
518-
this->copy_store_to_store(other.data(), Endian_Other, this->storage);
519+
unaligned_copy::copy_store_to_store(other.data(), Endian_Other, this->storage);
519520
}
520521

521522
//*************************************************************************
522523
/// Assignment operator
523524
//*************************************************************************
524525
unaligned_type& operator =(T value)
525526
{
526-
this->copy_value_to_store(value, this->storage);
527+
unaligned_copy::copy_value_to_store(value, this->storage);
527528

528529
return *this;
529530
}
@@ -533,7 +534,7 @@ namespace etl
533534
//*************************************************************************
534535
unaligned_type& operator =(const unaligned_type<T, Endian_>& other)
535536
{
536-
this->copy_store_to_store(other.data(), Endian_, this->storage);
537+
unaligned_copy::copy_store_to_store(other.data(), Endian_, this->storage);
537538

538539
return *this;
539540
}
@@ -544,7 +545,7 @@ namespace etl
544545
template <int Endian_Other>
545546
unaligned_type& operator =(const unaligned_type<T, Endian_Other>& other)
546547
{
547-
this->copy_store_to_store(other.data(), Endian_Other, this->storage);
548+
unaligned_copy::copy_store_to_store(other.data(), Endian_Other, this->storage);
548549

549550
return *this;
550551
}
@@ -556,7 +557,7 @@ namespace etl
556557
{
557558
T value = T();
558559

559-
this->copy_store_to_value(this->storage, value);
560+
unaligned_copy::copy_store_to_value(this->storage, value);
560561

561562
return value;
562563
}
@@ -568,7 +569,7 @@ namespace etl
568569
{
569570
T value = T();
570571

571-
this->copy_store_to_value(this->storage, value);
572+
unaligned_copy::copy_store_to_value(this->storage, value);
572573

573574
return value;
574575
}
@@ -589,7 +590,6 @@ namespace etl
589590
//*************************************************************************
590591
template <typename T, int Endian_>
591592
ETL_PACKED_CLASS(unaligned_type_ext) : public private_unaligned_type::unaligned_type_storage_ext<sizeof(T)>
592-
, public private_unaligned_type::unaligned_copy<sizeof(T), Endian_, etl::is_floating_point<T>::value ? false : true>
593593
{
594594
public:
595595

@@ -600,6 +600,8 @@ namespace etl
600600

601601
typedef T value_type;
602602

603+
typedef private_unaligned_type::unaligned_copy<sizeof(T), Endian_, etl::is_floating_point<T>::value ? false : true> unaligned_copy;
604+
603605
typedef typename private_unaligned_type::unaligned_type_storage_ext<sizeof(T)>::storage_type storage_type;
604606
typedef typename private_unaligned_type::unaligned_type_storage_ext<sizeof(T)>::pointer pointer;
605607
typedef typename private_unaligned_type::unaligned_type_storage_ext<sizeof(T)>::const_pointer const_pointer;
@@ -625,7 +627,7 @@ namespace etl
625627
unaligned_type_ext(T value, pointer storage_)
626628
: private_unaligned_type::unaligned_type_storage_ext<Size>(storage_)
627629
{
628-
this->copy_value_to_store(value, this->storage);
630+
unaligned_copy::copy_value_to_store(value, this->storage);
629631
}
630632

631633
//*************************************************************************
@@ -635,7 +637,7 @@ namespace etl
635637
unaligned_type_ext(const unaligned_type_ext<T, Endian_Other>& other, pointer storage_)
636638
: private_unaligned_type::unaligned_type_storage_ext<Size>(storage_)
637639
{
638-
this->copy_store_to_store(other.data(), Endian_Other, this->storage);
640+
unaligned_copy::copy_store_to_store(other.data(), Endian_Other, this->storage);
639641
}
640642

641643
#if ETL_USING_CPP11
@@ -670,7 +672,7 @@ namespace etl
670672
//*************************************************************************
671673
unaligned_type_ext& operator =(T value)
672674
{
673-
this->copy_value_to_store(value, this->storage);
675+
unaligned_copy::copy_value_to_store(value, this->storage);
674676

675677
return *this;
676678
}
@@ -680,7 +682,7 @@ namespace etl
680682
//*************************************************************************
681683
unaligned_type_ext& operator =(const unaligned_type_ext<T, Endian>& other)
682684
{
683-
this->copy_store_to_store(other.data(), Endian, this->storage);
685+
unaligned_copy::copy_store_to_store(other.data(), Endian, this->storage);
684686

685687
return *this;
686688
}
@@ -691,7 +693,7 @@ namespace etl
691693
template <int Endian_Other>
692694
unaligned_type_ext& operator =(const unaligned_type_ext<T, Endian_Other>& other)
693695
{
694-
this->copy_store_to_store(other.data(), Endian_Other, this->storage);
696+
unaligned_copy::copy_store_to_store(other.data(), Endian_Other, this->storage);
695697

696698
return *this;
697699
}
@@ -735,7 +737,7 @@ namespace etl
735737
{
736738
T value = T();
737739

738-
this->copy_store_to_value(this->storage, value);
740+
unaligned_copy::copy_store_to_value(this->storage, value);
739741

740742
return value;
741743
}
@@ -747,7 +749,7 @@ namespace etl
747749
{
748750
T value = T();
749751

750-
this->copy_store_to_value(this->storage, value);
752+
unaligned_copy::copy_store_to_value(this->storage, value);
751753

752754
return value;
753755
}

0 commit comments

Comments
 (0)