diff options
author | aarongreen <aarongreen@google.com> | 2023-05-30 16:58:31 +0000 |
---|---|---|
committer | CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-05-30 16:58:31 +0000 |
commit | 0afc2d5743f9af77d5c8007f5b8720370b3e3ac9 (patch) | |
tree | 714739cc77253395e5cbd536ffd7bb220ff8e336 /pw_string | |
parent | 255ab6106000d8d698ed61105bb40b11eecdaf6e (diff) | |
download | pigweed-0afc2d5743f9af77d5c8007f5b8720370b3e3ac9.tar.gz |
pw_string: Add insert, erase
Bug: b/239996007
Change-Id: I214cd243e21328a9bc19281b3c878ed16f5bbdc6
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/148333
Commit-Queue: Aaron Green <aarongreen@google.com>
Reviewed-by: Taylor Cramer <cramertj@google.com>
Diffstat (limited to 'pw_string')
-rw-r--r-- | pw_string/public/pw_string/internal/string_common_functions.inc | 165 | ||||
-rw-r--r-- | pw_string/public/pw_string/internal/string_impl.h | 50 | ||||
-rw-r--r-- | pw_string/public/pw_string/string.h | 146 | ||||
-rw-r--r-- | pw_string/string_test.cc | 308 |
4 files changed, 586 insertions, 83 deletions
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 761beed60..4fa140b1b 100644 --- a/pw_string/public/pw_string/internal/string_common_functions.inc +++ b/pw_string/public/pw_string/internal/string_common_functions.inc @@ -81,8 +81,7 @@ constexpr InlineBasicString& assign(const T (&array)[kCharArraySize]) { template <typename InputIterator, typename = string_impl::EnableIfInputIterator<InputIterator>> constexpr InlineBasicString& assign(InputIterator start, InputIterator finish) { - return static_cast<InlineBasicString&>( - IteratorCopy(start, finish, data(), data() + max_size())); + return static_cast<InlineBasicString&>(CopyIterator(data(), start, finish)); } constexpr InlineBasicString& assign(std::initializer_list<T> list) { @@ -181,7 +180,152 @@ constexpr size_t capacity() const noexcept { return max_size(); } constexpr void clear() { SetSizeAndTerminate(data(), 0); } -// TODO(b/239996007): Implement insert and erase. +constexpr InlineBasicString& insert(size_t index, size_t count, T ch) { + MoveExtend(data(), index, index + count); + return static_cast<InlineBasicString&>(FillExtend(data(), index, ch, count)); +} + +constexpr InlineBasicString& insert(size_t index, + const T* string, + size_t count) { + MoveExtend(data(), index, index + count); + return static_cast<InlineBasicString&>( + CopyExtend(data(), index, string, count)); +} + +template <size_t kCharArraySize> +constexpr InlineBasicString& insert(size_t index, + const T (&array)[kCharArraySize]) { + return insert( + index, array, string_impl::ArrayStringLength(array, max_size())); +} + +template <typename U, typename = string_impl::EnableIfNonArrayCharPointer<T, U>> +constexpr InlineBasicString& insert(size_t index, U c_string) { + return insert( + index, c_string, string_impl::BoundedStringLength(c_string, max_size())); +} + +template <size_t kOtherCapacity> +constexpr InlineBasicString& insert( + size_t index, const InlineBasicString<T, kOtherCapacity>& string) { + return insert(index, string.data(), string.size()); +} + +template <size_t kOtherCapacity> +constexpr InlineBasicString& insert( + size_t index, + const InlineBasicString<T, kOtherCapacity>& other, + size_t other_index, + size_t count = npos) { + PW_ASSERT(other_index <= other.size()); + if (count == npos || count > other.size() - other_index) { + count = other.size() - other_index; + } + PW_ASSERT(index <= index + count); + MoveExtend(data(), index, index + count); + return static_cast<InlineBasicString&>(CopyExtendSubstr( + data(), index, other.data(), other.size(), other_index, count)); +} + +// Use a templated type rather than `const_iterator` to convince the compiler +// to prefer `0` as an index rather than as a `nullptr`. +template <typename U> +constexpr iterator insert(const U* pos, size_t count, T ch) { + PW_ASSERT(cbegin() <= pos && pos <= cend()); + size_t index = static_cast<size_t>(pos - cbegin()); + PW_ASSERT(index <= index + count); + MoveExtend(data(), index, index + count); + FillExtend(data(), index, ch, count); + return begin() + index; +} + +template <typename U> +constexpr iterator insert(const U* pos, T ch) { + return insert(pos, 1, ch); +} + +template <typename U, class InputIt> +constexpr iterator insert(const U* pos, InputIt first, InputIt last) { + PW_ASSERT(cbegin() <= pos && pos <= cend()); + size_t index = static_cast<size_t>(pos - cbegin()); + size_t count = 0; + for (auto tmp = first; tmp != last; ++tmp) { + PW_ASSERT(count < max_size()); + ++count; + } + PW_ASSERT(index <= index + count); + MoveExtend(data(), index, index + count); + CopyIteratorExtend(data(), index, first, last); + return begin() + index; +} + +template <typename U> +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; + PW_ASSERT(view.size() < npos); + PW_ASSERT(string_index <= view.size()); + if (count == npos || count > view.size() - string_index) { + count = view.size() - string_index; + } + PW_ASSERT(index <= index + count); + MoveExtend(data(), index, index + count); + return static_cast<InlineBasicString&>(CopyExtendSubstr( + data(), index, view.data(), view.size(), string_index, count)); +} + +template <typename StringView, + typename = string_impl::EnableIfStringViewLike<T, StringView>> +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 = + index + std::min(count == npos ? size() : count, size() - index); + return static_cast<InlineBasicString&>(MoveExtend(data(), old_index, index)); +} + +// Use a templated type rather than `const_iterator` to convince the compiler +// to prefer `0` as an index rather than as a `nullptr`. +template <typename U> +constexpr iterator erase(const U* pos) { + PW_ASSERT(cbegin() <= pos && pos <= cend()); + size_t index = static_cast<size_t>(pos - cbegin()); + size_t old_index = index + 1; + if (old_index <= size()) { + MoveExtend(data(), old_index, index); + } + return old_index <= size() ? begin() + index : end(); +} + +template <typename U> +constexpr iterator erase(const U* first, const U* last) { + PW_ASSERT(cbegin() <= first && first <= cend()); + size_t old_index = + first == cend() ? size() : static_cast<size_t>(first - cbegin()); + size_t index = old_index; + for (auto tmp = first; tmp != last; ++tmp) { + PW_ASSERT(index < size()); + ++old_index; + } + MoveExtend(data(), old_index, index); + return old_index <= size() ? begin() + index : end(); +} constexpr void push_back(value_type ch) { static_assert(kCapacity != 0, @@ -196,7 +340,7 @@ constexpr void pop_back() { } constexpr InlineBasicString& append(size_t count, T ch) { - return static_cast<InlineBasicString&>(FillExtend(data(), ch, count)); + return static_cast<InlineBasicString&>(FillExtend(data(), size(), ch, count)); } template <size_t kOtherCapacity> @@ -213,12 +357,13 @@ constexpr InlineBasicString& append( const InlineBasicString<T, kOtherCapacity>& other, size_t index, size_t count = npos) { - return static_cast<InlineBasicString&>( - CopyExtendSubstr(data(), other.data(), other.size(), index, count)); + return static_cast<InlineBasicString&>(CopyExtendSubstr( + data(), size(), other.data(), other.size(), index, count)); } constexpr InlineBasicString& append(const T* string, size_t count) { - return static_cast<InlineBasicString&>(CopyExtend(data(), string, count)); + return static_cast<InlineBasicString&>( + CopyExtend(data(), size(), string, count)); } template <size_t kCharArraySize> @@ -239,11 +384,11 @@ template <typename InputIterator, typename = string_impl::EnableIfInputIterator<InputIterator>> constexpr InlineBasicString& append(InputIterator first, InputIterator last) { return static_cast<InlineBasicString&>( - IteratorExtend(first, last, data() + size(), data() + max_size())); + CopyIteratorExtend(data(), size(), first, last)); } constexpr InlineBasicString& append(std::initializer_list<T> list) { - return append(list.begin(), pw::string_impl::CheckedCastToSize(list.size())); + return append(list.begin(), list.size()); } #if PW_CXX_STANDARD_IS_SUPPORTED(17) // std::string_view is a C++17 feature @@ -264,7 +409,7 @@ constexpr InlineBasicString& append(const StringView& string, const std::basic_string_view<T> view = string; PW_ASSERT(view.size() < npos); return static_cast<InlineBasicString&>( - CopyExtendSubstr(data(), view.data(), view.size(), index, count)); + CopyExtendSubstr(data(), size(), view.data(), view.size(), index, count)); } #endif // PW_CXX_STANDARD_IS_SUPPORTED(17) diff --git a/pw_string/public/pw_string/internal/string_impl.h b/pw_string/public/pw_string/internal/string_impl.h index 80b8ded1c..9672d0c17 100644 --- a/pw_string/public/pw_string/internal/string_impl.h +++ b/pw_string/public/pw_string/internal/string_impl.h @@ -27,7 +27,7 @@ namespace pw { namespace string_impl { -// pw::InlineString<>::size_t is unsigned short so the capacity and current +// pw::InlineString<>::size_type is unsigned short so the capacity and current // size fit into a single word. using size_type = unsigned short; @@ -85,6 +85,17 @@ class char_traits : private std::char_traits<T> { using std::char_traits<T>::eq; + static constexpr T* move(T* dest, const T* source, size_t count) { + if (dest < source) { + char_traits<T>::copy(dest, source, count); + } else if (source < dest) { + for (size_t i = count; i != 0; --i) { + char_traits<T>::assign(dest[i - 1], source[i - 1]); + } + } + return dest; + } + static constexpr T* copy(T* dest, const T* source, size_t count) { for (size_t i = 0; i < count; ++i) { char_traits<T>::assign(dest[i], source[i]); @@ -154,21 +165,40 @@ constexpr size_t ArrayStringLength(const T (&array)[kCharArraySize], static_assert(kCharArraySize - 1 < kGeneric, "The size of this literal or character array is too large " "for pw::InlineString<>::size_t"); - return ArrayStringLength(array, kCharArraySize - 1, capacity); + return ArrayStringLength( + array, static_cast<size_t>(kCharArraySize - 1), capacity); } // Constexpr version of std::copy that returns the number of copied characters. +// Does NOT null-terminate the string. template <typename InputIterator, typename T> -constexpr size_t IteratorCopyAndTerminate(InputIterator begin, - InputIterator end, - T* const string_begin, - const T* const string_end) { +constexpr size_t IteratorCopy(InputIterator begin, + InputIterator end, + T* const string_begin, + const T* const string_end) { T* current_position = string_begin; - for (InputIterator it = begin; it != end; ++it) { - PW_ASSERT(current_position != string_end); - char_traits<T>::assign(*current_position++, *it); + + // 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>) { + PW_ASSERT(begin <= end); + PW_ASSERT(end - begin <= string_end - string_begin); + for (InputIterator it = begin; it != end; ++it) { + 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); + } } - char_traits<T>::assign(*current_position, T()); // Null terminate return static_cast<size_t>(current_position - string_begin); } diff --git a/pw_string/public/pw_string/string.h b/pw_string/public/pw_string/string.h index d66543e81..1f4d9a335 100644 --- a/pw_string/public/pw_string/string.h +++ b/pw_string/public/pw_string/string.h @@ -120,7 +120,7 @@ class InlineBasicString final typename = string_impl::EnableIfInputIterator<InputIterator>> constexpr InlineBasicString(InputIterator start, InputIterator finish) : InlineBasicString() { - IteratorCopy(start, finish, data(), data() + max_size()); + CopyIterator(data(), start, finish); } // Use the default copy for InlineBasicString with the same capacity. @@ -164,8 +164,7 @@ class InlineBasicString final std::is_same<StringView, std::basic_string_view<T>>::value>* = nullptr> constexpr InlineBasicString(const StringView& view) - : InlineBasicString(view.data(), - pw::string_impl::CheckedCastToSize(view.size())) {} + : InlineBasicString(view.data(), view.size()) {} template <typename StringView, typename = string_impl::EnableIfStringViewLike<T, StringView>> @@ -174,11 +173,7 @@ class InlineBasicString final size_t count) : InlineBasicString() { const std::basic_string_view<T> view = string; - CopySubstr(data(), - view.data(), - pw::string_impl::CheckedCastToSize(view.size()), - index, - count); + CopySubstr(data(), view.data(), view.size(), index, count); } #endif // PW_CXX_STANDARD_IS_SUPPORTED(17) @@ -287,11 +282,12 @@ class InlineBasicString final using InlineBasicString<T, string_impl::kGeneric>::Copy; using InlineBasicString<T, string_impl::kGeneric>::CopySubstr; using InlineBasicString<T, string_impl::kGeneric>::Fill; - using InlineBasicString<T, string_impl::kGeneric>::IteratorCopy; + using InlineBasicString<T, string_impl::kGeneric>::CopyIterator; using InlineBasicString<T, string_impl::kGeneric>::CopyExtend; using InlineBasicString<T, string_impl::kGeneric>::CopyExtendSubstr; using InlineBasicString<T, string_impl::kGeneric>::FillExtend; - using InlineBasicString<T, string_impl::kGeneric>::IteratorExtend; + using InlineBasicString<T, string_impl::kGeneric>::MoveExtend; + using InlineBasicString<T, string_impl::kGeneric>::CopyIteratorExtend; using InlineBasicString<T, string_impl::kGeneric>::Resize; using InlineBasicString<T, string_impl::kGeneric>::SetSizeAndTerminate; @@ -366,34 +362,36 @@ class InlineBasicString<T, string_impl::kGeneric> { constexpr InlineBasicString& Fill(T* data, T fill_char, size_t new_size); template <typename InputIterator> - constexpr InlineBasicString& IteratorCopy(InputIterator start, - InputIterator finish, - T* data_start, - const T* data_finish) { - set_size(string_impl::IteratorCopyAndTerminate( - start, finish, data_start, data_finish)); - return *this; - } + constexpr InlineBasicString& CopyIterator(T* data_start, + InputIterator begin, + InputIterator end); constexpr InlineBasicString& CopyExtend(T* data, + size_t index, const T* source, size_t count); - constexpr InlineBasicString& CopyExtendSubstr( - T* data, const T* source, size_t source_size, size_t index, size_t count); + constexpr InlineBasicString& CopyExtendSubstr(T* data, + size_t index, + const T* source, + size_t source_size, + size_t source_index, + size_t count); - constexpr InlineBasicString& FillExtend(T* data, T fill_char, size_t count); + constexpr InlineBasicString& FillExtend(T* data, + size_t index, + T fill_char, + size_t count); template <typename InputIterator> - constexpr InlineBasicString& IteratorExtend(InputIterator start, - InputIterator finish, - T* data_start, - const T* data_finish) { - set_size(string_impl::IteratorCopyAndTerminate( - start, finish, data_start, data_finish) + - size()); - return *this; - } + constexpr InlineBasicString& CopyIteratorExtend(T* data, + size_t index, + InputIterator begin, + InputIterator end); + + constexpr InlineBasicString& MoveExtend(T* data, + size_t index, + size_t new_index); constexpr void Resize(T* data, size_t new_size, T ch); @@ -401,6 +399,7 @@ class InlineBasicString<T, string_impl::kGeneric> { length_ = string_impl::CheckedCastToSize(length); } constexpr void SetSizeAndTerminate(T* data, size_t length) { + PW_ASSERT(length <= max_size()); string_impl::char_traits<T>::assign(data[length], T()); set_size(length); } @@ -597,43 +596,92 @@ InlineBasicString<T, string_impl::kGeneric>::CopySubstr( template <typename T> constexpr InlineBasicString<T, string_impl::kGeneric>& -InlineBasicString<T, string_impl::kGeneric>::Fill(T* data, - T fill_char, - size_t new_size) { - PW_ASSERT(new_size <= max_size()); - string_impl::char_traits<T>::assign(data, new_size, fill_char); - SetSizeAndTerminate(data, new_size); +InlineBasicString<T, string_impl::kGeneric>::CopyExtend(T* data, + size_t index, + const T* source, + size_t count) { + PW_ASSERT(index <= size()); + PW_ASSERT(count <= max_size() - index); + string_impl::char_traits<T>::copy(data + index, source, count); + SetSizeAndTerminate(data, std::max(size(), index + count)); return *this; } template <typename T> constexpr InlineBasicString<T, string_impl::kGeneric>& -InlineBasicString<T, string_impl::kGeneric>::CopyExtend(T* data, - const T* source, - size_t count) { - PW_ASSERT(count <= max_size() - size()); - string_impl::char_traits<T>::copy(data + size(), source, count); - SetSizeAndTerminate(data, size() + count); +InlineBasicString<T, string_impl::kGeneric>::CopyExtendSubstr( + T* data, + size_t index, + const T* source, + size_t source_size, + size_t source_index, + size_t count) { + PW_ASSERT(source_index <= source_size); + return CopyExtend(data, + index, + source + source_index, + std::min(count, source_size - source_index)); return *this; } template <typename T> +template <typename InputIterator> constexpr InlineBasicString<T, string_impl::kGeneric>& -InlineBasicString<T, string_impl::kGeneric>::CopyExtendSubstr( - T* data, const T* source, size_t source_size, size_t index, size_t count) { - PW_ASSERT(index <= source_size); - return CopyExtend(data, source + index, std::min(count, source_size - index)); +InlineBasicString<T, string_impl::kGeneric>::CopyIterator(T* data, + InputIterator begin, + InputIterator end) { + size_t length = + string_impl::IteratorCopy(begin, end, data, data + max_size()); + SetSizeAndTerminate(data, length); + return *this; +} + +template <typename T> +template <typename InputIterator> +constexpr InlineBasicString<T, string_impl::kGeneric>& +InlineBasicString<T, string_impl::kGeneric>::CopyIteratorExtend( + T* data, size_t index, InputIterator begin, InputIterator end) { + size_t length = + string_impl::IteratorCopy(begin, end, data + index, data + max_size()); + SetSizeAndTerminate(data, std::max(size(), index + length)); + return *this; +} + +template <typename T> +constexpr InlineBasicString<T, string_impl::kGeneric>& +InlineBasicString<T, string_impl::kGeneric>::Fill(T* data, + T fill_char, + size_t new_size) { + PW_ASSERT(new_size <= max_size()); + string_impl::char_traits<T>::assign(data, new_size, fill_char); + SetSizeAndTerminate(data, new_size); return *this; } template <typename T> constexpr InlineBasicString<T, string_impl::kGeneric>& InlineBasicString<T, string_impl::kGeneric>::FillExtend(T* data, + size_t index, T fill_char, size_t count) { - PW_ASSERT(count <= max_size() - size()); - string_impl::char_traits<T>::assign(data + size(), count, fill_char); - SetSizeAndTerminate(data, size() + count); + PW_ASSERT(index <= size()); + PW_ASSERT(count <= max_size() - index); + string_impl::char_traits<T>::assign(data + index, count, fill_char); + SetSizeAndTerminate(data, std::max(size(), index + count)); + return *this; +} + +template <typename T> +constexpr InlineBasicString<T, string_impl::kGeneric>& +InlineBasicString<T, string_impl::kGeneric>::MoveExtend(T* data, + size_t index, + size_t new_index) { + PW_ASSERT(index <= size()); + PW_ASSERT(new_index <= max_size()); + PW_ASSERT(size() - index <= max_size() - new_index); + string_impl::char_traits<T>::move( + data + new_index, data + index, size() - index); + SetSizeAndTerminate(data, size() - index + new_index); return *this; } diff --git a/pw_string/string_test.cc b/pw_string/string_test.cc index 96d55e474..ad962fdd3 100644 --- a/pw_string/string_test.cc +++ b/pw_string/string_test.cc @@ -1238,9 +1238,289 @@ TEST(InlineString, Clear) { TEST_STRING(InlineString<8>("!!"), str.clear(); str.assign("?"), "?"); } -// TODO(b/239996007): Test insert. - -// TODO(b/239996007): Test erase. +// // insert + +// TEST(InlineString, Insert_CharactersAtIndex) { +// TEST_STRING(InlineString<1>(), str.insert(0, 0, 'b'), ""); +// TEST_STRING(InlineString<1>("a"), str.insert(0, 0, 'b'), "a"); +// TEST_STRING(InlineString<10>("a"), str.insert(0, 2, 'b'), "bba"); +// TEST_STRING(InlineString<10>("a"), str.insert(1, 2, 'b'), "abb"); +// TEST_STRING(InlineString<10>(), str.insert(0, 10, 'b'), "bbbbbbbbbb"); +// } +// #if PW_NC_TEST(Insert_CharactersAtIndex_DoesNotFit) +// PW_NC_EXPECT("PW_ASSERT\(size\(\) - index <= max_size\(\) - new_index\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<3> str({0, 1}); +// return str.insert(1, 2, '?'); +// }(); +// #endif // PW_NC_TEST + +// TEST(InlineString, Insert_PointerSizeAtIndex) { +// TEST_STRING(InlineString<1>(), str.insert(0, "", 0), ""); +// TEST_STRING(InlineString<1>("a"), str.insert(0, "b", 0), "a"); +// TEST_STRING(InlineString<10>("a"), str.insert(0, "bb", 2), "bba"); +// TEST_STRING(InlineString<10>("a"), str.insert(1, "bb", 2), "abb"); +// TEST_STRING( +// InlineString<10>(), str.insert(0, "bbbbbbbbbb", 10), "bbbbbbbbbb"); +// } +// #if PW_NC_TEST(Insert_PointerSizeAtIndex_DoesNotFit) +// PW_NC_EXPECT("PW_ASSERT\(size\(\) - index <= max_size\(\) - new_index\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<3> str({0, 1}); +// return str.insert(1, "23", 2); +// }(); +// #endif // PW_NC_TEST + +// TEST(InlineString, Insert_ArrayAtIndex) { +// TEST_STRING(InlineString<1>(), fixed_str.insert(0, ""), ""); +// TEST_STRING(InlineString<2>(), fixed_str.insert(0, "a"), "a"); +// TEST_STRING(InlineString<6>(), fixed_str.insert(0, "12345"), "12345"); + +// TEST_STRING(InlineString<1>({'a'}), fixed_str.insert(1, ""), "a"); +// TEST_STRING(InlineString<2>("a"), fixed_str.insert(1, "a"), "aa"); +// TEST_STRING(InlineString<6>("a"), fixed_str.insert(1, "12345"), "a12345"); +// } +// #if PW_NC_TEST(Insert_ArrayAtIndex_DoesNotFit) +// PW_NC_EXPECT("PW_ASSERT\(size\(\) - index <= max_size\(\) - new_index\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<4> str({0, 1}); +// return str.insert(1, "123"); +// }(); +// #endif // PW_NC_TEST + +// TEST(InlineString, Insert_PointerAtIndex) { +// TEST_STRING(InlineString<0>(), str.insert(0, kPointer0), ""); +// TEST_STRING(InlineString<10>(), str.insert(0, kPointer10), "9876543210"); +// TEST_STRING( +// InlineString<10>("abc"), str.insert(1, kPointer10 + 5), "a43210bc"); +// TEST_STRING( +// InlineString<13>("abc"), str.insert(3, kPointer10), "abc9876543210"); +// } +// #if PW_NC_TEST(Insert_PointerAtIndex_DoesNotFit) +// PW_NC_EXPECT("PW_ASSERT\(size\(\) - index <= max_size\(\) - new_index\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<3> str({0, 1}); +// return str.insert(1, kPointer10 + 8); +// }(); +// #endif // PW_NC_TEST + +// TEST(InlineString, Insert_BasicStringAtIndex) { +// TEST_STRING(InlineString<0>(), str.insert(0, kEmptyCapacity0), ""); +// TEST_STRING(InlineString<10>(), str.insert(0, kEmptyCapacity10), ""); +// TEST_STRING(InlineString<10>(), str.insert(0, kSize5Capacity10), "12345"); +// TEST_STRING( +// InlineString<10>(), str.insert(0, kSize10Capacity10), "1234567890"); + +// TEST_STRING(InlineString<1>({'a'}), str.insert(0, kEmptyCapacity0), "a"); +// TEST_STRING(InlineString<11>("a"), str.insert(1, kEmptyCapacity10), "a"); +// TEST_STRING( +// InlineString<12>("aa"), str.insert(1, kSize5Capacity10), "a12345a"); +// TEST_STRING( +// InlineString<12>("aa"), str.insert(2, kSize10Capacity10), +// "aa1234567890"); +// } + +// #if PW_NC_TEST(Insert_BasicStringAtIndex_DoesNotFit) +// PW_NC_EXPECT("PW_ASSERT\(new_index <= max_size\(\)\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<3> str({0, 1}); +// return str.insert(1, kSize5Capacity10); +// }(); +// #endif // PW_NC_TEST + +// TEST(InlineString, Insert_BasicStringSubstrAtIndex) { +// TEST_STRING( +// InlineString<1>({'a'}), str.insert(0, kEmptyCapacity0, 0, 0), "a"); +// TEST_STRING( +// InlineString<11>("a"), str.insert(1, kSize10Capacity10, 10, 0), "a"); +// TEST_STRING(InlineString<12>("aa"), +// str.insert(1, kSize10Capacity10, 3, 5), +// "a45678a"); +// TEST_STRING(InlineString<12>("aa"), +// str.insert(2, kSize10Capacity10, 0, 10), +// "aa1234567890"); +// } +// #if PW_NC_TEST(Insert_BasicStringSubstrAtIndex_DoesNotFit) +// PW_NC_EXPECT("PW_ASSERT\(size\(\) - index <= max_size\(\) - new_index\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<3> str({0, 1}); +// return str.insert(1, kSize5Capacity10, 1, 2); +// }(); +// #endif // PW_NC_TEST + +// TEST(InlineString, Insert_CharactersAtPosition) { +// TEST_STRING(InlineString<1>(), str.insert(str.begin(), 0, 'b'), ""); +// TEST_STRING(InlineString<1>("a"), str.insert(str.begin(), 0, 'b'), "a"); +// TEST_STRING(InlineString<10>("a"), str.insert(str.begin(), 2, 'b'), "bba"); +// TEST_STRING( +// InlineString<10>("a"), str.insert(str.begin() + 1, 2, 'b'), "abb"); +// TEST_STRING(InlineString<10>(), str.insert(str.end(), 10, 'b'), +// "bbbbbbbbbb"); +// } + +// #if PW_NC_TEST(Insert_CharactersAtPosition_DoesNotFit) +// PW_NC_EXPECT("PW_ASSERT\(size\(\) - index <= max_size\(\) - new_index\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<3> str({0, 1}); +// return str.insert(str.begin() + 1, 2, '?'); +// }(); +// #endif // PW_NC_TEST + +// TEST(InlineString, Insert_CharacterAtPosition) { +// TEST_STRING(InlineString<1>(), str.insert(str.begin(), 'b'), "b"); +// TEST_STRING(InlineString<10>("aa"), str.insert(str.begin(), 'b'), "baa"); +// TEST_STRING(InlineString<10>("aa"), str.insert(str.begin() + 1, 'b'), +// "aba"); TEST_STRING(InlineString<10>("aa"), str.insert(str.begin() + 2, +// 'b'), "aab"); TEST_STRING(InlineString<10>("aa"), str.insert(str.end(), +// 'b'), "aab"); +// } +// #if PW_NC_TEST(Insert_CharacterAtPosition_DoesNotFit) +// PW_NC_EXPECT("PW_ASSERT\(size\(\) - index <= max_size\(\) - new_index\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<2> str({0, 1}); +// return str.insert(str.begin() + 1, '?'); +// }(); +// #endif // PW_NC_TEST + +// TEST(InlineString, Insert_IteratorsAtPosition) { +// TEST_STRING(InlineString<0>(), +// str.insert(str.begin(), kEvenNumbers0, kEvenNumbers0), +// ""); +// TEST_STRING(InlineString<10>(), +// str.insert(str.end(), kEvenNumbers0, kEvenNumbers0), +// ""); +// TEST_STRING(InlineString<10>(), +// str.insert(str.end(), kEvenNumbers0, kEvenNumbers0), +// ""); +// TEST_STRING(InlineString<10>(), +// str.insert(str.begin(), kEvenNumbers0, kEvenNumbers8), +// "\0\2\4\6"); +// TEST_STRING(InlineString<10>(), +// str.insert(str.end(), kEvenNumbers0, kEvenNumbers8), +// "\0\2\4\6"); +// TEST_STRING(InlineString<10>("aa"), +// str.insert(str.begin(), kEvenNumbers0, kEvenNumbers8), +// "\0\2\4\6aa"); +// TEST_STRING(InlineString<10>("aa"), +// str.insert(str.begin() + 1, kEvenNumbers0, kEvenNumbers8), +// "a\0\2\4\6a"); +// TEST_STRING(InlineString<10>("aa"), +// str.insert(str.begin() + 2, kEvenNumbers0, kEvenNumbers8), +// "aa\0\2\4\6"); +// TEST_STRING(InlineString<10>("aa"), +// str.insert(str.end(), kEvenNumbers0, kEvenNumbers8), +// "aa\0\2\4\6"); +// } +// #if PW_NC_TEST(Insert_IteratorsAtPosition_DoesNotFit) +// PW_NC_EXPECT("PW_ASSERT\(count < max_size\(\)\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<3> str({0, 1}); +// return str.insert(str.begin() + 1, kEvenNumbers0, kEvenNumbers8); +// }(); +// #endif // PW_NC_TEST + +// TEST(InlineString, Insert_InitializerListAtPosition) { +// TEST_STRING(InlineString<0>(), str.insert(str.begin(), {}), ""); +// TEST_STRING(InlineString<10>(), str.insert(str.end(), {1, 2, 3}), +// "\1\2\3"); TEST_STRING( +// InlineString<10>("abc"), str.insert(str.begin(), {1, 2, 3}), +// "\1\2\3abc"); +// TEST_STRING(InlineString<10>("abc"), +// str.insert(str.begin() + 1, {1, 2, 3}), +// "a\1\2\3bc"); +// TEST_STRING(InlineString<10>("abc"), +// str.insert(str.begin() + 3, {1, 2, 3}), +// "abc\1\2\3"); +// TEST_STRING( +// InlineString<5>("abc"), str.insert(str.end(), {'4', '5'}), "abc45"); +// } +// #if PW_NC_TEST(Insert_InitializerListAtPosition_DoesNotFit) +// PW_NC_EXPECT("PW_ASSERT\(size\(\) - index <= max_size\(\) - new_index\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<3> str({0, 1, 2}); +// return str.insert(str.begin() + 1, {3}); +// }(); +// #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"); +// TEST_STRING(InlineString<10>("abc"), str.insert(0, "123"sv), "123abc"); +// TEST_STRING(InlineString<10>("abc"), str.insert(1, "123"sv), "a123bc"); +// TEST_STRING(InlineString<5>("abc"), str.insert(3, "45"sv), "abc45"); +// } +// #if PW_NC_TEST(Insert_StringViewAtIndex_DoesNotFit) +// PW_NC_EXPECT("PW_ASSERT\(size\(\) - index <= max_size\(\) - new_index\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<3> str({0, 1, 2}); +// return str.insert(1, "3"sv); +// }(); +// #endif // PW_NC_TEST + +// TEST(InlineString, Insert_StringViewSubstrAtIndex) { +// TEST_STRING(InlineString<0>(), str.insert(0, ""sv, 0), ""); +// TEST_STRING(InlineString<0>(), str.insert(0, ""sv, 0, 0), ""); +// TEST_RUNTIME_STRING( +// InlineString<5>("aa"), str.insert(0, "123"sv, 0), "123aa"); +// TEST_RUNTIME_STRING( +// InlineString<10>("aa"), str.insert(1, "123"sv, 1, 0), "aa"); +// TEST_RUNTIME_STRING( +// InlineString<10>("aa"), str.insert(1, "123"sv, 1, 1), "a2a"); +// TEST_RUNTIME_STRING( +// InlineString<10>("aa"), str.insert(1, "123"sv, 1, 99), "a23a"); +// TEST_RUNTIME_STRING( +// InlineString<10>("aa"), str.insert(2, "123"sv, 1, 99), "aa23"); +// TEST_RUNTIME_STRING( +// InlineString<10>("aa"), str.insert(2, "123"sv, 3, 99), "aa"); +// } +// #if PW_NC_TEST(Insert_StringViewSubstrAtIndex_DoesNotFit) +// PW_NC_EXPECT("PW_ASSERT\(size\(\) - index <= max_size\(\) - new_index\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<3> str({0, 1, 2}); +// return str.insert(1, "34"sv, 1); +// }(); +// #endif // PW_NC_TEST +// #endif // PW_CXX_STANDARD_IS_SUPPORTED(17) + +// // erase. + +// TEST(InlineString, Erase_CharactersAtIndex) { +// TEST_STRING(InlineString<0>(), str.erase(), ""); +// TEST_STRING(InlineString<10>("abc"), str.erase(), ""); +// TEST_STRING(InlineString<10>("abc"), str.erase(0), ""); +// TEST_STRING(InlineString<10>("abc"), str.erase(1), "a"); +// TEST_STRING(InlineString<10>("abc"), str.erase(1, 1), "ac"); +// TEST_STRING(InlineString<10>("abc"), str.erase(1, 10), "a"); +// TEST_STRING(InlineString<10>("abc"), str.erase(3, 10), "abc"); +// } +// #if PW_NC_TEST(Erase_IndexOutOfRange) +// PW_NC_EXPECT("PW_ASSERT\(index <= size\(\)\)"); +// [[maybe_unused]] constexpr auto fail = [] { +// InlineString<3> str("abc"); +// return str.erase(4, 2); +// }(); +// #endif // PW_NC_TEST + +// TEST(InlineString, Erase_CharacterAtPosition) { +// TEST_STRING(InlineString<3>(), str.erase(str.begin()), ""); +// TEST_STRING(InlineString<3>(), str.erase(str.end()), ""); +// TEST_STRING(InlineString<3>("abc"), str.erase(str.begin()), "bc"); +// TEST_STRING(InlineString<3>("abc"), str.erase(str.begin() + 1), "ac"); +// TEST_STRING(InlineString<3>("abc"), str.erase(str.begin() + 2), "ab"); +// TEST_STRING(InlineString<3>("abc"), str.erase(str.end()), "abc"); +// } + +// TEST(InlineString, Erase_CharactersInRange) { +// TEST_STRING( +// InlineString<3>("abc"), str.erase(str.begin(), str.begin()), "abc"); +// TEST_STRING(InlineString<3>("abc"), str.erase(str.end(), str.end()), +// "abc"); TEST_STRING(InlineString<3>("abc"), str.erase(str.begin(), +// str.end()), ""); TEST_STRING( +// InlineString<3>("abc"), str.erase(str.begin(), str.begin() + 1), "bc"); +// TEST_STRING( +// InlineString<3>("abc"), str.erase(str.begin() + 1, str.end()), "a"); +// } TEST(InlineString, PushBack) { TEST_STRING(InlineString<1>(), str.push_back('#'), "#"); @@ -1289,7 +1569,7 @@ TEST(InlineString, Append_BasicString) { InlineString<11>("a"), str.append(kSize10Capacity10), "a1234567890"); #if PW_NC_TEST(Append_BasicString_DoesNotFit) - PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - size\(\)\)"); + PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - index"); [[maybe_unused]] constexpr auto fail = [] { InlineString<3> str({0, 1}); return str.append(kSize5Capacity10); @@ -1309,7 +1589,7 @@ TEST(InlineString, Append_Characters) { TEST_STRING(InlineString<6>("Hi"), str.append(4, '!'), "Hi!!!!"); #if PW_NC_TEST(Append_Characters_DoesNotFit) - PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - size\(\)\)"); + PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - index\)"); [[maybe_unused]] constexpr auto fail = [] { InlineString<3> str({0, 1}); return str.append(2, '?'); @@ -1326,7 +1606,7 @@ TEST(InlineString, Append_PointerSize) { TEST_STRING(InlineString<10>("abc"), str.append("1234567", 3), "abc123"); #if PW_NC_TEST(Append_PointerSize_DoesNotFit) - PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - size\(\)\)"); + PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - index"); [[maybe_unused]] constexpr auto fail = [] { InlineString<3> str({0, 1}); return str.append("23", 2); @@ -1360,7 +1640,7 @@ TEST(InlineString, Append_Pointer) { TEST_STRING(InlineString<13>("abc"), str.append(kPointer10), "abc9876543210"); #if PW_NC_TEST(Append_Pointer_DoesNotFit) - PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - size\(\)\)"); + PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - index"); [[maybe_unused]] constexpr auto fail = [] { InlineString<3> str({0, 1}); return str.append(kPointer10 + 8); @@ -1394,7 +1674,7 @@ TEST(InlineString, Append_InitializerList) { TEST_STRING(InlineString<5>("abc"), str.append({'4', '5'}), "abc45"); #if PW_NC_TEST(Append_InitializerList_DoesNotFit) - PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - size\(\)\)"); + PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - index"); [[maybe_unused]] constexpr auto fail = [] { InlineString<3> str({0, 1, 2}); return str.append({3}); @@ -1410,7 +1690,7 @@ TEST(InlineString, Append_StringView) { TEST_STRING(InlineString<5>("abc"), str.append("45"sv), "abc45"); #if PW_NC_TEST(Append_StringView_DoesNotFit) - PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - size\(\)\)"); + PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - index"); [[maybe_unused]] constexpr auto fail = [] { InlineString<3> str({0, 1, 2}); return str.append("3"sv); @@ -1428,7 +1708,7 @@ TEST(InlineString, Append_StringViewSubstr) { TEST_RUNTIME_STRING(InlineString<4>("a"), str.append("123"sv, 3, 99), "a"); #if PW_NC_TEST(Append_StringViewSubstr_DoesNotFit) - PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - size\(\)\)"); + PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - index"); [[maybe_unused]] constexpr auto fail = [] { InlineString<3> str({0, 1, 2}); return str.append("34"sv, 1); @@ -1451,7 +1731,7 @@ TEST(InlineString, AppendOperator_BasicString) { TEST_STRING(InlineString<6>("Hi"), str.append(4, '!'), "Hi!!!!"); #if PW_NC_TEST(AppendOperator_BasicString_DoesNotFit) - PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - size\(\)\)"); + PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - index"); [[maybe_unused]] constexpr auto fail = [] { InlineString<3> str({0, 1}); return str.append(kSize5Capacity10); @@ -1502,7 +1782,7 @@ TEST(InlineString, AppendOperator_Pointer) { InlineString<13>("abc"), fixed_str += kPointer10, "abc9876543210"); #if PW_NC_TEST(AppendOperator_Pointer_DoesNotFit) - PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - size\(\)\)"); + PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - index"); [[maybe_unused]] constexpr auto fail = [] { InlineString<3> str({0, 1}); return str.append(kPointer10 + 8); @@ -1517,7 +1797,7 @@ TEST(InlineString, AppendOperator_InitializerList) { TEST_STRING(InlineString<5>("abc"), (fixed_str += {'4', '5'}), "abc45"); #if PW_NC_TEST(AppendOperator_InitializerList_DoesNotFit) - PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - size\(\)\)"); + PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - index"); [[maybe_unused]] constexpr auto fail = [] { InlineString<3> str({0, 1, 2}); return str.append({3}); @@ -1533,7 +1813,7 @@ TEST(InlineString, AppendOperator_StringView) { TEST_STRING(InlineString<5>("abc"), fixed_str += "45"sv, "abc45"); #if PW_NC_TEST(AppendOperator_StringView_DoesNotFit) - PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - size\(\)\)"); + PW_NC_EXPECT("PW_ASSERT\(count <= max_size\(\) - index"); [[maybe_unused]] constexpr auto fail = [] { InlineString<3> str({0, 1, 2}); return str.append("3"sv); |