Skip to content

Commit

Permalink
Add a _CharSpan string literal operator
Browse files Browse the repository at this point in the history
This allows constexpr CharSpans to be created.
  • Loading branch information
ksperling-apple committed Oct 27, 2023
1 parent 02e7647 commit cdf5cf1
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 1 deletion.
36 changes: 36 additions & 0 deletions src/lib/core/Unchecked.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
*
* Copyright (c) 2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @file
* This file defines the chip::Optional class to handle values which may
* or may not be present.
*
*/
#pragma once

namespace chip {

/// Unchecked is disambiguation tag that can be used to provide and select a variant of a
/// constructor or other method that omits the runtime checks performed by the default variant.
struct UncheckedType
{
explicit UncheckedType() = default;
};
inline constexpr UncheckedType Unchecked{};

} // namespace chip
16 changes: 15 additions & 1 deletion src/lib/support/Span.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <string.h>
#include <type_traits>

#include <lib/core/Unchecked.h>
#include <lib/support/CodeUtils.h>

namespace chip {
Expand Down Expand Up @@ -149,7 +150,10 @@ class Span
return Span(reinterpret_cast<T *>(&bytes[1]), length);
}

// Allow creating CharSpans from a character string.
// Creates a CharSpans from a null-terminated C character string.
//
// Note that for string literals, the user-defined `_CharSpan` string
// literal operator should be used instead, e.g. `"Hello"_CharSpan`.
template <class U, typename = std::enable_if_t<std::is_same<T, const U>::value && std::is_same<const char, T>::value>>
static Span fromCharString(U * chars)
{
Expand All @@ -165,8 +169,18 @@ class Span
private:
pointer mDataBuf;
size_t mDataLen;

constexpr Span(UncheckedType tag, pointer databuf, size_t datalen) : mDataBuf(databuf), mDataLen(datalen) {}

friend constexpr Span<char const> operator"" _CharSpan(char const *, size_t);
};

// Creates a CharSpan from a string literal.
constexpr Span<char const> operator"" _CharSpan(char const * literal, size_t size)
{
return Span<char const>(Unchecked, literal, size);
}

namespace detail {

// To make FixedSpan (specifically various FixedByteSpan types) default constructible
Expand Down
9 changes: 9 additions & 0 deletions src/lib/support/tests/TestSpan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,14 @@ static void TestFromCharString(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT(inSuite, s1.data_equal(CharSpan(str, 3)));
}

static void TestLiteral(nlTestSuite * inSuite, void * inContext)
{
constexpr CharSpan literal = "HI!"_CharSpan;
NL_TEST_ASSERT(inSuite, literal.size() == 3);
NL_TEST_ASSERT(inSuite, literal.data_equal(CharSpan::fromCharString("HI!")));
NL_TEST_ASSERT(inSuite, ""_CharSpan.size() == 0);
}

static void TestConversionConstructors(nlTestSuite * inSuite, void * inContext)
{
struct Foo
Expand Down Expand Up @@ -330,6 +338,7 @@ static const nlTest sTests[] = {
NL_TEST_DEF_FN(TestSubSpan),
NL_TEST_DEF_FN(TestFromZclString),
NL_TEST_DEF_FN(TestFromCharString),
NL_TEST_DEF_FN(TestLiteral),
NL_TEST_DEF_FN(TestConversionConstructors),
NL_TEST_SENTINEL(),
};
Expand Down

0 comments on commit cdf5cf1

Please sign in to comment.