diff --git a/include/fixed_containers/fixed_string.hpp b/include/fixed_containers/fixed_string.hpp index 11f808dc..a6059538 100644 --- a/include/fixed_containers/fixed_string.hpp +++ b/include/fixed_containers/fixed_string.hpp @@ -88,6 +88,16 @@ class FixedString using reverse_iterator = typename FixedVecStorage::reverse_iterator; using const_reverse_iterator = typename FixedVecStorage::const_reverse_iterator; +private: + static constexpr void check_target_length(size_type target_length, + const std_transition::source_location& loc) + { + if (preconditions::test(target_length <= MAXIMUM_LENGTH)) + { + Checking::length_error(target_length, loc); + } + } + public: // Public so this type is a structural type and can thus be used in template parameters FixedVecStorage IMPLEMENTATION_DETAIL_DO_NOT_USE_data_; @@ -445,6 +455,29 @@ class FixedString return std::string_view(*this).substr(pos, len); } + constexpr void resize( + size_type count, + const std_transition::source_location& loc = std_transition::source_location::current()) + { + resize(count, CharT{}, loc); + } + + constexpr void resize( + size_type count, + CharT ch, + const std_transition::source_location& loc = std_transition::source_location::current()) + { + if (ch == CharT{} && count > length()) + { + // Before `count` is shrinked, ensure it is not too big + check_target_length(count, loc); + count = length(); + } + + vec().resize(count, ch, loc); + null_terminate(loc); + } + private: constexpr void null_terminate(std::size_t n) { diff --git a/test/fixed_string_test.cpp b/test/fixed_string_test.cpp index aacb50e6..dbaf4272 100644 --- a/test/fixed_string_test.cpp +++ b/test/fixed_string_test.cpp @@ -1406,4 +1406,59 @@ TEST(FixedString, Substring) EXPECT_DEATH((void)v1.substr(5, 1), ""); } +TEST(FixedString, Resize) +{ + constexpr auto v1 = []() + { + FixedString<7> v{"012"}; + v.resize(6); // This won't add extra null-terminators + return v; + }(); + + static_assert(v1[0] == '0'); + static_assert(v1[1] == '1'); + static_assert(v1[2] == '2'); + static_assert(v1.size() == 3); + static_assert(v1.max_size() == 7); + + constexpr auto v2 = []() + { + FixedString<7> v{"012"}; + v.resize(7, 'c'); + v[4] = 'x'; + v.resize(5, 'e'); + return v; + }(); + + static_assert(v2[0] == '0'); + static_assert(v2[1] == '1'); + static_assert(v2[2] == '2'); + static_assert(v2[3] == 'c'); + static_assert(v2[4] == 'x'); + static_assert(v2.size() == 5); + static_assert(v2.max_size() == 7); + + FixedString<8> v3{"0123"}; + v3.resize(6); // This won't add extra null-terminators + + EXPECT_EQ(v3, "0123"); + + v3.resize(2); + EXPECT_EQ(v3, "01"); + + v3.resize(5, '3'); + + EXPECT_EQ(v3, "01333"); +} + +TEST(FixedString, Resize_ExceedCapacity) +{ + FixedString<3> v1{}; + EXPECT_DEATH(v1.resize(6), ""); + EXPECT_DEATH(v1.resize(6, 5), ""); + const size_t to_size = 7; + EXPECT_DEATH(v1.resize(to_size), ""); + EXPECT_DEATH(v1.resize(to_size, 5), ""); +} + } // namespace fixed_containers