Add take() to etl::span (#1083)

This commit is contained in:
Roland Reichwein 2025-05-06 09:52:51 +02:00 committed by GitHub
parent 0b280bf5f0
commit ba487bcb04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 168 additions and 0 deletions

View File

@ -932,6 +932,43 @@ namespace etl
(pend - pbegin) * sizeof(element_type) / sizeof(TNew));
}
//*************************************************************************
/// Split off and return an initial span of specified type of this span.
/// The original span is advanced by the size of the returned span.
/// \tparam TRet Returned span type
/// \param n Number of elements in returned span
//*************************************************************************
template<typename TRet>
ETL_NODISCARD etl::span<TRet> take(size_t const n)
{
ETL_STATIC_ASSERT(sizeof(TRet) % sizeof(element_type) == 0, "sizeof(TRet) must be divisible by sizeof(T)");
ETL_ASSERT(etl::is_aligned<etl::alignment_of<TRet>::value>(pbegin), ETL_ERROR(span_alignment_exception));
ETL_ASSERT(sizeof(TRet) * n <= sizeof(element_type) * size(), ETL_ERROR(span_size_mismatch));
etl::span<TRet> result = reinterpret_as<TRet>().first(n);
advance(sizeof(TRet) / sizeof(element_type) * n);
return result;
}
//*************************************************************************
/// Split off and return an initial value of specified type of this span.
/// The original span is advanced by the size of TRet
/// \tparam TRet Returned span type
//*************************************************************************
template<typename TRet>
ETL_NODISCARD TRet& take()
{
ETL_STATIC_ASSERT(sizeof(TRet) % sizeof(element_type) == 0, "sizeof(TRet) must be divisible by sizeof(T)");
ETL_ASSERT(etl::is_aligned<etl::alignment_of<TRet>::value>(pbegin), ETL_ERROR(span_alignment_exception));
ETL_ASSERT(sizeof(TRet) <= sizeof(element_type) * size(), ETL_ERROR(span_size_mismatch));
TRet& result = *reinterpret_cast<TRet*>(data());
advance(sizeof(TRet) / sizeof(element_type));
return result;
}
private:
pointer pbegin;

View File

@ -1370,6 +1370,137 @@ namespace
CHECK_EQUAL(etl::copy(data0, data1), true);
}
//*************************************************************************
TEST(test_take_span_size_error)
{
uint8_t src[] = { 0x01, 0x02, 0x03 };
etl::span<uint8_t> data0 = src;
CHECK_THROW({etl::span<etl::be_uint32_t> data1 = data0.take<etl::be_uint32_t>(1); (void) data1;}, etl::span_size_mismatch);
}
//*************************************************************************
TEST(test_take_span)
{
uint8_t src[] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
etl::span<uint8_t> data0 = src;
etl::span<uint8_t> data1 = data0.take<uint8_t>(1);
CHECK_EQUAL(data0.size(), 4);
CHECK_EQUAL(data1.size(), 1);
CHECK_EQUAL(data1[0], 0x01);
etl::span<etl::be_uint32_t> data2 = data0.take<etl::be_uint32_t>(1);
CHECK_EQUAL(data0.size(), 0);
CHECK_EQUAL(data2.size(), 1);
CHECK_EQUAL(data2[0], 0x02030405);
data1 = data0.take<uint8_t>(0);
CHECK_EQUAL(data0.size(), 0);
CHECK_EQUAL(data1.size(), 0);
CHECK_THROW({etl::span<uint8_t> data3 = data0.take<uint8_t>(1); (void) data3;}, etl::span_size_mismatch);
}
//*************************************************************************
TEST(test_take_span_2)
{
uint8_t src[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
etl::span<uint8_t> data0 = src;
etl::span<etl::be_uint32_t> data1 = data0.take<etl::be_uint32_t>(2);
CHECK_EQUAL(data0.size(), 2);
CHECK_EQUAL(data1.size(), 2);
CHECK_EQUAL(data1[0], 0x01020304);
CHECK_EQUAL(data1[1], 0x05060708);
etl::span<uint8_t> data2 = data0.take<uint8_t>(1);
CHECK_EQUAL(data0.size(), 1);
CHECK_EQUAL(data2.size(), 1);
CHECK_EQUAL(data2[0], 0x09);
}
//*************************************************************************
TEST(test_take_span_const)
{
const uint8_t src[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
etl::span<const uint8_t> data0 = src;
etl::span<const etl::be_uint32_t> data1 = data0.take<const etl::be_uint32_t>(2);
CHECK_EQUAL(data0.size(), 2);
CHECK_EQUAL(data1.size(), 2);
CHECK_EQUAL(data1[0], 0x01020304);
CHECK_EQUAL(data1[1], 0x05060708);
etl::span<const uint8_t> data2 = data0.take<const uint8_t>(1);
CHECK_EQUAL(data0.size(), 1);
CHECK_EQUAL(data2.size(), 1);
CHECK_EQUAL(data2[0], 0x09);
data2 = data0.take<const uint8_t>(0);
CHECK_EQUAL(data0.size(), 1);
CHECK_EQUAL(data2.size(), 0);
}
//*************************************************************************
TEST(test_take_value)
{
uint8_t src[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
etl::span<uint8_t> data0 = src;
uint8_t& data1 = data0.take<uint8_t>();
CHECK_EQUAL(data0.size(), 9);
CHECK_EQUAL(data1, 0x01);
etl::be_uint32_t& data2 = data0.take<etl::be_uint32_t>();
CHECK_EQUAL(data0.size(), 5);
CHECK_EQUAL(data2, 0x02030405);
etl::be_uint32_t& data3 = data0.take<etl::be_uint32_t>();
CHECK_EQUAL(data0.size(), 1);
CHECK_EQUAL(data3, 0x06070809);
uint8_t& data4 = data0.take<uint8_t>();
CHECK_EQUAL(data0.size(), 0);
CHECK_EQUAL(data4, 0x0a);
CHECK_THROW({uint8_t& data5 = data0.take<uint8_t>(); (void) data5;}, etl::span_size_mismatch);
}
//*************************************************************************
TEST(test_take_value_const)
{
const uint8_t src[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
etl::span<const uint8_t> data0 = src;
const uint8_t& data1 = data0.take<const uint8_t>();
CHECK_EQUAL(data0.size(), 9);
CHECK_EQUAL(data1, 0x01);
const etl::be_uint32_t& data2 = data0.take<const etl::be_uint32_t>();
CHECK_EQUAL(data0.size(), 5);
CHECK_EQUAL(data2, 0x02030405);
const etl::be_uint32_t& data3 = data0.take<const etl::be_uint32_t>();
CHECK_EQUAL(data0.size(), 1);
CHECK_EQUAL(data3, 0x06070809);
const uint8_t& data4 = data0.take<const uint8_t>();
CHECK_EQUAL(data0.size(), 0);
CHECK_EQUAL(data4, 0x0a);
CHECK_THROW({const uint8_t& data5 = data0.take<const uint8_t>(); (void) data5;}, etl::span_size_mismatch);
}
#include "etl/private/diagnostic_pop.h"
};
}