diff options
author | Wyatt Hepler <hepler@google.com> | 2024-03-01 00:02:52 +0000 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2024-05-08 22:18:53 -0700 |
commit | 0069dc840059ee077efa7b808807fc580596f40c (patch) | |
tree | 1ba9b93fda929860a1670e1d8941ba78ca479f8e | |
parent | 3a68395aa2e464420cc957f07249f1975014758e (diff) | |
download | pigweed-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.h | 3 | ||||
-rw-r--r-- | pw_string/BUILD.bazel | 5 | ||||
-rw-r--r-- | pw_string/BUILD.gn | 5 | ||||
-rw-r--r-- | pw_string/CMakeLists.txt | 1 | ||||
-rw-r--r-- | pw_string/public/pw_string/internal/string_common_functions.inc | 26 | ||||
-rw-r--r-- | pw_string/public/pw_string/internal/string_impl.h | 119 | ||||
-rw-r--r-- | pw_string/public/pw_string/string.h | 36 | ||||
-rw-r--r-- | pw_string/string_test.cc | 74 |
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 |