diff --git a/src/catch2/internal/catch_string_manip.cpp b/src/catch2/internal/catch_string_manip.cpp index 0c889ca181..f9aa7bfe2b 100644 --- a/src/catch2/internal/catch_string_manip.cpp +++ b/src/catch2/internal/catch_string_manip.cpp @@ -5,6 +5,7 @@ // https://www.boost.org/LICENSE_1_0.txt) // SPDX-License-Identifier: BSL-1.0 +#include #include #include @@ -65,17 +66,26 @@ namespace Catch { } bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { - bool replaced = false; std::size_t i = str.find( replaceThis ); - while( i != std::string::npos ) { - replaced = true; - str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); - if( i < str.size()-withThis.size() ) - i = str.find( replaceThis, i+withThis.size() ); + if (i == std::string::npos) { + return false; + } + std::size_t copyBegin = 0; + std::string origStr = CATCH_MOVE(str); + str.clear(); + do { + str.append(origStr, copyBegin, i-copyBegin ); + str += withThis; + copyBegin = i + replaceThis.size(); + if( copyBegin < origStr.size() ) + i = origStr.find( replaceThis, copyBegin ); else i = std::string::npos; + } while( i != std::string::npos ); + if ( copyBegin < origStr.size() ) { + str.append(origStr, copyBegin, origStr.size() ); } - return replaced; + return true; } std::vector splitStringRef( StringRef str, char delimiter ) { diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index b868e7a933..b55625bdd2 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -2483,6 +2483,10 @@ StringManip.tests.cpp:: passed: Catch::replaceInPlace(letters, lett StringManip.tests.cpp:: passed: letters == "replaced" for: "replaced" == "replaced" StringManip.tests.cpp:: passed: !(Catch::replaceInPlace(letters, "x", "z")) for: !false StringManip.tests.cpp:: passed: letters == letters for: "abcdefcg" == "abcdefcg" +StringManip.tests.cpp:: passed: Catch::replaceInPlace(letters, "c", "cc") for: true +StringManip.tests.cpp:: passed: letters == "abccdefccg" for: "abccdefccg" == "abccdefccg" +StringManip.tests.cpp:: passed: Catch::replaceInPlace(s, "--", "-") for: true +StringManip.tests.cpp:: passed: s == "--" for: "--" == "--" StringManip.tests.cpp:: passed: Catch::replaceInPlace(s, "'", "|'") for: true StringManip.tests.cpp:: passed: s == "didn|'t" for: "didn|'t" == "didn|'t" Stream.tests.cpp:: passed: Catch::makeStream( "%somestream" ) @@ -2690,6 +2694,6 @@ InternalBenchmark.tests.cpp:: passed: q3 == 23. for: 23.0 == 23.0 Misc.tests.cpp:: passed: Misc.tests.cpp:: passed: test cases: 417 | 312 passed | 85 failed | 6 skipped | 14 failed as expected -assertions: 2260 | 2079 passed | 146 failed | 35 failed as expected +assertions: 2264 | 2083 passed | 146 failed | 35 failed as expected diff --git a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt index 591feaf7d5..7e4fff9c3b 100644 --- a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt @@ -2472,6 +2472,10 @@ StringManip.tests.cpp:: passed: Catch::replaceInPlace(letters, lett StringManip.tests.cpp:: passed: letters == "replaced" for: "replaced" == "replaced" StringManip.tests.cpp:: passed: !(Catch::replaceInPlace(letters, "x", "z")) for: !false StringManip.tests.cpp:: passed: letters == letters for: "abcdefcg" == "abcdefcg" +StringManip.tests.cpp:: passed: Catch::replaceInPlace(letters, "c", "cc") for: true +StringManip.tests.cpp:: passed: letters == "abccdefccg" for: "abccdefccg" == "abccdefccg" +StringManip.tests.cpp:: passed: Catch::replaceInPlace(s, "--", "-") for: true +StringManip.tests.cpp:: passed: s == "--" for: "--" == "--" StringManip.tests.cpp:: passed: Catch::replaceInPlace(s, "'", "|'") for: true StringManip.tests.cpp:: passed: s == "didn|'t" for: "didn|'t" == "didn|'t" Stream.tests.cpp:: passed: Catch::makeStream( "%somestream" ) @@ -2679,6 +2683,6 @@ InternalBenchmark.tests.cpp:: passed: q3 == 23. for: 23.0 == 23.0 Misc.tests.cpp:: passed: Misc.tests.cpp:: passed: test cases: 417 | 312 passed | 85 failed | 6 skipped | 14 failed as expected -assertions: 2260 | 2079 passed | 146 failed | 35 failed as expected +assertions: 2264 | 2083 passed | 146 failed | 35 failed as expected diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt index 2542625656..075f2824b7 100644 --- a/tests/SelfTest/Baselines/console.std.approved.txt +++ b/tests/SelfTest/Baselines/console.std.approved.txt @@ -1589,5 +1589,5 @@ due to unexpected exception with message: =============================================================================== test cases: 417 | 326 passed | 70 failed | 7 skipped | 14 failed as expected -assertions: 2243 | 2079 passed | 129 failed | 35 failed as expected +assertions: 2247 | 2083 passed | 129 failed | 35 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index a718f5170c..6cde749eff 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -17309,6 +17309,42 @@ StringManip.tests.cpp:: PASSED: with expansion: "abcdefcg" == "abcdefcg" +------------------------------------------------------------------------------- +replaceInPlace + no replace in already-replaced string + lengthening +------------------------------------------------------------------------------- +StringManip.tests.cpp: +............................................................................... + +StringManip.tests.cpp:: PASSED: + CHECK( Catch::replaceInPlace(letters, "c", "cc") ) +with expansion: + true + +StringManip.tests.cpp:: PASSED: + CHECK( letters == "abccdefccg" ) +with expansion: + "abccdefccg" == "abccdefccg" + +------------------------------------------------------------------------------- +replaceInPlace + no replace in already-replaced string + shortening +------------------------------------------------------------------------------- +StringManip.tests.cpp: +............................................................................... + +StringManip.tests.cpp:: PASSED: + CHECK( Catch::replaceInPlace(s, "--", "-") ) +with expansion: + true + +StringManip.tests.cpp:: PASSED: + CHECK( s == "--" ) +with expansion: + "--" == "--" + ------------------------------------------------------------------------------- replaceInPlace escape ' @@ -18752,5 +18788,5 @@ Misc.tests.cpp:: PASSED: =============================================================================== test cases: 417 | 312 passed | 85 failed | 6 skipped | 14 failed as expected -assertions: 2260 | 2079 passed | 146 failed | 35 failed as expected +assertions: 2264 | 2083 passed | 146 failed | 35 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.multi.approved.txt b/tests/SelfTest/Baselines/console.sw.multi.approved.txt index 751f08ad9a..7b8fb50505 100644 --- a/tests/SelfTest/Baselines/console.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.multi.approved.txt @@ -17298,6 +17298,42 @@ StringManip.tests.cpp:: PASSED: with expansion: "abcdefcg" == "abcdefcg" +------------------------------------------------------------------------------- +replaceInPlace + no replace in already-replaced string + lengthening +------------------------------------------------------------------------------- +StringManip.tests.cpp: +............................................................................... + +StringManip.tests.cpp:: PASSED: + CHECK( Catch::replaceInPlace(letters, "c", "cc") ) +with expansion: + true + +StringManip.tests.cpp:: PASSED: + CHECK( letters == "abccdefccg" ) +with expansion: + "abccdefccg" == "abccdefccg" + +------------------------------------------------------------------------------- +replaceInPlace + no replace in already-replaced string + shortening +------------------------------------------------------------------------------- +StringManip.tests.cpp: +............................................................................... + +StringManip.tests.cpp:: PASSED: + CHECK( Catch::replaceInPlace(s, "--", "-") ) +with expansion: + true + +StringManip.tests.cpp:: PASSED: + CHECK( s == "--" ) +with expansion: + "--" == "--" + ------------------------------------------------------------------------------- replaceInPlace escape ' @@ -18741,5 +18777,5 @@ Misc.tests.cpp:: PASSED: =============================================================================== test cases: 417 | 312 passed | 85 failed | 6 skipped | 14 failed as expected -assertions: 2260 | 2079 passed | 146 failed | 35 failed as expected +assertions: 2264 | 2083 passed | 146 failed | 35 failed as expected diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index 48eccfc3d1..c17e5a6eb3 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -1966,6 +1966,8 @@ at Message.tests.cpp: + + diff --git a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt index d270c88fb6..375abaa389 100644 --- a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt @@ -1,6 +1,6 @@ - + @@ -1965,6 +1965,8 @@ at Message.tests.cpp: + + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index 36b05e54dc..3db09ec09f 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -262,6 +262,8 @@ at AssertionHandler.tests.cpp: + + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt index c9d3d205bb..f5305eb336 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt @@ -261,6 +261,8 @@ at AssertionHandler.tests.cpp: + + diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index d02a48881b..e5feb41b7e 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -4206,6 +4206,14 @@ ok {test-number} - !(Catch::replaceInPlace(letters, "x", "z")) for: !false # replaceInPlace ok {test-number} - letters == letters for: "abcdefcg" == "abcdefcg" # replaceInPlace +ok {test-number} - Catch::replaceInPlace(letters, "c", "cc") for: true +# replaceInPlace +ok {test-number} - letters == "abccdefccg" for: "abccdefccg" == "abccdefccg" +# replaceInPlace +ok {test-number} - Catch::replaceInPlace(s, "--", "-") for: true +# replaceInPlace +ok {test-number} - s == "--" for: "--" == "--" +# replaceInPlace ok {test-number} - Catch::replaceInPlace(s, "'", "|'") for: true # replaceInPlace ok {test-number} - s == "didn|'t" for: "didn|'t" == "didn|'t" @@ -4549,5 +4557,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2272 +1..2276 diff --git a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt index 40a5860a67..a064c2b64e 100644 --- a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt @@ -4195,6 +4195,14 @@ ok {test-number} - !(Catch::replaceInPlace(letters, "x", "z")) for: !false # replaceInPlace ok {test-number} - letters == letters for: "abcdefcg" == "abcdefcg" # replaceInPlace +ok {test-number} - Catch::replaceInPlace(letters, "c", "cc") for: true +# replaceInPlace +ok {test-number} - letters == "abccdefccg" for: "abccdefccg" == "abccdefccg" +# replaceInPlace +ok {test-number} - Catch::replaceInPlace(s, "--", "-") for: true +# replaceInPlace +ok {test-number} - s == "--" for: "--" == "--" +# replaceInPlace ok {test-number} - Catch::replaceInPlace(s, "'", "|'") for: true # replaceInPlace ok {test-number} - s == "didn|'t" for: "didn|'t" == "didn|'t" @@ -4538,5 +4546,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2272 +1..2276 diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index 0f2db4286f..8e79dc4797 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -20066,6 +20066,50 @@ b1! +
+
+ + + Catch::replaceInPlace(letters, "c", "cc") + + + true + + + + + letters == "abccdefccg" + + + "abccdefccg" == "abccdefccg" + + + +
+ +
+
+
+ + + Catch::replaceInPlace(s, "--", "-") + + + true + + + + + s == "--" + + + "--" == "--" + + + +
+ +
@@ -21707,6 +21751,6 @@ b1!
- + diff --git a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt index b651b439f8..79281bc001 100644 --- a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt @@ -20065,6 +20065,50 @@ b1! +
+
+ + + Catch::replaceInPlace(letters, "c", "cc") + + + true + + + + + letters == "abccdefccg" + + + "abccdefccg" == "abccdefccg" + + + +
+ +
+
+
+ + + Catch::replaceInPlace(s, "--", "-") + + + true + + + + + s == "--" + + + "--" == "--" + + + +
+ +
@@ -21706,6 +21750,6 @@ b1!
- + diff --git a/tests/SelfTest/IntrospectiveTests/StringManip.tests.cpp b/tests/SelfTest/IntrospectiveTests/StringManip.tests.cpp index 36554ddc3b..f30573cc5c 100644 --- a/tests/SelfTest/IntrospectiveTests/StringManip.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/StringManip.tests.cpp @@ -57,6 +57,17 @@ TEST_CASE("replaceInPlace", "[string-manip]") { CHECK_FALSE(Catch::replaceInPlace(letters, "x", "z")); CHECK(letters == letters); } + SECTION("no replace in already-replaced string") { + SECTION("lengthening") { + CHECK(Catch::replaceInPlace(letters, "c", "cc")); + CHECK(letters == "abccdefccg"); + } + SECTION("shortening") { + std::string s = "----"; + CHECK(Catch::replaceInPlace(s, "--", "-")); + CHECK(s == "--"); + } + } SECTION("escape '") { std::string s = "didn't"; CHECK(Catch::replaceInPlace(s, "'", "|'"));