From 9ca61638348c1e37f75cbad3f7edd9664b01ecf0 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Sat, 17 Feb 2024 16:54:19 +0800 Subject: [PATCH] sstring: implement push_back() to be more compatible with basic_string<> this is also what we expect from a sequence-alike STL containers. Fixes #2104 Signed-off-by: Kefu Chai --- include/seastar/core/sstring.hh | 23 +++++++++++++++++++++++ tests/unit/sstring_test.cc | 21 +++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/seastar/core/sstring.hh b/include/seastar/core/sstring.hh index ff352294cc0..3f7d4a09860 100644 --- a/include/seastar/core/sstring.hh +++ b/include/seastar/core/sstring.hh @@ -346,6 +346,29 @@ public: return *this; } + /** + * Append the given character to the end of the string + * @param ch The character to append + * @note unlike @c std::basic_string, sstring does not preallocate, so + * this call always lead to reallocation if external storage is + * used. + */ + constexpr void push_back(char_type ch) { + if (is_internal()) { + if (static_cast(u.internal.size) < max_size) { + u.internal.str[u.internal.size++] = ch; + if (NulTerminate) { + u.internal.str[u.internal.size] = '\0'; + } + return; + } + } + basic_sstring new_str(initialized_later(), u.external.size + 1); + std::copy(begin(), end(), new_str.begin()); + new_str.u.external.str[new_str.u.external.size - 1] = ch; + *this = std::move(new_str); + } + /** * Resize string and use the specified @c op to modify the content and the length * @param n new size diff --git a/tests/unit/sstring_test.cc b/tests/unit/sstring_test.cc index 210d57882a0..649031a1b0b 100644 --- a/tests/unit/sstring_test.cc +++ b/tests/unit/sstring_test.cc @@ -199,6 +199,27 @@ BOOST_AUTO_TEST_CASE(test_append) { BOOST_REQUIRE_EQUAL(sstring("aba").append("1234", 0), "aba"); } +BOOST_AUTO_TEST_CASE(test_push_back) { + { + // append in internal storage + basic_sstring s("0123456789"); + s.push_back('a'); + BOOST_REQUIRE_EQUAL(s, "0123456789a"); + } + { + // append causing spilling to external storage + basic_sstring s("0123456789abcde"); + s.push_back('f'); + BOOST_REQUIRE_EQUAL(s, "0123456789abcdef"); + } + { + // append with external storage + basic_sstring s("0123456789abcdef"); + s.push_back('g'); + BOOST_REQUIRE_EQUAL(s, "0123456789abcdefg"); + } +} + BOOST_AUTO_TEST_CASE(test_replace) { BOOST_REQUIRE_EQUAL(sstring("abc").replace(1,1, "xyz", 1), "axc"); BOOST_REQUIRE_EQUAL(sstring("abc").replace(3,2, "xyz", 2), "abcxy");