aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakePresets.json8
-rw-r--r--libs/kstd/kstd/bits/basic_string.hpp43
-rw-r--r--libs/kstd/kstd/string.test.cpp304
3 files changed, 354 insertions, 1 deletions
diff --git a/CMakePresets.json b/CMakePresets.json
index 0e5dd88c..0e70d1a9 100644
--- a/CMakePresets.json
+++ b/CMakePresets.json
@@ -47,7 +47,13 @@
"testPresets": [
{
"name": "bht-dbg",
- "configurePreset": "bht"
+ "configurePreset": "bht",
+ "output": {
+ "outputOnFailure": true
+ },
+ "execution": {
+ "jobs": 0
+ }
}
]
} \ No newline at end of file
diff --git a/libs/kstd/kstd/bits/basic_string.hpp b/libs/kstd/kstd/bits/basic_string.hpp
index 5d2eecd7..0509e33a 100644
--- a/libs/kstd/kstd/bits/basic_string.hpp
+++ b/libs/kstd/kstd/bits/basic_string.hpp
@@ -734,6 +734,7 @@ namespace kstd
//!
//! @param index The position to insert the data at.
//! @param string The string to insert.
+ //! @return A reference to this string.
constexpr auto insert(size_type index, CharacterType const * string) -> basic_string &
{
if (string == nullptr)
@@ -744,6 +745,48 @@ namespace kstd
return do_insert(index, std::basic_string_view<value_type, traits_type>{string});
}
+ //! Insert the characters in the range [string, string + length) into this string at a given position.
+ //!
+ //! The inserted range may contain null characters.
+ //!
+ //! @param index The position to insert the data at.
+ //! @param range The pointer to the first character of the range.
+ //! @param length The length of the range.
+ //! @return A reference to this string.
+ constexpr auto insert(size_type index, CharacterType const * range, size_type length) -> basic_string &
+ {
+ if (range == nullptr)
+ {
+ os::panic("Tried to insert nullptr range");
+ }
+
+ return do_insert(index, std::basic_string_view<value_type, traits_type>{range, length});
+ }
+
+ //! Insert a given string into this string at a given position.
+ //!
+ //! @param index The position to insert the data at.
+ //! @param string The string to insert.
+ //! @return A reference to this string.
+ constexpr auto insert(size_type index, basic_string const & string) -> basic_string &
+ {
+ return do_insert(index, static_cast<std::basic_string_view<value_type, traits_type>>(string));
+ }
+
+ //! Insert the elements of a string view like object at a given position.
+ //!
+ //! @param index The position to insert the data at.
+ //! @param view_like The string view like object.
+ //! @return A reference to this string.
+ template<typename StringViewLike>
+ requires(std::is_convertible_v<StringViewLike const &, std::basic_string_view<CharacterType, Traits>> &&
+ !std::is_convertible_v<StringViewLike const &, CharacterType const *>)
+ constexpr auto insert(size_type index, StringViewLike const & view_like) -> basic_string &
+ {
+ auto view = static_cast<std::basic_string_view<CharacterType, Traits>>(view_like);
+ return do_insert(index, view);
+ }
+
//! Append a character to this string.
//!
//! @param character The character to append.
diff --git a/libs/kstd/kstd/string.test.cpp b/libs/kstd/kstd/string.test.cpp
index 19345e09..74be1f0b 100644
--- a/libs/kstd/kstd/string.test.cpp
+++ b/libs/kstd/kstd/string.test.cpp
@@ -2152,6 +2152,310 @@ SCENARIO("String modifiers", "[string]")
}
}
+SCENARIO("String insertion", "[string]")
+{
+ GIVEN("A short string")
+ {
+ auto s = kstd::string{"abcd"};
+ auto old_capacity = s.capacity();
+ auto old_size = s.size();
+
+ WHEN("inserting five copies of a character at the beginning")
+ {
+ s.insert(0, 5, 'A');
+
+ THEN("the size of the string is increased by 5")
+ {
+ REQUIRE(s.size() == old_size + 5);
+ }
+
+ THEN("The capacity of the string stays the same")
+ {
+ REQUIRE(s.capacity() == old_capacity);
+ }
+
+ THEN("The string is equal to the old string with the new characters prepended")
+ {
+ REQUIRE(s == kstd::string{"AAAAAabcd"});
+ }
+ }
+
+ WHEN("inserting five copies of a character in the middle")
+ {
+ s.insert(2, 5, 'A');
+
+ THEN("the size of the string is increased by 5")
+ {
+ REQUIRE(s.size() == old_size + 5);
+ }
+
+ THEN("The capacity of the string stays the same")
+ {
+ REQUIRE(s.capacity() == old_capacity);
+ }
+
+ THEN("The string is equal to the old string with the new characters inserted")
+ {
+ REQUIRE(s == kstd::string{"abAAAAAcd"});
+ }
+ }
+
+ WHEN("inserting five copies of a character at the end")
+ {
+ s.insert(4, 5, 'A');
+
+ THEN("the size of the string is increased by 5")
+ {
+ REQUIRE(s.size() == old_size + 5);
+ }
+
+ THEN("The capacity of the string stays the same")
+ {
+ REQUIRE(s.capacity() == old_capacity);
+ }
+
+ THEN("The string is equal to the old string with the new characters appended")
+ {
+ REQUIRE(s == kstd::string{"abcdAAAAA"});
+ }
+ }
+
+ WHEN("inserting five copies of a character behind the end")
+ {
+ THEN("an OS panic is triggered")
+ {
+ REQUIRE_THROWS_AS(s.insert(5, 5, 'A'), kstd::tests::os_panic);
+ }
+ }
+
+ WHEN("inserting 20 copies of a character")
+ {
+ s.insert(2, 20, 'A');
+
+ THEN("the capacity of the string grows")
+ {
+ REQUIRE(s.capacity() > old_capacity);
+ }
+
+ THEN("the string is equal t o the old string with the new characters inserted")
+ {
+ REQUIRE(s == kstd::string{"abAAAAAAAAAAAAAAAAAAAAcd"});
+ }
+ }
+
+ WHEN("inserting a C-style string of length 5 at the beginning")
+ {
+ s.insert(0, "AAAAA");
+
+ THEN("the size of the string is increased by 5")
+ {
+ REQUIRE(s.size() == old_size + 5);
+ }
+
+ THEN("The capacity of the string stays the same")
+ {
+ REQUIRE(s.capacity() == old_capacity);
+ }
+
+ THEN("The string is equal to the old string with the new characters prepended")
+ {
+ REQUIRE(s == kstd::string{"AAAAAabcd"});
+ }
+ }
+
+ WHEN("inserting a C-style string of length 5 in the middle")
+ {
+ s.insert(2, "AAAAA");
+
+ THEN("the size of the string is increased by 5")
+ {
+ REQUIRE(s.size() == old_size + 5);
+ }
+
+ THEN("The capacity of the string stays the same")
+ {
+ REQUIRE(s.capacity() == old_capacity);
+ }
+
+ THEN("The string is equal to the old string with the new characters inserted")
+ {
+ REQUIRE(s == kstd::string{"abAAAAAcd"});
+ }
+ }
+
+ WHEN("inserting a C-style string of length 5 at the end")
+ {
+ s.insert(4, "AAAAA");
+
+ THEN("the size of the string is increased by 5")
+ {
+ REQUIRE(s.size() == old_size + 5);
+ }
+
+ THEN("The capacity of the string stays the same")
+ {
+ REQUIRE(s.capacity() == old_capacity);
+ }
+
+ THEN("The string is equal to the old string with the new characters appended")
+ {
+ REQUIRE(s == kstd::string{"abcdAAAAA"});
+ }
+ }
+
+ WHEN("inserting a C-style string of length 5 behind the end")
+ {
+ THEN("an OS panic is triggered")
+ {
+ REQUIRE_THROWS_AS(s.insert(5, "AAAAA"), kstd::tests::os_panic);
+ }
+ }
+ }
+
+ GIVEN("A long string")
+ {
+ auto s = kstd::string{"abcdefghijABCDEFGHIJ"};
+ auto old_capacity = s.capacity();
+ auto old_size = s.size();
+
+ WHEN("inserting five copies of a character at the beginning")
+ {
+ s.insert(0, 5, 'A');
+
+ THEN("the size of the string is increased by 5")
+ {
+ REQUIRE(s.size() == old_size + 5);
+ }
+
+ THEN("The capacity of the string increases")
+ {
+ REQUIRE(s.capacity() >= old_capacity + 5);
+ }
+
+ THEN("The string is equal to the old string with the new characters prepended")
+ {
+ REQUIRE(s == kstd::string{"AAAAAabcdefghijABCDEFGHIJ"});
+ }
+ }
+
+ WHEN("inserting five copies of a character in the middle")
+ {
+ s.insert(10, 5, 'A');
+
+ THEN("the size of the string is increased by 5")
+ {
+ REQUIRE(s.size() == old_size + 5);
+ }
+
+ THEN("The capacity of the string increases")
+ {
+ REQUIRE(s.capacity() >= old_capacity + 5);
+ }
+
+ THEN("The string is equal to the old string with the new characters inserted")
+ {
+ REQUIRE(s == kstd::string{"abcdefghijAAAAAABCDEFGHIJ"});
+ }
+ }
+
+ WHEN("inserting five copies of a character at the end")
+ {
+ s.insert(20, 5, 'A');
+
+ THEN("the size of the string is increased by 5")
+ {
+ REQUIRE(s.size() == old_size + 5);
+ }
+
+ THEN("The capacity of the string increases")
+ {
+ REQUIRE(s.capacity() >= old_capacity + 5);
+ }
+
+ THEN("The string is equal to the old string with the new characters appended")
+ {
+ REQUIRE(s == kstd::string{"abcdefghijABCDEFGHIJAAAAA"});
+ }
+ }
+
+ WHEN("inserting five copies of a character behind the end")
+ {
+ THEN("an OS panic is triggered")
+ {
+ REQUIRE_THROWS_AS(s.insert(21, 5, 'A'), kstd::tests::os_panic);
+ }
+ }
+
+ WHEN("inserting a C-style string of length 5 at the beginning")
+ {
+ s.insert(0, "AAAAA");
+
+ THEN("the size of the string is increased by 5")
+ {
+ REQUIRE(s.size() == old_size + 5);
+ }
+
+ THEN("The capacity of the string increases")
+ {
+ REQUIRE(s.capacity() >= old_capacity + 5);
+ }
+
+ THEN("The string is equal to the old string with the new characters prepended")
+ {
+ REQUIRE(s == kstd::string{"AAAAAabcdefghijABCDEFGHIJ"});
+ }
+ }
+
+ WHEN("inserting a C-style string of length 5 in the middle")
+ {
+ s.insert(10, "AAAAA");
+
+ THEN("the size of the string is increased by 5")
+ {
+ REQUIRE(s.size() == old_size + 5);
+ }
+
+ THEN("The capacity of the string increases")
+ {
+ REQUIRE(s.capacity() >= old_capacity + 5);
+ }
+
+ THEN("The string is equal to the old string with the new characters inserted")
+ {
+ REQUIRE(s == kstd::string{"abcdefghijAAAAAABCDEFGHIJ"});
+ }
+ }
+
+ WHEN("inserting a C-style string of length 5 at the end")
+ {
+ s.insert(20, "AAAAA");
+
+ THEN("the size of the string is increased by 5")
+ {
+ REQUIRE(s.size() == old_size + 5);
+ }
+
+ THEN("The capacity of the increases")
+ {
+ REQUIRE(s.capacity() >= old_capacity + 5);
+ }
+
+ THEN("The string is equal to the old string with the new characters appended")
+ {
+ REQUIRE(s == kstd::string{"abcdefghijABCDEFGHIJAAAAA"});
+ }
+ }
+
+ WHEN("inserting a C-style string of length 5 behind the end")
+ {
+ THEN("an OS panic is triggered")
+ {
+ REQUIRE_THROWS_AS(s.insert(21, "AAAAA"), kstd::tests::os_panic);
+ }
+ }
+ }
+}
+
SCENARIO("String concatenation", "[string]")
{
GIVEN("Two strings")