diff options
| -rw-r--r-- | CMakePresets.json | 8 | ||||
| -rw-r--r-- | libs/kstd/kstd/bits/basic_string.hpp | 43 | ||||
| -rw-r--r-- | libs/kstd/kstd/string.test.cpp | 304 |
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") |
