Skip to content

Commit

Permalink
etl::span: Add advance(), copy(), reinterpret_as()
Browse files Browse the repository at this point in the history
  • Loading branch information
rolandreichweinbmw committed Dec 30, 2024
1 parent 99d7537 commit 75024d9
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 0 deletions.
53 changes: 53 additions & 0 deletions include/etl/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,16 @@ namespace etl
: etl::span<element_type, etl::dynamic_extent>(pbegin + offset, pbegin + offset + count);
}

//*************************************************************************
/// Reinterpret the span as a span with different element type.
//*************************************************************************
template<typename TNew>
ETL_NODISCARD ETL_CONSTEXPR etl::span<TNew, etl::dynamic_extent> reinterpret_as() const ETL_NOEXCEPT
{
return etl::span<TNew, etl::dynamic_extent>(reinterpret_cast<TNew*>(pbegin),
Extent * sizeof(element_type) / sizeof(TNew));
}

private:

pointer pbegin;
Expand Down Expand Up @@ -694,6 +704,25 @@ namespace etl
: etl::span<element_type, etl::dynamic_extent>(pbegin + offset, pbegin + offset + count);
}

//*************************************************************************
/// Moves the pointer to the first element of the span further by a specified number of elements.
///\tparam elements Number of elements to move forward
//*************************************************************************
void advance(size_t elements) ETL_NOEXCEPT
{
pbegin += elements;
}

//*************************************************************************
/// Reinterpret the span as a span with different element type.
//*************************************************************************
template<typename TNew>
ETL_NODISCARD ETL_CONSTEXPR etl::span<TNew, etl::dynamic_extent> reinterpret_as() const ETL_NOEXCEPT
{
return etl::span<TNew, etl::dynamic_extent>(reinterpret_cast<TNew*>(pbegin),
(pend - pbegin) * sizeof(element_type) / sizeof(TNew));
}

private:

pointer pbegin;
Expand Down Expand Up @@ -746,6 +775,30 @@ namespace etl
etl::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}

//*************************************************************************
/// Copy complete element data from one span to another. If the destination
/// span is bigger than the source span, only the initial part of
/// destination span is overwritten.
///\param src Source
///\param dst Destination
///\return true, iff copy was successful. Reasons for unsuccessful operation:
/// 1. Source span is empty.
/// 2. They both point to the same data.
/// 3. The destination span is shorter than the source span.
//*************************************************************************
template <typename T1, size_t N1, typename T2, size_t N2>
typename etl::enable_if<etl::is_same<typename etl::remove_cv<T1>::type, typename etl::remove_cv<T2>::type>::value &&
!etl::is_const<T2>::value, bool>::type
copy(const etl::span<T1, N1>& src, const etl::span<T2, N2>& dst)
{
if (src.empty() || (src.begin() == dst.begin()) || src.size() > dst.size())
{
return false;
}
(void) etl::copy(src.begin(), src.end(), dst.begin());
return true;
}

//*************************************************************************
/// Template deduction guides.
//*************************************************************************
Expand Down
82 changes: 82 additions & 0 deletions test/test_span_dynamic_extent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,88 @@ namespace
}
}

//*************************************************************************
TEST(test_advance)
{
{
uint8_t data[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
etl::span<uint8_t> data0 = data;

CHECK_EQUAL(data0.size(), 5);
data0.advance(1);
CHECK_EQUAL(data0.size(), 4);
CHECK_EQUAL(data0[0], 0x02);
data0.advance(2);
CHECK_EQUAL(data0.size(), 2);
CHECK_EQUAL(data0[0], 0x04);
data0.advance(1);
CHECK_EQUAL(data0.size(), 1);
CHECK_EQUAL(data0[0], 0x05);
data0.advance(1);
CHECK_EQUAL(data0.size(), 0);
}
{
const uint8_t data[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
etl::span<const uint8_t> data0 = data;

CHECK_EQUAL(data0.size(), 5);
data0.advance(1);
CHECK_EQUAL(data0.size(), 4);
CHECK_EQUAL(data0[0], 0x02);
data0.advance(2);
CHECK_EQUAL(data0.size(), 2);
CHECK_EQUAL(data0[0], 0x04);
data0.advance(1);
CHECK_EQUAL(data0.size(), 1);
CHECK_EQUAL(data0[0], 0x05);
data0.advance(1);
CHECK_EQUAL(data0.size(), 0);
}
}

//*************************************************************************
TEST(test_reinterpret_as)
{
uint8_t data[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
etl::span<uint8_t> data0 = data;

etl::span<uint16_t> data1 = data0.reinterpret_as<uint16_t>();

CHECK_EQUAL(data1.size(), 2);
CHECK(data1[0] > 0x100);
CHECK(data1[1] > 0x300);
}

//*************************************************************************
TEST(test_copy)
{
uint8_t src[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
uint8_t dst[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
etl::span<uint8_t> data0 = src;
etl::span<uint8_t> data1 = dst;

CHECK_EQUAL(etl::copy(data0, data1), true);
CHECK(std::equal(data0.begin(), data0.end(), data1.begin()));

data1 = data1.subspan(1);

CHECK_EQUAL(etl::copy(data0, data1), true);
CHECK(std::equal(data0.begin(), data0.end(), data1.begin()));

data1 = data1.subspan(1);

CHECK_EQUAL(etl::copy(data0, data1), false);

data0 = data0.subspan(0, 0);

CHECK_EQUAL(etl::copy(data0, data1), false);

data0 = src;
data1 = src;

CHECK_EQUAL(etl::copy(data0, data1), false);
}

#include "etl/private/diagnostic_pop.h"
};
}
53 changes: 53 additions & 0 deletions test/test_span_fixed_extent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,59 @@ namespace
}
}

//*************************************************************************
TEST(test_reinterpret_as)
{
uint8_t data[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
etl::span<uint8_t, 5> data0 = data;

etl::span<uint16_t> data1 = data0.reinterpret_as<uint16_t>();

CHECK_EQUAL(data1.size(), 2);
CHECK(data1[0] > 0x100);
CHECK(data1[1] > 0x300);
}

//*************************************************************************
TEST(test_copy)
{
uint8_t src[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
uint8_t dst[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
{
etl::span<uint8_t, 5> data0 = src;
etl::span<uint8_t, 6> data1 = dst;

CHECK_EQUAL(etl::copy(data0, data1), true);
CHECK(std::equal(data0.begin(), data0.end(), data1.begin()));
}
{
etl::span<uint8_t, 5> data0 = src;
etl::span<uint8_t, 5> data1(&dst[1], 5);

CHECK_EQUAL(etl::copy(data0, data1), true);
CHECK(std::equal(data0.begin(), data0.end(), data1.begin()));
}

{
etl::span<uint8_t, 5> data0 = src;
etl::span<uint8_t, 4> data1(&dst[2], 4);

CHECK_EQUAL(etl::copy(data0, data1), false);
}
{
etl::span<uint8_t, 0> data0(&src[0], 0);
etl::span<uint8_t, 6> data1 = dst;

CHECK_EQUAL(etl::copy(data0, data1), false);
}
{
etl::span<uint8_t, 5> data0 = src;
etl::span<uint8_t, 5> data1 = src;

CHECK_EQUAL(etl::copy(data0, data1), false);
}
}

#include "etl/private/diagnostic_pop.h"
};
}

0 comments on commit 75024d9

Please sign in to comment.