aboutsummaryrefslogtreecommitdiff
path: root/pw_string
diff options
context:
space:
mode:
authoraarongreen <aarongreen@google.com>2023-05-30 16:58:31 +0000
committerCQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-05-30 16:58:31 +0000
commit0afc2d5743f9af77d5c8007f5b8720370b3e3ac9 (patch)
tree714739cc77253395e5cbd536ffd7bb220ff8e336 /pw_string
parent255ab6106000d8d698ed61105bb40b11eecdaf6e (diff)
downloadpigweed-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.inc165
-rw-r--r--pw_string/public/pw_string/internal/string_impl.h50
-rw-r--r--pw_string/public/pw_string/string.h146
-rw-r--r--pw_string/string_test.cc308
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);