diff --git a/src/catch2/catch_stringref.cpp b/src/catch2/catch_stringref.cpp index 3402d1c8..1ae57047 100644 --- a/src/catch2/catch_stringref.cpp +++ b/src/catch2/catch_stringref.cpp @@ -22,17 +22,7 @@ namespace Catch { CATCH_ENFORCE(isNullTerminated(), "Called StringRef::c_str() on a non-null-terminated instance"); return m_start; } - auto StringRef::data() const noexcept -> char const* { - return m_start; - } - auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { - if (start < m_size) { - return StringRef(m_start + start, (std::min)(m_size - start, size)); - } else { - return StringRef(); - } - } auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { return m_size == other.m_size && (std::memcmp( m_start, other.m_start, m_size ) == 0); diff --git a/src/catch2/catch_stringref.h b/src/catch2/catch_stringref.h index 9d5522a5..8ed1e731 100644 --- a/src/catch2/catch_stringref.h +++ b/src/catch2/catch_stringref.h @@ -74,12 +74,21 @@ namespace Catch { public: // substrings and searches // Returns a substring of [start, start + length). - // If start + length > size(), then the substring is [start, size()). + // If start + length > size(), then the substring is [start, start + size()). // If start > size(), then the substring is empty. - auto substr( size_type start, size_type length ) const noexcept -> StringRef; + constexpr StringRef substr(size_type start, size_type length) const noexcept { + if (start < m_size) { + const auto shortened_size = m_size - start; + return StringRef(m_start + start, (shortened_size < length) ? shortened_size : length); + } else { + return StringRef(); + } + } // Returns the current start pointer. May not be null-terminated. - auto data() const noexcept -> char const*; + constexpr char const* data() const noexcept { + return m_start; + } constexpr auto isNullTerminated() const noexcept -> bool { return m_start[m_size] == '\0'; diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index 9dc81ad4..66f75768 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -1193,6 +1193,7 @@ String.tests.cpp:: passed: s.data() == s2.data() for: "hello world! String.tests.cpp:: passed: s.data() == ss.data() for: "hello world!" == "hello world!" String.tests.cpp:: passed: s.substr(s.size() + 1, 123).empty() for: true String.tests.cpp:: passed: std::strcmp(ss.c_str(), "world!") == 0 for: 0 == 0 +String.tests.cpp:: passed: s.substr(1'000'000, 1).empty() for: true String.tests.cpp:: passed: (char*)buffer1 != (char*)buffer2 for: "Hello" != "Hello" String.tests.cpp:: passed: left == right for: Hello == Hello String.tests.cpp:: passed: left != left.substr(0, 3) for: Hello != Hel @@ -1206,11 +1207,20 @@ String.tests.cpp:: passed: stdStr == "a stringref" for: "a stringre String.tests.cpp:: passed: stdStr.size() == sr.size() for: 11 == 11 String.tests.cpp:: passed: stdStr == "a stringref" for: "a stringref" == "a stringref" String.tests.cpp:: passed: stdStr.size() == sr.size() for: 11 == 11 -String.tests.cpp:: passed: with 1 message: 'StringRef{}.size() == 0' -String.tests.cpp:: passed: with 1 message: 'StringRef{ "abc", 3 }.size() == 3' -String.tests.cpp:: passed: with 1 message: 'StringRef{ "abc", 3 }.isNullTerminated()' -String.tests.cpp:: passed: with 1 message: 'StringRef{ "abc", 2 }.size() == 2' -String.tests.cpp:: passed: with 1 message: '!(StringRef{ "abc", 2 }.isNullTerminated())' +String.tests.cpp:: passed: with 1 message: 'empty.size() == 0' +String.tests.cpp:: passed: with 1 message: 'empty.begin() == empty.end()' +String.tests.cpp:: passed: with 1 message: 'stringref.size() == 3' +String.tests.cpp:: passed: with 1 message: 'stringref.isNullTerminated()' +String.tests.cpp:: passed: with 1 message: 'stringref.data() == abc' +String.tests.cpp:: passed: with 1 message: 'stringref.begin() == abc' +String.tests.cpp:: passed: with 1 message: 'stringref.begin() != stringref.end()' +String.tests.cpp:: passed: with 1 message: 'stringref.substr(10, 0).empty()' +String.tests.cpp:: passed: with 1 message: 'stringref.substr(2, 1).data() == abc + 2' +String.tests.cpp:: passed: with 1 message: 'shortened.size() == 2' +String.tests.cpp:: passed: with 1 message: 'shortened.data() == abc' +String.tests.cpp:: passed: with 1 message: 'shortened.begin() != shortened.end()' +String.tests.cpp:: passed: with 1 message: '!(shortened.isNullTerminated())' +String.tests.cpp:: passed: with 1 message: '!(shortened.substr(1, 3).isNullTerminated())' String.tests.cpp:: passed: with 1 message: '!(sr1.empty())' String.tests.cpp:: passed: with 1 message: 'sr1.size() == 3' String.tests.cpp:: passed: with 1 message: 'sr1.isNullTerminated()' diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt index fe6e4f14..d714a7f4 100644 --- a/tests/SelfTest/Baselines/console.std.approved.txt +++ b/tests/SelfTest/Baselines/console.std.approved.txt @@ -1381,5 +1381,5 @@ due to unexpected exception with message: =============================================================================== test cases: 320 | 246 passed | 70 failed | 4 failed as expected -assertions: 1782 | 1630 passed | 131 failed | 21 failed as expected +assertions: 1792 | 1640 passed | 131 failed | 21 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index bba11da2..e6d9c48d 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -8715,6 +8715,19 @@ String.tests.cpp:: PASSED: with expansion: 0 == 0 +------------------------------------------------------------------------------- +StringRef + Substrings + substring start after the end is empty +------------------------------------------------------------------------------- +String.tests.cpp: +............................................................................... + +String.tests.cpp:: PASSED: + REQUIRE( s.substr(1'000'000, 1).empty() ) +with expansion: + true + ------------------------------------------------------------------------------- StringRef Comparisons are deep @@ -8836,23 +8849,59 @@ String.tests.cpp: String.tests.cpp:: PASSED: with message: - StringRef{}.size() == 0 + empty.size() == 0 String.tests.cpp:: PASSED: with message: - StringRef{ "abc", 3 }.size() == 3 + empty.begin() == empty.end() String.tests.cpp:: PASSED: with message: - StringRef{ "abc", 3 }.isNullTerminated() + stringref.size() == 3 String.tests.cpp:: PASSED: with message: - StringRef{ "abc", 2 }.size() == 2 + stringref.isNullTerminated() String.tests.cpp:: PASSED: with message: - !(StringRef{ "abc", 2 }.isNullTerminated()) + stringref.data() == abc + +String.tests.cpp:: PASSED: +with message: + stringref.begin() == abc + +String.tests.cpp:: PASSED: +with message: + stringref.begin() != stringref.end() + +String.tests.cpp:: PASSED: +with message: + stringref.substr(10, 0).empty() + +String.tests.cpp:: PASSED: +with message: + stringref.substr(2, 1).data() == abc + 2 + +String.tests.cpp:: PASSED: +with message: + shortened.size() == 2 + +String.tests.cpp:: PASSED: +with message: + shortened.data() == abc + +String.tests.cpp:: PASSED: +with message: + shortened.begin() != shortened.end() + +String.tests.cpp:: PASSED: +with message: + !(shortened.isNullTerminated()) + +String.tests.cpp:: PASSED: +with message: + !(shortened.substr(1, 3).isNullTerminated()) ------------------------------------------------------------------------------- StringRef at compilation time @@ -14005,5 +14054,5 @@ Misc.tests.cpp:: PASSED: =============================================================================== test cases: 320 | 230 passed | 86 failed | 4 failed as expected -assertions: 1799 | 1630 passed | 148 failed | 21 failed as expected +assertions: 1809 | 1640 passed | 148 failed | 21 failed as expected diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index f2537378..0a3175dc 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -1114,6 +1114,7 @@ Matchers.tests.cpp: + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index fa9e2a57..d359b155 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -142,6 +142,7 @@ + diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index 2b561824..bc0f3c25 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -2300,6 +2300,8 @@ ok {test-number} - s.substr(s.size() + 1, 123).empty() for: true # StringRef ok {test-number} - std::strcmp(ss.c_str(), "world!") == 0 for: 0 == 0 # StringRef +ok {test-number} - s.substr(1'000'000, 1).empty() for: true +# StringRef ok {test-number} - (char*)buffer1 != (char*)buffer2 for: "Hello" != "Hello" # StringRef ok {test-number} - left == right for: Hello == Hello @@ -2326,15 +2328,33 @@ ok {test-number} - stdStr == "a stringref" for: "a stringref" == "a stringref" # StringRef ok {test-number} - stdStr.size() == sr.size() for: 11 == 11 # StringRef at compilation time -ok {test-number} - with 1 message: 'StringRef{}.size() == 0' +ok {test-number} - with 1 message: 'empty.size() == 0' # StringRef at compilation time -ok {test-number} - with 1 message: 'StringRef{ "abc", 3 }.size() == 3' +ok {test-number} - with 1 message: 'empty.begin() == empty.end()' # StringRef at compilation time -ok {test-number} - with 1 message: 'StringRef{ "abc", 3 }.isNullTerminated()' +ok {test-number} - with 1 message: 'stringref.size() == 3' # StringRef at compilation time -ok {test-number} - with 1 message: 'StringRef{ "abc", 2 }.size() == 2' +ok {test-number} - with 1 message: 'stringref.isNullTerminated()' # StringRef at compilation time -ok {test-number} - with 1 message: '!(StringRef{ "abc", 2 }.isNullTerminated())' +ok {test-number} - with 1 message: 'stringref.data() == abc' +# StringRef at compilation time +ok {test-number} - with 1 message: 'stringref.begin() == abc' +# StringRef at compilation time +ok {test-number} - with 1 message: 'stringref.begin() != stringref.end()' +# StringRef at compilation time +ok {test-number} - with 1 message: 'stringref.substr(10, 0).empty()' +# StringRef at compilation time +ok {test-number} - with 1 message: 'stringref.substr(2, 1).data() == abc + 2' +# StringRef at compilation time +ok {test-number} - with 1 message: 'shortened.size() == 2' +# StringRef at compilation time +ok {test-number} - with 1 message: 'shortened.data() == abc' +# StringRef at compilation time +ok {test-number} - with 1 message: 'shortened.begin() != shortened.end()' +# StringRef at compilation time +ok {test-number} - with 1 message: '!(shortened.isNullTerminated())' +# StringRef at compilation time +ok {test-number} - with 1 message: '!(shortened.substr(1, 3).isNullTerminated())' # StringRef at compilation time ok {test-number} - with 1 message: '!(sr1.empty())' # StringRef at compilation time @@ -3590,5 +3610,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..1791 +1..1801 diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index 39122b05..ca1f10e4 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -10906,6 +10906,20 @@ Message from section two +
+
+ + + s.substr(1'000'000, 1).empty() + + + true + + + +
+ +
@@ -11047,7 +11061,7 @@ Message from section two
- +
@@ -16895,7 +16909,7 @@ loose text artifact
- + - + diff --git a/tests/SelfTest/IntrospectiveTests/String.tests.cpp b/tests/SelfTest/IntrospectiveTests/String.tests.cpp index 6b94cdc8..b7f4a2dd 100644 --- a/tests/SelfTest/IntrospectiveTests/String.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/String.tests.cpp @@ -72,7 +72,9 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) { ss = s.substr(6, 123); REQUIRE(std::strcmp(ss.c_str(), "world!") == 0); } - // TODO: substring into string + size is longer than end + SECTION("substring start after the end is empty") { + REQUIRE(s.substr(1'000'000, 1).empty()); + } } SECTION( "Comparisons are deep" ) { @@ -124,15 +126,32 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) { } TEST_CASE("StringRef at compilation time", "[Strings][StringRef][constexpr]") { + //TODO: + // * substr using Catch::StringRef; SECTION("Simple constructors") { - STATIC_REQUIRE(StringRef{}.size() == 0); + constexpr StringRef empty; + STATIC_REQUIRE(empty.size() == 0); + STATIC_REQUIRE(empty.begin() == empty.end()); - STATIC_REQUIRE(StringRef{ "abc", 3 }.size() == 3); - STATIC_REQUIRE(StringRef{ "abc", 3 }.isNullTerminated()); + constexpr char const* const abc = "abc"; - STATIC_REQUIRE(StringRef{ "abc", 2 }.size() == 2); - STATIC_REQUIRE_FALSE(StringRef{ "abc", 2 }.isNullTerminated()); + constexpr StringRef stringref(abc, 3); + STATIC_REQUIRE(stringref.size() == 3); + STATIC_REQUIRE(stringref.isNullTerminated()); + STATIC_REQUIRE(stringref.data() == abc); + STATIC_REQUIRE(stringref.begin() == abc); + STATIC_REQUIRE(stringref.begin() != stringref.end()); + STATIC_REQUIRE(stringref.substr(10, 0).empty()); + STATIC_REQUIRE(stringref.substr(2, 1).data() == abc + 2); + + + constexpr StringRef shortened(abc, 2); + STATIC_REQUIRE(shortened.size() == 2); + STATIC_REQUIRE(shortened.data() == abc); + STATIC_REQUIRE(shortened.begin() != shortened.end()); + STATIC_REQUIRE_FALSE(shortened.isNullTerminated()); + STATIC_REQUIRE_FALSE(shortened.substr(1, 3).isNullTerminated()); } SECTION("UDL construction") { constexpr auto sr1 = "abc"_catch_sr;