aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWyatt Hepler <hepler@google.com>2024-03-01 00:02:52 +0000
committerXin Li <delphij@google.com>2024-05-08 22:18:53 -0700
commit0069dc840059ee077efa7b808807fc580596f40c (patch)
tree1ba9b93fda929860a1670e1d8941ba78ca479f8e
parent3a68395aa2e464420cc957f07249f1975014758e (diff)
downloadpigweed-tmp_amf_24Q2.tar.gz
pw_string: Support InlineBasicString<std::byte>; InlineByteString aliastmp_amf_24Q2
- std::char_traits does not provide a std::byte specialization, so use the custom constexpr char_traits implementaiton in its place. - Introduce pw::InlineByteString<> alias. - Remove any suggestion of C++14 support since this change requires C++17, and C++14 is no longer supported in Pigweed. Change-Id: I7ce03a557c45113c8e7a15fc56e858dea3333f60 Merged-In: I1d881839924eaa6467b5bf8b0346d5524f86e163
-rw-r--r--pw_minimal_cpp_stdlib/public/pw_minimal_cpp_stdlib/internal/string_view.h3
-rw-r--r--pw_string/BUILD.bazel5
-rw-r--r--pw_string/BUILD.gn5
-rw-r--r--pw_string/CMakeLists.txt1
-rw-r--r--pw_string/public/pw_string/internal/string_common_functions.inc26
-rw-r--r--pw_string/public/pw_string/internal/string_impl.h119
-rw-r--r--pw_string/public/pw_string/string.h36
-rw-r--r--pw_string/string_test.cc74
8 files changed, 124 insertions, 145 deletions
diff --git a/pw_minimal_cpp_stdlib/public/pw_minimal_cpp_stdlib/internal/string_view.h b/pw_minimal_cpp_stdlib/public/pw_minimal_cpp_stdlib/internal/string_view.h
index 5eafb8d38..99de81b71 100644
--- a/pw_minimal_cpp_stdlib/public/pw_minimal_cpp_stdlib/internal/string_view.h
+++ b/pw_minimal_cpp_stdlib/public/pw_minimal_cpp_stdlib/internal/string_view.h
@@ -24,6 +24,9 @@
_PW_POLYFILL_BEGIN_NAMESPACE_STD
template <typename T>
+class char_traits;
+
+template <typename T, typename = char_traits<T>>
class basic_string_view {
public:
using traits_type = void; // No traits object is used.
diff --git a/pw_string/BUILD.bazel b/pw_string/BUILD.bazel
index 7a9e5d68f..eda9a04f1 100644
--- a/pw_string/BUILD.bazel
+++ b/pw_string/BUILD.bazel
@@ -79,10 +79,7 @@ cc_library(
],
hdrs = ["public/pw_string/string.h"],
includes = ["public"],
- deps = [
- "//pw_assert",
- "//pw_polyfill",
- ],
+ deps = ["//pw_assert"],
)
cc_library(
diff --git a/pw_string/BUILD.gn b/pw_string/BUILD.gn
index fd10ba83f..6ae265dce 100644
--- a/pw_string/BUILD.gn
+++ b/pw_string/BUILD.gn
@@ -93,10 +93,7 @@ pw_source_set("string") {
"public/pw_string/internal/string_common_functions.inc",
"public/pw_string/internal/string_impl.h",
]
- public_deps = [
- dir_pw_assert,
- dir_pw_polyfill,
- ]
+ public_deps = [ dir_pw_assert ]
# TODO: b/259746255 - Remove this when everything compiles with -Wconversion.
configs = [ "$dir_pw_build:conversion_warnings" ]
diff --git a/pw_string/CMakeLists.txt b/pw_string/CMakeLists.txt
index 17b4c1ea3..1cf8f9b1e 100644
--- a/pw_string/CMakeLists.txt
+++ b/pw_string/CMakeLists.txt
@@ -71,7 +71,6 @@ pw_add_library(pw_string.string INTERFACE
public
PUBLIC_DEPS
pw_assert
- pw_polyfill
)
pw_add_library(pw_string.to_string STATIC
diff --git a/pw_string/public/pw_string/internal/string_common_functions.inc b/pw_string/public/pw_string/internal/string_common_functions.inc
index 38ad827a7..fd2071117 100644
--- a/pw_string/public/pw_string/internal/string_common_functions.inc
+++ b/pw_string/public/pw_string/internal/string_common_functions.inc
@@ -88,12 +88,10 @@ constexpr InlineBasicString& assign(std::initializer_list<T> list) {
return assign(list.begin(), list.size());
}
-#if PW_CXX_STANDARD_IS_SUPPORTED(17) // std::string_view is a C++17 feature
-
template <typename StringView,
typename = string_impl::EnableIfStringViewLike<T, StringView>>
constexpr InlineBasicString& assign(const StringView& string) {
- const std::basic_string_view<T> view = string;
+ const string_impl::View<T> view = string;
PW_ASSERT(view.size() < npos);
return assign(view.data(), view.size());
}
@@ -103,14 +101,12 @@ template <typename StringView,
constexpr InlineBasicString& assign(const StringView& string,
size_t index,
size_t count = npos) {
- const std::basic_string_view<T> view = string;
+ const string_impl::View<T> view = string;
PW_ASSERT(view.size() < npos);
return static_cast<InlineBasicString&>(
CopySubstr(data(), view.data(), view.size(), index, count));
}
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
-
constexpr InlineBasicString& assign(std::nullptr_t) = delete;
// Element access
@@ -137,8 +133,8 @@ constexpr const_reference back() const { return data()[size() - 1]; }
constexpr const_pointer c_str() const noexcept { return data(); }
-constexpr operator std::basic_string_view<T>() const noexcept {
- return std::basic_string_view<T>(data(), size());
+constexpr operator string_impl::View<T>() const noexcept {
+ return string_impl::View<T>(data(), size());
}
// Iterators
@@ -265,15 +261,13 @@ constexpr iterator insert(const U* pos, std::initializer_list<T> list) {
return insert(pos, list.begin(), list.end());
}
-#if PW_CXX_STANDARD_IS_SUPPORTED(17) // std::string_view is a C++17 feature
-
template <typename StringView,
typename = string_impl::EnableIfStringViewLike<T, StringView>>
constexpr InlineBasicString& insert(size_t index,
const StringView& string,
size_t string_index,
size_t count = npos) {
- const std::basic_string_view<T> view = string;
+ const string_impl::View<T> view = string;
PW_ASSERT(view.size() < npos);
PW_ASSERT(string_index <= view.size());
if (count == npos || count > view.size() - string_index) {
@@ -291,8 +285,6 @@ constexpr InlineBasicString& insert(size_t index, const StringView& string) {
return insert(index, string, 0);
}
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
-
constexpr InlineBasicString& erase(size_t index = 0, size_t count = npos) {
PW_ASSERT(index <= size());
size_t old_index =
@@ -391,12 +383,10 @@ constexpr InlineBasicString& append(std::initializer_list<T> list) {
return append(list.begin(), list.size());
}
-#if PW_CXX_STANDARD_IS_SUPPORTED(17) // std::string_view is a C++17 feature
-
template <typename StringView,
typename = string_impl::EnableIfStringViewLike<T, StringView>>
constexpr InlineBasicString& append(const StringView& string) {
- const std::basic_string_view<T> view = string;
+ const string_impl::View<T> view = string;
PW_ASSERT(view.size() < npos);
return append(view.data(), view.size());
}
@@ -406,14 +396,12 @@ template <typename StringView,
constexpr InlineBasicString& append(const StringView& string,
size_t index,
size_t count = npos) {
- const std::basic_string_view<T> view = string;
+ const string_impl::View<T> view = string;
PW_ASSERT(view.size() < npos);
return static_cast<InlineBasicString&>(
CopyExtendSubstr(data(), size(), view.data(), view.size(), index, count));
}
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
-
template <size_t kOtherCapacity>
constexpr int compare(
const InlineBasicString<T, kOtherCapacity>& other) const noexcept {
diff --git a/pw_string/public/pw_string/internal/string_impl.h b/pw_string/public/pw_string/internal/string_impl.h
index 9672d0c17..0ac44808c 100644
--- a/pw_string/public/pw_string/internal/string_impl.h
+++ b/pw_string/public/pw_string/internal/string_impl.h
@@ -15,63 +15,36 @@
#include <limits>
#include <string> // for std::char_traits
-#include <type_traits>
-
-#if PW_CXX_STANDARD_IS_SUPPORTED(17) // std::string_view is a C++17 feature
#include <string_view>
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
+#include <type_traits>
#include "pw_assert/assert.h"
#include "pw_polyfill/language_feature_macros.h"
-namespace pw {
-namespace string_impl {
+namespace pw::string_impl {
// pw::InlineString<>::size_type is unsigned short so the capacity and current
// size fit into a single word.
using size_type = unsigned short;
-template <typename CharType, typename T>
-using EnableIfNonArrayCharPointer = std::enable_if_t<
- std::is_pointer<T>::value && !std::is_array<T>::value &&
- std::is_same<CharType, std::remove_cv_t<std::remove_pointer_t<T>>>::value>;
-
-template <typename T>
-using EnableIfInputIterator = std::enable_if_t<
- std::is_convertible<typename std::iterator_traits<T>::iterator_category,
- std::input_iterator_tag>::value>;
-
-#if PW_CXX_STANDARD_IS_SUPPORTED(17) // std::string_view is a C++17 feature
-template <typename CharType, typename T>
-using EnableIfStringViewLike = std::enable_if_t<
- std::is_convertible<const T&, std::basic_string_view<CharType>>() &&
- !std::is_convertible<const T&, const CharType*>()>;
-
-template <typename CharType, typename T>
-using EnableIfStringViewLikeButNotStringView = std::enable_if_t<
- !std::is_same<T, std::basic_string_view<CharType>>() &&
- std::is_convertible<const T&, std::basic_string_view<CharType>>() &&
- !std::is_convertible<const T&, const CharType*>()>;
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
-
// Reserved capacity that is used to represent a generic-length
// pw::InlineString.
PW_INLINE_VARIABLE constexpr size_t kGeneric = size_type(-1);
-#if defined(__cpp_lib_constexpr_string) && __cpp_lib_constexpr_string >= 201907L
-
-// Like std::string and std::string_view, pw::InlineString uses std::char_traits
-// for low-level operations.
-using std::char_traits;
+template <typename T>
+inline constexpr bool kUseStdCharTraits =
+#if !defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L
+ false &&
+#endif // __cpp_lib_constexpr_string
+ !std::is_same_v<T, std::byte>;
-#else
+// Provide a minimal custom traits class for use by std::byte and if
+// std::char_traits is not yet fully constexpr (__cpp_lib_constexpr_string).
+template <typename T, bool = kUseStdCharTraits<T>>
+struct char_traits {
+ using char_type = T;
+ using int_type = unsigned int;
-// If constexpr std::char_traits is not available, provide a custom traits class
-// with constexpr versions of the necessary functions. Defer to std::char_traits
-// when possible.
-template <typename T>
-class char_traits : private std::char_traits<T> {
- public:
static constexpr void assign(T& dest, const T& source) noexcept {
dest = source;
}
@@ -83,7 +56,7 @@ class char_traits : private std::char_traits<T> {
return dest;
}
- using std::char_traits<T>::eq;
+ static constexpr bool eq(T lhs, T rhs) { return lhs == rhs; }
static constexpr T* move(T* dest, const T* source, size_t count) {
if (dest < source) {
@@ -103,10 +76,61 @@ class char_traits : private std::char_traits<T> {
return dest;
}
- using std::char_traits<T>::compare;
+ static constexpr int compare(const T* lhs, const T* rhs, size_t count) {
+ for (size_t i = 0; i < count; ++i) {
+ if (lhs[i] < rhs[i]) {
+ return -1;
+ }
+ if (rhs[i] < lhs[i]) {
+ return 1;
+ }
+ }
+ return 0;
+ }
};
-#endif // __cpp_lib_constexpr_string
+// Use std::char_traits for character types when it fully supports constexpr.
+template <typename T>
+struct char_traits<T, true> : public std::char_traits<T> {};
+
+// string_views for byte strings need to use Pigweed's custom char_traits since
+// std::char_traits<std::byte> is not defined. (Alternately, could specialize
+// std::char_traits, but this is simpler.) basic_string_view<byte> won't be
+// commonly used (byte spans are more common), but support it for completeness.
+template <typename T>
+struct StringViewType {
+ using type = std::basic_string_view<T>;
+};
+
+template <>
+struct StringViewType<std::byte> {
+ using type = std::basic_string_view<std::byte, char_traits<std::byte>>;
+};
+
+template <typename T>
+using View = typename StringViewType<T>::type;
+
+// Aliases for disabling overloads with SFINAE.
+template <typename CharType, typename T>
+using EnableIfNonArrayCharPointer = std::enable_if_t<
+ std::is_pointer<T>::value && !std::is_array<T>::value &&
+ std::is_same<CharType, std::remove_cv_t<std::remove_pointer_t<T>>>::value>;
+
+template <typename T>
+using EnableIfInputIterator = std::enable_if_t<
+ std::is_convertible<typename std::iterator_traits<T>::iterator_category,
+ std::input_iterator_tag>::value>;
+
+template <typename CharType, typename T>
+using EnableIfStringViewLike =
+ std::enable_if_t<std::is_convertible<const T&, View<CharType>>() &&
+ !std::is_convertible<const T&, const CharType*>()>;
+
+template <typename CharType, typename T>
+using EnableIfStringViewLikeButNotStringView =
+ std::enable_if_t<!std::is_same<T, View<CharType>>() &&
+ std::is_convertible<const T&, View<CharType>>() &&
+ !std::is_convertible<const T&, const CharType*>()>;
// Used in static_asserts to check that a C array fits in an InlineString.
constexpr bool NullTerminatedArrayFitsInString(
@@ -181,7 +205,6 @@ constexpr size_t IteratorCopy(InputIterator begin,
// If `InputIterator` is a `LegacyRandomAccessIterator`, the bounds check can
// be done up front, allowing the compiler more flexibility in optimizing the
// loop.
-#if PW_CXX_STANDARD_IS_SUPPORTED(17) // constexpr-if is a C++17 feature
using category =
typename std::iterator_traits<InputIterator>::iterator_category;
if constexpr (std::is_same_v<category, std::random_access_iterator_tag>) {
@@ -191,9 +214,6 @@ constexpr size_t IteratorCopy(InputIterator begin,
char_traits<T>::assign(*current_position++, *it);
}
} else {
-#else
- {
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
for (InputIterator it = begin; it != end; ++it) {
PW_ASSERT(current_position != string_end);
char_traits<T>::assign(*current_position++, *it);
@@ -215,5 +235,4 @@ constexpr int Compare(const T* lhs,
return lhs_size < rhs_size ? -1 : 1;
}
-} // namespace string_impl
-} // namespace pw
+} // namespace pw::string_impl
diff --git a/pw_string/public/pw_string/string.h b/pw_string/public/pw_string/string.h
index 7e544b192..ae932378b 100644
--- a/pw_string/public/pw_string/string.h
+++ b/pw_string/public/pw_string/string.h
@@ -21,9 +21,9 @@
#include <cstddef>
#include <initializer_list>
#include <iterator>
+#include <type_traits>
#include "pw_assert/assert.h"
-#include "pw_polyfill/standard.h"
#include "pw_preprocessor/compiler.h"
#include "pw_string/internal/string_impl.h"
@@ -44,7 +44,7 @@ namespace pw {
/// @brief `pw::InlineBasicString` is a fixed-capacity version of
/// `std::basic_string`. In brief:
///
-/// - It is C++14-compatible and null-terminated.
+/// - It is always null-terminated.
/// - It stores the string contents inline and uses no dynamic memory.
/// - It implements mostly the same API as `std::basic_string`, but the capacity
/// of the string is fixed at construction and cannot grow. Attempting to
@@ -139,7 +139,6 @@ class InlineBasicString final
constexpr InlineBasicString(std::initializer_list<T> list)
: InlineBasicString(list.begin(), list.size()) {}
-#if PW_CXX_STANDARD_IS_SUPPORTED(17) // std::string_view is a C++17 feature
// Unlike std::string, pw::InlineString<> supports implicit conversions from
// std::string_view. However, explicit conversions are still required from
// types that convert to std::string_view, as with std::string.
@@ -155,14 +154,14 @@ class InlineBasicString final
string_impl::EnableIfStringViewLikeButNotStringView<T, StringViewLike>* =
nullptr>
explicit constexpr InlineBasicString(const StringViewLike& string)
- : InlineBasicString(std::basic_string_view<T>(string)) {}
+ : InlineBasicString(string_impl::View<T>(string)) {}
// This converting constructor is enabled for std::string_view, but not types
// that convert to it.
- template <typename StringView,
- std::enable_if_t<
- std::is_same<StringView, std::basic_string_view<T>>::value>* =
- nullptr>
+ template <
+ typename StringView,
+ std::enable_if_t<std::is_same<StringView, string_impl::View<T>>::value>* =
+ nullptr>
constexpr InlineBasicString(const StringView& view)
: InlineBasicString(view.data(), view.size()) {}
@@ -172,10 +171,9 @@ class InlineBasicString final
size_t index,
size_t count)
: InlineBasicString() {
- const std::basic_string_view<T> view = string;
+ const string_impl::View<T> view = string;
CopySubstr(data(), view.data(), view.size(), index, count);
}
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
InlineBasicString(std::nullptr_t) = delete; // Cannot construct from nullptr
@@ -213,13 +211,11 @@ class InlineBasicString final
return assign(list); // NOLINT
}
-#if PW_CXX_STANDARD_IS_SUPPORTED(17) // std::string_view is a C++17 feature
template <typename StringView,
typename = string_impl::EnableIfStringViewLike<T, StringView>>
constexpr InlineBasicString& operator=(const StringView& string) {
return assign(string); // NOLINT
}
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
constexpr InlineBasicString& operator=(std::nullptr_t) = delete;
@@ -249,13 +245,11 @@ class InlineBasicString final
return append(list.begin(), list.size());
}
-#if PW_CXX_STANDARD_IS_SUPPORTED(17) // std::string_view is a C++17 feature
template <typename StringView,
typename = string_impl::EnableIfStringViewLike<T, StringView>>
constexpr InlineBasicString& operator+=(const StringView& string) {
return append(string);
}
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
// The data() and size() functions are defined differently for the generic and
// known-size specializations. This is to support using pw::InlineBasicString
@@ -405,6 +399,14 @@ class InlineBasicString<T, string_impl::kGeneric> {
}
private:
+ static_assert(std::is_same_v<char, T> || std::is_same_v<wchar_t, T> ||
+#ifdef __cpp_char8_t
+ std::is_same_v<char8_t, T> ||
+#endif // __cpp_char8_t
+ std::is_same_v<char16_t, T> ||
+ std::is_same_v<char32_t, T> || std::is_same_v<std::byte, T>,
+ "Only character types and std::byte are supported");
+
// Allow StringBuilder to directly set length_ when doing string operations.
friend class StringBuilder;
@@ -565,6 +567,12 @@ constexpr bool operator>=(const T* lhs,
template <size_t kCapacity = string_impl::kGeneric>
using InlineString = InlineBasicString<char, kCapacity>;
+/// @brief `pw::InlineByteString` is an alias of
+/// `pw::InlineBasicString<std::byte>`. `InlineByteString` may be used as a
+/// simple, efficient byte container.
+template <size_t kCapacity = string_impl::kGeneric>
+using InlineByteString = InlineBasicString<std::byte, kCapacity>;
+
// Function implementations
template <typename T>
diff --git a/pw_string/string_test.cc b/pw_string/string_test.cc
index 322477a5d..dc7dd321f 100644
--- a/pw_string/string_test.cc
+++ b/pw_string/string_test.cc
@@ -19,13 +19,10 @@
#include <type_traits>
#include "pw_compilation_testing/negative_compilation.h"
-#include "pw_polyfill/standard.h"
#include "pw_unit_test/framework.h"
namespace pw {
-#if PW_CXX_STANDARD_IS_SUPPORTED(17) // std::string_view is a C++17 feature
-
using namespace std::string_view_literals;
template <typename T>
@@ -53,8 +50,6 @@ class StringViewLikeButConvertsToPointer : public StringViewLike<T> {
std::basic_string_view<T> value_;
};
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
-
template <typename T>
class EvenNumberIterator {
public:
@@ -228,16 +223,12 @@ constexpr EvenNumberIterator<char> kEvenNumbers0(0);
constexpr EvenNumberIterator<char> kEvenNumbers2(2);
constexpr EvenNumberIterator<char> kEvenNumbers8(8);
-#if PW_CXX_STANDARD_IS_SUPPORTED(17) // std::string_view is a C++17 feature
-
constexpr std::string_view kView0;
constexpr std::string_view kView5 = "12345"sv;
constexpr std::string_view kView10 = "1234567890"sv;
constexpr StringViewLike<char> kStringViewLike10("0123456789", 10);
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
-
//
// Construction and assignment
//
@@ -418,7 +409,6 @@ TEST(InlineString, Construct_Array) {
}
TEST(InlineString, Construct_Iterator) {
-#if PW_CXX_STANDARD_IS_SUPPORTED(17) // std::string_view is a C++17 feature
TEST_STRING(InlineString<0>(kView0.begin(), kView0.end()), , "");
TEST_STRING(InlineString<0>(kView5.end(), kView5.end()), , "");
TEST_STRING(InlineString<5>(kView0.begin(), kView0.end()), , "");
@@ -427,7 +417,6 @@ TEST(InlineString, Construct_Iterator) {
TEST_STRING(InlineString<5>(kView5.begin(), kView5.end()), , "12345");
TEST_STRING(InlineString<10>(kView5.begin(), kView5.end()), , "12345");
TEST_STRING(InlineString<10>(kView10.begin(), kView10.end()), , "1234567890");
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
TEST_STRING(InlineString<0>(kEvenNumbers0, kEvenNumbers0), , "");
TEST_STRING(InlineString<10>(kEvenNumbers2, kEvenNumbers2), , "");
@@ -501,8 +490,6 @@ TEST(InlineString, Construct_InitializerList) {
#endif // PW_NC_TEST
}
-#if PW_CXX_STANDARD_IS_SUPPORTED(17)
-
constexpr InlineString<16> TakesInlineString(const InlineString<16>& str) {
return str;
}
@@ -592,7 +579,6 @@ TEST(InlineString, Construct_StringViewSubstr) {
[[maybe_unused]] constexpr InlineString<10> bad_string("12345"sv, 6, 0);
#endif // PW_NC_TEST
}
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
TEST(InlineString, Construct_Nullptr) {
#if PW_NC_TEST(Construct_Nullptr)
@@ -698,7 +684,6 @@ TEST(InlineString, AssignOperator_InitializerList) {
#endif // PW_NC_TEST
}
-#if PW_CXX_STANDARD_IS_SUPPORTED(17)
TEST(InlineString, AssignOperator_StringView) {
TEST_STRING(InlineString<1>(), fixed_str = "\0"sv, "\0");
TEST_STRING(InlineString<1>({'a'}), fixed_str = "\0"sv, "\0");
@@ -712,7 +697,6 @@ TEST(InlineString, AssignOperator_StringView) {
}();
#endif // PW_NC_TEST
}
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
// assign
@@ -959,7 +943,6 @@ TEST(InlineString, Assign_Array) {
}
TEST(InlineString, Assign_Iterator) {
-#if PW_CXX_STANDARD_IS_SUPPORTED(17)
TEST_STRING(InlineString<0>(), str.assign(kView0.begin(), kView0.end()), "");
TEST_STRING(InlineString<0>(), str.assign(kView5.end(), kView5.end()), "");
TEST_STRING(
@@ -975,7 +958,6 @@ TEST(InlineString, Assign_Iterator) {
TEST_STRING(InlineString<10>("abc"),
str.assign(kView10.begin(), kView10.end()),
"1234567890");
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
TEST_STRING(InlineString<0>(), str.assign(kEvenNumbers0, kEvenNumbers0), "");
TEST_STRING(InlineString<10>(), str.assign(kEvenNumbers2, kEvenNumbers2), "");
@@ -1020,7 +1002,6 @@ TEST(InlineString, Assign_InitializerList) {
#endif // PW_NC_TEST
}
-#if PW_CXX_STANDARD_IS_SUPPORTED(17)
TEST(InlineString, Assign_StringView) {
TEST_STRING(InlineString<0>(), str.assign(""sv), "");
TEST_STRING(InlineString<10>("abc"), str.assign(""sv), "");
@@ -1093,7 +1074,6 @@ TEST(InlineString, Assign_StringViewSubstr) {
}();
#endif // PW_NC_TEST
}
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
//
// Element access
@@ -1156,7 +1136,6 @@ TEST(InlineString, DataCStr) {
EXPECT_STREQ(kSize10Capacity10.c_str(), "1234567890");
}
-#if PW_CXX_STANDARD_IS_SUPPORTED(17)
TEST(InlineString, ConvertsToStringView) {
static_assert(std::string_view(kSize5Capacity10) == "12345"sv);
EXPECT_EQ(std::string_view(Generic(kSize5Capacity10)), "12345"sv);
@@ -1197,7 +1176,6 @@ TEST(InlineString, Iterators) {
return true;
}());
}
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
//
// Capacity
@@ -1438,7 +1416,6 @@ PW_NC_EXPECT("PW_ASSERT\(size\(\) - index <= max_size\(\) - new_index\)");
}();
#endif // PW_NC_TEST
-#if PW_CXX_STANDARD_IS_SUPPORTED(17)
TEST(InlineString, Insert_StringViewAtIndex) {
TEST_STRING(InlineString<0>(), str.insert(0, ""sv), "");
TEST_STRING(InlineString<10>("a"), str.insert(0, ""sv), "a");
@@ -1477,7 +1454,6 @@ PW_NC_EXPECT("PW_ASSERT\(size\(\) - index <= max_size\(\) - new_index\)");
return str.insert(1, "34"sv, 1);
}();
#endif // PW_NC_TEST
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
// erase.
@@ -1678,7 +1654,6 @@ TEST(InlineString, Append_InitializerList) {
#endif // PW_NC_TEST
}
-#if PW_CXX_STANDARD_IS_SUPPORTED(17)
TEST(InlineString, Append_StringView) {
TEST_STRING(InlineString<0>(), str.append(""sv), "");
TEST_STRING(InlineString<10>("a"), str.append(""sv), "a");
@@ -1711,7 +1686,6 @@ TEST(InlineString, Append_StringViewSubstr) {
}();
#endif // PW_NC_TEST
}
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
// operator+=
@@ -1801,7 +1775,6 @@ TEST(InlineString, AppendOperator_InitializerList) {
#endif // PW_NC_TEST
}
-#if PW_CXX_STANDARD_IS_SUPPORTED(17)
TEST(InlineString, AppendOperator_StringView) {
TEST_STRING(InlineString<0>(), fixed_str += ""sv, "");
TEST_STRING(InlineString<10>("a"), fixed_str += ""sv, "a");
@@ -1816,14 +1789,12 @@ TEST(InlineString, AppendOperator_StringView) {
}();
#endif // PW_NC_TEST
}
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
TEST(InlineString, Compare) {
EXPECT_EQ(InlineString<10>("abb").compare(InlineString<5>("abb")), 0);
EXPECT_LT(InlineString<10>("abb").compare(InlineString<5>("bbb")), 0);
EXPECT_LT(InlineString<10>("bb").compare(InlineString<5>("bbb")), 0);
-#if PW_CXX_STANDARD_IS_SUPPORTED(17)
static_assert(InlineString<10>("bbb").compare(InlineString<5>("bbb")) == 0,
"equal");
static_assert(InlineString<10>("abb").compare(InlineString<5>("bbb")) < 0,
@@ -1846,7 +1817,6 @@ TEST(InlineString, Compare) {
"less");
static_assert(InlineString<5>("abc").compare(InlineString<5>("")) > 0,
"greater");
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
}
// TODO: b/239996007 - Test other pw::InlineString functions:
@@ -1939,7 +1909,6 @@ TEST(InlineString, ComparisonOperators_InlineString) {
EXPECT_GT(InlineString<10>("b"), InlineString<10>("a"));
EXPECT_GE(InlineString<10>("b"), InlineString<10>("a"));
-#if PW_CXX_STANDARD_IS_SUPPORTED(17)
static_assert(InlineString<10>() == InlineString<10>(), "equal"); // NOLINT
static_assert(InlineString<10>("abc") == InlineString<5>("abc"), "equal");
static_assert(InlineString<1>({'a'}) == InlineString<10>("a"), "equal");
@@ -1990,7 +1959,6 @@ TEST(InlineString, ComparisonOperators_InlineString) {
"greater equal");
static_assert(!(InlineString<3>("\0\0") >= InlineString<10>("\1\0")),
"greater equal");
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
}
TEST(InlineString, ComparisonOperators_NullTerminatedString) {
@@ -2016,7 +1984,6 @@ TEST(InlineString, ComparisonOperators_NullTerminatedString) {
EXPECT_GE(InlineString<10>("a"), "a");
EXPECT_GE("a", InlineString<10>("a"));
-#if PW_CXX_STANDARD_IS_SUPPORTED(17)
static_assert(InlineString<10>() == "", "equal"); // NOLINT
static_assert("" == InlineString<10>(), "equal"); // NOLINT
static_assert(InlineString<10>("abc") == "abc", "equal");
@@ -2053,7 +2020,6 @@ TEST(InlineString, ComparisonOperators_NullTerminatedString) {
static_assert("abc" >= InlineString<5>("ab"), "greater equal");
static_assert(InlineString<10>("abc") >= "abc", "greater equal");
static_assert("abc" >= InlineString<5>("abc"), "greater equal");
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(17)
}
// Test instantiating an InlineBasicString with different character types.
@@ -2067,31 +2033,20 @@ TEST(InlineString, ComparisonOperators_NullTerminatedString) {
#define PW_STRING_WRAP_TEST_EXPANSION(expr)
#endif // __cpp_constexpr >= 201603L
-#define TEST_FOR_TYPES_BASE(test_macro, ...) \
- PW_STRING_WRAP_TEST_EXPANSION(test_macro(char, __VA_ARGS__)); \
- PW_STRING_WRAP_TEST_EXPANSION(test_macro(wchar_t, __VA_ARGS__));
-
-#if PW_CXX_STANDARD_IS_SUPPORTED(11)
-#define TEST_FOR_TYPES_CXX11(test_macro, ...) \
- TEST_FOR_TYPES_BASE(test_macro, __VA_ARGS__) \
+#define TEST_FOR_TYPES_BASE(test_macro, ...) \
+ PW_STRING_WRAP_TEST_EXPANSION(test_macro(char, __VA_ARGS__)); \
+ PW_STRING_WRAP_TEST_EXPANSION(test_macro(wchar_t, __VA_ARGS__)); \
PW_STRING_WRAP_TEST_EXPANSION(test_macro(char16_t, __VA_ARGS__)); \
PW_STRING_WRAP_TEST_EXPANSION(test_macro(char32_t, __VA_ARGS__));
-#else
-#define TEST_FOR_TYPES_CXX11(test_macro, ...) \
- TEST_FOR_TYPES_BASE(test_macro, __VA_ARGS__)
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(11)
-#if PW_CXX_STANDARD_IS_SUPPORTED(20)
-#define TEST_FOR_TYPES_CXX20(test_macro, ...) \
- TEST_FOR_TYPES_CXX11(test_macro, __VA_ARGS__) \
+#ifdef __cpp_char8_t
+#define TEST_FOR_TYPES(test_macro, ...) \
+ TEST_FOR_TYPES_BASE(test_macro, __VA_ARGS__) \
PW_STRING_WRAP_TEST_EXPANSION(test_macro(char8_t, __VA_ARGS__));
#else
-#define TEST_FOR_TYPES_CXX20(test_macro, ...) \
- TEST_FOR_TYPES_CXX11(test_macro, __VA_ARGS__)
-#endif // PW_CXX_STANDARD_IS_SUPPORTED(20)
-
#define TEST_FOR_TYPES(test_macro, ...) \
- TEST_FOR_TYPES_CXX20(test_macro, __VA_ARGS__)
+ TEST_FOR_TYPES_BASE(test_macro, __VA_ARGS__)
+#endif // __cpp_char8_t
TEST(BasicStrings, Empty) {
#define BASIC_STRINGS_EMPTY(type, capacity) \
@@ -2154,4 +2109,17 @@ TEST(BasicStrings, VariousOperations) {
#undef BASIC_STRINGS_VARIOUS_OPERATIONS
}
+TEST(BasicStrings, ByteString) {
+ InlineByteString<5> bytes;
+ bytes.push_back(std::byte{1});
+ bytes.push_back(std::byte{2});
+
+ EXPECT_EQ(bytes.size(), 2u);
+ EXPECT_EQ(bytes[0], std::byte{1});
+ EXPECT_EQ(bytes[1], std::byte{2});
+
+ InlineByteString<5> higher_bytes({std::byte{99}, std::byte{100}});
+ EXPECT_LT(bytes, higher_bytes);
+}
+
} // namespace pw