encoding+lp+net: simplify with `if constexpr`
Change-Id: Ie2b45a502c59e5cb7181628e691f7aaaf7509d84
diff --git a/ndn-cxx/encoding/block-helpers.hpp b/ndn-cxx/encoding/block-helpers.hpp
index 653280d..9472061 100644
--- a/ndn-cxx/encoding/block-helpers.hpp
+++ b/ndn-cxx/encoding/block-helpers.hpp
@@ -181,73 +181,64 @@
* @brief Create a binary block copying from RandomAccessIterator.
*/
template<class Iterator>
-class BinaryBlockFast
+Block
+makeBinaryBlockFast(uint32_t type, Iterator first, Iterator last)
{
-public:
BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<Iterator>));
- static Block
- makeBlock(uint32_t type, Iterator first, Iterator last)
- {
- EncodingEstimator estimator;
- size_t valueLength = last - first;
- size_t totalLength = valueLength;
- totalLength += estimator.prependVarNumber(valueLength);
- totalLength += estimator.prependVarNumber(type);
+ EncodingEstimator estimator;
+ size_t valueLength = last - first;
+ size_t totalLength = valueLength;
+ totalLength += estimator.prependVarNumber(valueLength);
+ totalLength += estimator.prependVarNumber(type);
- EncodingBuffer encoder(totalLength, 0);
- encoder.prependRange(first, last);
- encoder.prependVarNumber(valueLength);
- encoder.prependVarNumber(type);
+ EncodingBuffer encoder(totalLength, 0);
+ encoder.prependRange(first, last);
+ encoder.prependVarNumber(valueLength);
+ encoder.prependVarNumber(type);
- return encoder.block();
- }
-};
+ return encoder.block();
+}
/**
* @brief Create a binary block copying from generic InputIterator.
*/
template<class Iterator>
-class BinaryBlockSlow
+Block
+makeBinaryBlockSlow(uint32_t type, Iterator first, Iterator last)
{
-public:
BOOST_CONCEPT_ASSERT((boost::InputIterator<Iterator>));
- static Block
- makeBlock(uint32_t type, Iterator first, Iterator last)
- {
- // reserve 4 bytes in front (common for 1(type)-3(length) encoding
- // Actual size will be adjusted as necessary by the encoder
- EncodingBuffer encoder(4, 4);
- size_t valueLength = encoder.appendRange(first, last);
- encoder.prependVarNumber(valueLength);
- encoder.prependVarNumber(type);
+ // Reserve 4 bytes in front, common for 1(type)-3(length) encoding.
+ // Actual size will be adjusted as necessary by the encoder.
+ EncodingBuffer encoder(4, 4);
+ size_t valueLength = encoder.appendRange(first, last);
+ encoder.prependVarNumber(valueLength);
+ encoder.prependVarNumber(type);
- return encoder.block();
- }
-};
+ return encoder.block();
+}
} // namespace detail
-/** @brief Create a TLV block copying TLV-VALUE from iterators.
- * @tparam Iterator an InputIterator dereferenceable to a 1-octet type; a faster implementation is
- * automatically selected for RandomAccessIterator
- * @param type TLV-TYPE number
- * @param first begin iterator
- * @param last past-the-end iterator
- * @sa prependBinaryBlock
+/**
+ * @brief Create a TLV block copying TLV-VALUE from iterators.
+ * @tparam Iterator an InputIterator dereferenceable to a 1-octet type; a faster implementation is
+ * automatically selected for RandomAccessIterator
+ * @param type TLV-TYPE number
+ * @param first begin iterator
+ * @param last past-the-end iterator
+ * @sa prependBinaryBlock
*/
template<class Iterator>
Block
makeBinaryBlock(uint32_t type, Iterator first, Iterator last)
{
- using BinaryBlockHelper = std::conditional_t<
- std::is_base_of_v<std::random_access_iterator_tag,
- typename std::iterator_traits<Iterator>::iterator_category>,
- detail::BinaryBlockFast<Iterator>,
- detail::BinaryBlockSlow<Iterator>>;
-
- return BinaryBlockHelper::makeBlock(type, first, last);
+ if constexpr (std::is_base_of_v<std::random_access_iterator_tag,
+ typename std::iterator_traits<Iterator>::iterator_category>)
+ return detail::makeBinaryBlockFast(type, first, last);
+ else
+ return detail::makeBinaryBlockSlow(type, first, last);
}
/**
diff --git a/ndn-cxx/encoding/tlv.hpp b/ndn-cxx/encoding/tlv.hpp
index 6480538..12bc854 100644
--- a/ndn-cxx/encoding/tlv.hpp
+++ b/ndn-cxx/encoding/tlv.hpp
@@ -177,7 +177,7 @@
* @return true if number was successfully read from input, false otherwise
*/
template<typename Iterator>
-[[nodiscard]] bool
+[[nodiscard]] constexpr bool
readVarNumber(Iterator& begin, Iterator end, uint64_t& number) noexcept;
/**
@@ -194,7 +194,7 @@
* the TLV-TYPE is zero or larger than 2^32-1 (maximum allowed by the packet format).
*/
template<typename Iterator>
-[[nodiscard]] bool
+[[nodiscard]] constexpr bool
readType(Iterator& begin, Iterator end, uint32_t& type) noexcept;
/**
@@ -208,7 +208,7 @@
* @throw tlv::Error VAR-NUMBER cannot be read
*/
template<typename Iterator>
-uint64_t
+constexpr uint64_t
readVarNumber(Iterator& begin, Iterator end);
/**
@@ -224,13 +224,13 @@
* the TLV-TYPE is zero or larger than 2^32-1 (maximum allowed by the packet format).
*/
template<typename Iterator>
-uint32_t
+constexpr uint32_t
readType(Iterator& begin, Iterator end);
/**
* @brief Get the number of bytes necessary to hold the value of @p number encoded as VAR-NUMBER.
*/
-constexpr size_t
+[[nodiscard]] constexpr size_t
sizeOfVarNumber(uint64_t number) noexcept;
/**
@@ -254,13 +254,13 @@
* If \p size differs from `std::distance(begin, end)`, tlv::Error exception will be thrown.
*/
template<typename Iterator>
-uint64_t
+constexpr uint64_t
readNonNegativeInteger(size_t size, Iterator& begin, Iterator end);
/**
* @brief Get the number of bytes necessary to hold the value of @p integer encoded as NonNegativeInteger.
*/
-constexpr size_t
+[[nodiscard]] constexpr size_t
sizeOfNonNegativeInteger(uint64_t integer) noexcept;
/**
@@ -271,48 +271,35 @@
writeNonNegativeInteger(std::ostream& os, uint64_t integer);
/////////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////////
-
// Inline definitions
-
-/////////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
namespace detail {
-/** @brief Function object to read a number from InputIterator.
+/**
+ * @brief Determine whether to select the readNumber() implementation for ContiguousIterator.
+ *
+ * This is not a full ContiguousIterator detection implementation. It returns true for
+ * the most common ContiguousIterator types used with TLV decoding function templates.
*/
-template<typename Iterator>
-class ReadNumberSlow
-{
-public:
- constexpr bool
- operator()(size_t size, Iterator& begin, Iterator end, uint64_t& number) const noexcept
- {
- number = 0;
- size_t count = 0;
- for (; begin != end && count < size; ++begin, ++count) {
- number = (number << 8) | *begin;
- }
- return count == size;
- }
-};
+template<typename Iterator,
+ typename DecayedIterator = std::decay_t<Iterator>,
+ typename ValueType = typename std::iterator_traits<DecayedIterator>::value_type>
+inline constexpr bool IsContiguousIterator =
+ (std::is_convertible_v<DecayedIterator, const ValueType*> ||
+ std::is_convertible_v<DecayedIterator, typename std::basic_string<ValueType>::const_iterator> ||
+ std::is_convertible_v<DecayedIterator, typename std::vector<ValueType>::const_iterator>) &&
+ sizeof(ValueType) == 1 && !std::is_same_v<ValueType, bool>;
-/** @brief Function object to read a number from ContiguousIterator.
- */
template<typename Iterator>
-class ReadNumberFast
+constexpr bool
+readNumber(size_t size, Iterator& begin, Iterator end, uint64_t& number) noexcept
{
-public:
- constexpr bool
- operator()(size_t size, Iterator& begin, Iterator end, uint64_t& number) const noexcept
- {
+ if constexpr (IsContiguousIterator<Iterator>) {
+ // fast path
if (begin + size > end) {
return false;
}
-
switch (size) {
case 1: {
number = *begin;
@@ -345,36 +332,21 @@
}
}
}
-};
-
-/** @brief Determine whether to select ReadNumber implementation for ContiguousIterator.
- *
- * This is not a full ContiguousIterator detection implementation. It returns true for the most
- * common ContiguousIterator types used with TLV decoding function templates.
- */
-template<typename Iterator,
- typename DecayedIterator = std::decay_t<Iterator>,
- typename ValueType = typename std::iterator_traits<DecayedIterator>::value_type>
-constexpr bool
-shouldSelectContiguousReadNumber()
-{
- return (std::is_convertible_v<DecayedIterator, const ValueType*> ||
- std::is_convertible_v<DecayedIterator, typename std::basic_string<ValueType>::const_iterator> ||
- std::is_convertible_v<DecayedIterator, typename std::vector<ValueType>::const_iterator>) &&
- sizeof(ValueType) == 1 &&
- !std::is_same_v<ValueType, bool>;
+ else {
+ // slow path
+ number = 0;
+ size_t count = 0;
+ for (; begin != end && count < size; ++begin, ++count) {
+ number = (number << 8) | *begin;
+ }
+ return count == size;
+ }
}
-template<typename Iterator>
-class ReadNumber : public std::conditional_t<shouldSelectContiguousReadNumber<Iterator>(),
- ReadNumberFast<Iterator>, ReadNumberSlow<Iterator>>
-{
-};
-
} // namespace detail
template<typename Iterator>
-bool
+constexpr bool
readVarNumber(Iterator& begin, Iterator end, uint64_t& number) noexcept
{
if (begin == end)
@@ -387,13 +359,13 @@
return true;
}
- size_t size = firstOctet == 253 ? 2 :
- firstOctet == 254 ? 4 : 8;
- return detail::ReadNumber<Iterator>()(size, begin, end, number);
+ size_t len = firstOctet == 253 ? 2 :
+ firstOctet == 254 ? 4 : 8;
+ return detail::readNumber(len, begin, end, number);
}
template<typename Iterator>
-bool
+constexpr bool
readType(Iterator& begin, Iterator end, uint32_t& type) noexcept
{
uint64_t number = 0;
@@ -407,24 +379,20 @@
}
template<typename Iterator>
-uint64_t
+constexpr uint64_t
readVarNumber(Iterator& begin, Iterator end)
{
- if (begin == end) {
- NDN_THROW(Error("Empty buffer during TLV parsing"));
- }
-
- uint64_t value = 0;
- bool isOk = readVarNumber(begin, end, value);
+ uint64_t number = 0;
+ bool isOk = readVarNumber(begin, end, number);
if (!isOk) {
NDN_THROW(Error("Insufficient data during TLV parsing"));
}
- return value;
+ return number;
}
template<typename Iterator>
-uint32_t
+constexpr uint32_t
readType(Iterator& begin, Iterator end)
{
uint64_t type = readVarNumber(begin, end);
@@ -471,15 +439,15 @@
}
template<typename Iterator>
-uint64_t
-readNonNegativeInteger(size_t size, Iterator& begin, Iterator end)
+constexpr uint64_t
+readNonNegativeInteger(size_t len, Iterator& begin, Iterator end)
{
- if (size != 1 && size != 2 && size != 4 && size != 8) {
- NDN_THROW(Error("Invalid length " + to_string(size) + " for NonNegativeInteger"));
+ if (len != 1 && len != 2 && len != 4 && len != 8) {
+ NDN_THROW(Error("Invalid NonNegativeInteger length " + to_string(len)));
}
uint64_t number = 0;
- bool isOk = detail::ReadNumber<Iterator>()(size, begin, end, number);
+ bool isOk = detail::readNumber(len, begin, end, number);
if (!isOk) {
NDN_THROW(Error("Insufficient data during NonNegativeInteger parsing"));
}
diff --git a/ndn-cxx/lp/field.hpp b/ndn-cxx/lp/field.hpp
index cae13f7..3ede2b5 100644
--- a/ndn-cxx/lp/field.hpp
+++ b/ndn-cxx/lp/field.hpp
@@ -34,33 +34,24 @@
*/
namespace field_location_tags {
-class Base
-{
-};
-
/**
* \brief A header field.
*/
-class Header : public Base
-{
-};
+struct Header {};
/**
* \brief The Fragment field.
*/
-class Fragment : public Base
-{
-};
+struct Fragment {};
} // namespace field_location_tags
/**
* \brief Concept check for NDNLPv2 fields.
*/
-template<class X>
+template<typename X>
struct Field
{
- static_assert(std::is_base_of_v<field_location_tags::Base, typename X::FieldLocation>, "");
static_assert(std::is_same_v<typename X::TlvType::value_type, uint32_t>, "");
static_assert(std::is_same_v<typename X::IsRepeatable::value_type, bool>, "");
static_assert(std::is_default_constructible_v<typename X::ValueType>, "");
diff --git a/ndn-cxx/lp/packet.cpp b/ndn-cxx/lp/packet.cpp
index 7097384..e942acc 100644
--- a/ndn-cxx/lp/packet.cpp
+++ b/ndn-cxx/lp/packet.cpp
@@ -30,44 +30,33 @@
namespace {
-template<typename TAG>
-int
-getLocationSortOrder() noexcept;
-
-template<>
-constexpr int
-getLocationSortOrder<field_location_tags::Header>() noexcept
+template<typename Tag>
+constexpr int8_t
+getLocationSortOrder() noexcept
{
- return 1;
+ if constexpr (std::is_same_v<Tag, field_location_tags::Header>)
+ return 1;
+ if constexpr (std::is_same_v<Tag, field_location_tags::Fragment>)
+ return 2;
}
-template<>
-constexpr int
-getLocationSortOrder<field_location_tags::Fragment>() noexcept
+struct FieldInfo
{
- return 2;
-}
-
-class FieldInfo
-{
-public:
constexpr
FieldInfo() noexcept = default;
explicit
FieldInfo(uint32_t type) noexcept;
-public:
uint32_t tlvType = 0; ///< TLV-TYPE of the field; 0 if field does not exist
bool isRecognized = false; ///< is this field known
bool canIgnore = false; ///< can this unknown field be ignored
bool isRepeatable = false; ///< is the field repeatable
- int locationSortOrder = getLocationSortOrder<field_location_tags::Header>(); ///< sort order of field_location_tag
+ int8_t locationSortOrder = getLocationSortOrder<field_location_tags::Header>(); ///< sort order of field_location_tag
};
-class ExtractFieldInfo
+struct ExtractFieldInfo
{
-public:
using result_type = void;
template<typename T>
@@ -115,7 +104,7 @@
Packet::wireEncode() const
{
// If no header or trailer, return bare network packet
- Block::element_container elements = m_wire.elements();
+ auto elements = m_wire.elements();
if (elements.size() == 1 && elements.front().type() == FragmentField::TlvType::value) {
elements.front().parse();
return elements.front().elements().front();
@@ -169,9 +158,7 @@
bool
Packet::comparePos(uint32_t first, const Block& second) noexcept
{
- FieldInfo firstInfo(first);
- FieldInfo secondInfo(second.type());
- return compareFieldSortOrder(firstInfo, secondInfo);
+ return compareFieldSortOrder(FieldInfo(first), FieldInfo(second.type()));
}
} // namespace lp
diff --git a/ndn-cxx/net/impl/netlink-message.hpp b/ndn-cxx/net/impl/netlink-message.hpp
index 01d5282..5eb44b8 100644
--- a/ndn-cxx/net/impl/netlink-message.hpp
+++ b/ndn-cxx/net/impl/netlink-message.hpp
@@ -47,92 +47,52 @@
template<typename T>
constexpr size_t
-getAttributeLength(const T* attr);
-
-template<>
-constexpr size_t
-getAttributeLength(const nlattr* attr)
+getAttributeLength(const T* attr)
{
- return attr->nla_len;
-}
-
-template<>
-constexpr size_t
-getAttributeLength(const rtattr* attr)
-{
- return attr->rta_len;
+ if constexpr (std::is_same_v<T, nlattr>)
+ return attr->nla_len;
+ if constexpr (std::is_same_v<T, rtattr>)
+ return attr->rta_len;
}
template<typename T>
constexpr size_t
-getAttributeLengthAligned(const T* attr);
-
-template<>
-constexpr size_t
-getAttributeLengthAligned(const nlattr* attr)
+getAttributeLengthAligned(const T* attr)
{
- return NLA_ALIGN(attr->nla_len);
-}
-
-template<>
-constexpr size_t
-getAttributeLengthAligned(const rtattr* attr)
-{
- return RTA_ALIGN(attr->rta_len);
+ if constexpr (std::is_same_v<T, nlattr>)
+ return NLA_ALIGN(attr->nla_len);
+ if constexpr (std::is_same_v<T, rtattr>)
+ return RTA_ALIGN(attr->rta_len);
}
template<typename T>
-constexpr uint16_t
-getAttributeType(const T* attr);
-
-template<>
-constexpr uint16_t
-getAttributeType(const nlattr* attr)
+uint16_t
+getAttributeType(const T* attr)
{
- return attr->nla_type & NLA_TYPE_MASK;
-}
-
-template<>
-constexpr uint16_t
-getAttributeType(const rtattr* attr)
-{
- return attr->rta_type;
+ if constexpr (std::is_same_v<T, nlattr>)
+ return attr->nla_type & NLA_TYPE_MASK;
+ if constexpr (std::is_same_v<T, rtattr>)
+ return attr->rta_type;
}
template<typename T>
const uint8_t*
-getAttributeValue(const T* attr);
-
-template<>
-inline const uint8_t*
-getAttributeValue(const nlattr* attr)
+getAttributeValue(const T* attr)
{
- return reinterpret_cast<const uint8_t*>(attr) + NLA_HDRLEN;
-}
-
-template<>
-inline const uint8_t*
-getAttributeValue(const rtattr* attr)
-{
- return reinterpret_cast<const uint8_t*>(RTA_DATA(const_cast<rtattr*>(attr)));
+ if constexpr (std::is_same_v<T, nlattr>)
+ return reinterpret_cast<const uint8_t*>(attr) + NLA_HDRLEN;
+ if constexpr (std::is_same_v<T, rtattr>)
+ return reinterpret_cast<const uint8_t*>(RTA_DATA(const_cast<rtattr*>(attr)));
}
template<typename T>
constexpr size_t
-getAttributeValueLength(const T* attr);
-
-template<>
-constexpr size_t
-getAttributeValueLength(const nlattr* attr)
+getAttributeValueLength(const T* attr)
{
- return attr->nla_len - NLA_HDRLEN;
-}
-
-template<>
-constexpr size_t
-getAttributeValueLength(const rtattr* attr)
-{
- return RTA_PAYLOAD(attr);
+ if constexpr (std::is_same_v<T, nlattr>)
+ return attr->nla_len - NLA_HDRLEN;
+ if constexpr (std::is_same_v<T, rtattr>)
+ return RTA_PAYLOAD(attr);
}
template<typename T>
diff --git a/tests/benchmarks/encoding-bench.cpp b/tests/benchmarks/encoding-bench.cpp
index 3ab246d..1adb452 100644
--- a/tests/benchmarks/encoding-bench.cpp
+++ b/tests/benchmarks/encoding-bench.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2023 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -42,34 +42,30 @@
template<>
struct ReadVarNumberTest<1>
{
- static const uint8_t WIRE[];
- static const uint64_t VALUE = 252;
+ static constexpr uint8_t WIRE[] = {0xfc};
+ static constexpr uint64_t VALUE = 252;
};
-const uint8_t ReadVarNumberTest<1>::WIRE[] = {0xfc};
template<>
struct ReadVarNumberTest<3>
{
- static const uint8_t WIRE[];
- static const uint64_t VALUE = 253;
+ static constexpr uint8_t WIRE[] = {0xfd, 0x00, 0xfd};
+ static constexpr uint64_t VALUE = 253;
};
-const uint8_t ReadVarNumberTest<3>::WIRE[] = {0xfd, 0x00, 0xfd};
template<>
struct ReadVarNumberTest<5>
{
- static const uint8_t WIRE[];
- static const uint64_t VALUE = 65536;
+ static constexpr uint8_t WIRE[] = {0xfe, 0x00, 0x01, 0x00, 0x00};
+ static constexpr uint64_t VALUE = 65536;
};
-const uint8_t ReadVarNumberTest<5>::WIRE[] = {0xfe, 0x00, 0x01, 0x00, 0x00};
template<>
struct ReadVarNumberTest<9>
{
- static const uint8_t WIRE[];
- static const uint64_t VALUE = 4294967296;
+ static constexpr uint8_t WIRE[] = {0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00};
+ static constexpr uint64_t VALUE = 4294967296;
};
-const uint8_t ReadVarNumberTest<9>::WIRE[] = {0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00};
template<size_t WIRE_SIZE, size_t ALIGNMENT_OFFSET>
struct ReadVarNumberAlignTest : public ReadVarNumberTest<WIRE_SIZE>
@@ -102,7 +98,7 @@
// It is recommended to run the benchmark multiple times and take the average.
BOOST_AUTO_TEST_CASE_TEMPLATE(ReadVarNumber, Test, ReadVarNumberTests)
{
- const int N_ITERATIONS = 100000000;
+ constexpr int N_ITERATIONS = 100000000;
alignas(8) uint8_t buffer[16];
static_assert(Test::AlignmentOffset::value + sizeof(Test::WIRE) <= sizeof(buffer), "");
diff --git a/tests/unit/encoding/block.t.cpp b/tests/unit/encoding/block.t.cpp
index f75eaf0..8dd21d3 100644
--- a/tests/unit/encoding/block.t.cpp
+++ b/tests/unit/encoding/block.t.cpp
@@ -169,7 +169,7 @@
BOOST_CHECK_EQUAL(b3.isValid(), false);
BOOST_CHECK_EQUAL(b3.type(), tlv::Invalid);
BOOST_CHECK_EXCEPTION(b3.size(), Block::Error, [] (const auto& e) {
- return e.what() == "Cannot determine size of invalid block"s;
+ return e.what() == "Cannot determine size of invalid block"sv;
});
BOOST_CHECK_EQUAL(b3.hasValue(), false);
BOOST_CHECK_EQUAL(b3.value_size(), 0);
@@ -253,7 +253,7 @@
BOOST_CHECK(stream.eof());
BOOST_CHECK_EXCEPTION(Block::fromStream(stream), tlv::Error, [] (const auto& e) {
- return e.what() == "Empty buffer during TLV parsing"s;
+ return e.what() == "Insufficient data during TLV parsing"sv;
});
}
@@ -315,7 +315,7 @@
BOOST_CHECK(b3.value() == nullptr);
BOOST_CHECK_EXCEPTION(Block::fromStream(stream), tlv::Error, [] (const auto& e) {
- return e.what() == "Empty buffer during TLV parsing"s;
+ return e.what() == "Insufficient data during TLV parsing"sv;
});
}
@@ -331,7 +331,7 @@
stream.seekg(0);
BOOST_CHECK_EXCEPTION(Block::fromStream(stream), tlv::Error, [] (const auto& e) {
- return e.what() == "TLV-LENGTH from stream exceeds limit"s;
+ return e.what() == "TLV-LENGTH from stream exceeds limit"sv;
});
}
@@ -447,12 +447,12 @@
{
Block b1(301);
BOOST_CHECK_EXCEPTION(b1.blockFromValue(), Block::Error, [] (const auto& e) {
- return e.what() == "Cannot construct block from empty TLV-VALUE"s;
+ return e.what() == "Cannot construct block from empty TLV-VALUE"sv;
});
Block b2(302, std::make_shared<Buffer>());
BOOST_CHECK_EXCEPTION(b2.blockFromValue(), Block::Error, [] (const auto& e) {
- return e.what() == "Cannot construct block from empty TLV-VALUE"s;
+ return e.what() == "Cannot construct block from empty TLV-VALUE"sv;
});
b1.encode();
@@ -491,7 +491,7 @@
BOOST_CHECK(data.get(0x15) == data.elements().at(2));
BOOST_CHECK_EXCEPTION(data.get(0x01), Block::Error, [] (const auto& e) {
- return e.what() == "No sub-element of type 1 found in block of type 6"s;
+ return e.what() == "No sub-element of type 1 found in block of type 6"sv;
});
BOOST_CHECK(data.find(0x15) == data.elements_begin() + 2);
@@ -503,7 +503,7 @@
};
Block bad(MALFORMED);
BOOST_CHECK_EXCEPTION(bad.parse(), Block::Error, [] (const auto& e) {
- return e.what() == "TLV-LENGTH of sub-element of type 7 exceeds TLV-VALUE boundary of parent block"s;
+ return e.what() == "TLV-LENGTH of sub-element of type 7 exceeds TLV-VALUE boundary of parent block"sv;
});
}
diff --git a/tests/unit/encoding/tlv.t.cpp b/tests/unit/encoding/tlv.t.cpp
index 5eaa17a..9cd7cc4 100644
--- a/tests/unit/encoding/tlv.t.cpp
+++ b/tests/unit/encoding/tlv.t.cpp
@@ -59,11 +59,9 @@
using StreamIterator = std::istream_iterator<uint8_t>;
#define ASSERT_READ_NUMBER_IS_FAST(T) \
- static_assert(std::is_base_of_v<detail::ReadNumberFast<T>, detail::ReadNumber<T>>, \
- # T " should use ReadNumberFast")
+ static_assert(detail::IsContiguousIterator<T>, #T " is not fast")
#define ASSERT_READ_NUMBER_IS_SLOW(T) \
- static_assert(std::is_base_of_v<detail::ReadNumberSlow<T>, detail::ReadNumber<T>>, \
- # T " should use ReadNumberSlow")
+ static_assert(!detail::IsContiguousIterator<T>, #T " is not slow")
ASSERT_READ_NUMBER_IS_FAST(const uint8_t*);
ASSERT_READ_NUMBER_IS_FAST(uint8_t*);
@@ -80,6 +78,8 @@
ASSERT_READ_NUMBER_IS_FAST(Uint8Array::iterator);
using CharArray = std::array<char, 87>;
ASSERT_READ_NUMBER_IS_FAST(CharArray::iterator);
+ASSERT_READ_NUMBER_IS_FAST(span<const uint8_t>::iterator);
+ASSERT_READ_NUMBER_IS_FAST(span<uint8_t>::iterator);
ASSERT_READ_NUMBER_IS_FAST(std::string::const_iterator);
ASSERT_READ_NUMBER_IS_FAST(std::string::iterator);
ASSERT_READ_NUMBER_IS_FAST(Buffer::const_iterator);