Skip to content

Commit

Permalink
Add element accessors on Span. (#26366)
Browse files Browse the repository at this point in the history
* Add element accessors on Span.

This matches std::span and avoids people having to write span.data()[index] and
whatnot.

* Remove the constexpr from element access, since it can't coexist with VerifyOrDie.
  • Loading branch information
bzbarsky-apple authored May 5, 2023
1 parent a59ffbd commit 9556cc3
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
30 changes: 28 additions & 2 deletions src/lib/support/Span.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ template <class T>
class Span
{
public:
using pointer = T *;
using pointer = T *;
using reference = T &;

constexpr Span() : mDataBuf(nullptr), mDataLen(0) {}
constexpr Span(pointer databuf, size_t datalen) : mDataBuf(databuf), mDataLen(datalen) {}
Expand Down Expand Up @@ -75,6 +76,18 @@ class Span
constexpr pointer begin() const { return data(); }
constexpr pointer end() const { return data() + size(); }

// Element accessors, matching the std::span API.
// VerifyOrDie cannot be used inside a constexpr function, because it uses
// "static" on some platforms (e.g. when CHIP_PW_TOKENIZER_LOGGING is true)
// and that's not allowed in constexpr functions.
reference operator[](size_t index) const
{
VerifyOrDie(index < size());
return data()[index];
}
reference front() const { return (*this)[0]; }
reference back() const { return (*this)[size() - 1]; }

template <class U, typename = std::enable_if_t<std::is_same<std::remove_const_t<T>, std::remove_const_t<U>>::value>>
bool data_equal(const Span<U> & other) const
{
Expand Down Expand Up @@ -142,7 +155,8 @@ template <class T, size_t N>
class FixedSpan
{
public:
using pointer = T *;
using pointer = T *;
using reference = T &;

constexpr FixedSpan() : mDataBuf(nullptr) {}

Expand Down Expand Up @@ -188,6 +202,18 @@ class FixedSpan
constexpr pointer begin() const { return mDataBuf; }
constexpr pointer end() const { return mDataBuf + N; }

// Element accessors, matching the std::span API.
// VerifyOrDie cannot be used inside a constexpr function, because it uses
// "static" on some platforms (e.g. when CHIP_PW_TOKENIZER_LOGGING is true)
// and that's not allowed in constexpr functions.
reference operator[](size_t index) const
{
VerifyOrDie(index < size());
return data()[index];
}
reference front() const { return (*this)[0]; }
reference back() const { return (*this)[size() - 1]; }

// Allow data_equal for spans that are over the same type up to const-ness.
template <class U, typename = std::enable_if_t<std::is_same<std::remove_const_t<T>, std::remove_const_t<U>>::value>>
bool data_equal(const FixedSpan<U, N> & other) const
Expand Down
10 changes: 10 additions & 0 deletions src/lib/support/tests/TestSpan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ static void TestByteSpan(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT(inSuite, s2.data_equal(s2));
NL_TEST_ASSERT(inSuite, !s2.data_equal(s1));
NL_TEST_ASSERT(inSuite, IsSpanUsable(s2) == true);
NL_TEST_ASSERT(inSuite, s2.front() == 1);
NL_TEST_ASSERT(inSuite, s2.back() == 3);
NL_TEST_ASSERT(inSuite, s2[0] == 1);
NL_TEST_ASSERT(inSuite, s2[1] == 2);
NL_TEST_ASSERT(inSuite, s2[2] == 3);

ByteSpan s3 = s2;
NL_TEST_ASSERT(inSuite, s3.data() == arr);
Expand Down Expand Up @@ -175,6 +180,11 @@ static void TestFixedByteSpan(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT(inSuite, s2.data()[2] == 3);
NL_TEST_ASSERT(inSuite, !s2.empty());
NL_TEST_ASSERT(inSuite, s2.data_equal(s2));
NL_TEST_ASSERT(inSuite, s2.front() == 1);
NL_TEST_ASSERT(inSuite, s2.back() == 3);
NL_TEST_ASSERT(inSuite, s2[0] == 1);
NL_TEST_ASSERT(inSuite, s2[1] == 2);
NL_TEST_ASSERT(inSuite, s2[2] == 3);

FixedByteSpan<3> s3 = s2;
NL_TEST_ASSERT(inSuite, s3.data() == arr);
Expand Down

0 comments on commit 9556cc3

Please sign in to comment.