From 05cd05743a75caeffbd6ad4c675ac68bc8e270f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 28 Feb 2018 22:05:01 +0100 Subject: [PATCH] Provide a public method to get StringRef's underlying pointer This allows reducing the amount of friends needed for its interface and some extra tricks later. The bad part is that the pointer can become invalidated via calls to other StringRef's public methods, but c'est la vie. --- include/internal/catch_stringref.cpp | 6 +++--- include/internal/catch_stringref.h | 12 +++++++----- .../SelfTest/Baselines/compact.sw.approved.txt | 4 ++-- .../SelfTest/Baselines/console.sw.approved.txt | 4 ++-- projects/SelfTest/Baselines/xml.sw.approved.txt | 4 ++-- .../IntrospectiveTests/String.tests.cpp | 17 +++++------------ 6 files changed, 21 insertions(+), 26 deletions(-) diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index 46b25039..9e9095e4 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -43,7 +43,7 @@ namespace Catch { const_cast( this )->takeOwnership(); return m_start; } - auto StringRef::data() const noexcept -> char const* { + auto StringRef::currentData() const noexcept -> char const* { return m_start; } @@ -112,11 +112,11 @@ namespace Catch { } auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { - return os.write(str.m_start, str.m_size); + return os.write(str.currentData(), str.size()); } auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& { - lhs.append(rhs.m_start, rhs.m_size); + lhs.append(rhs.currentData(), rhs.size()); return lhs; } diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h index beee2637..757d70cc 100644 --- a/include/internal/catch_stringref.h +++ b/include/internal/catch_stringref.h @@ -84,16 +84,12 @@ namespace Catch { void swap( StringRef& other ) noexcept; - friend auto operator << (std::ostream& os, StringRef const& sr)->std::ostream&; - public: // operators auto operator == ( StringRef const& other ) const noexcept -> bool; auto operator != ( StringRef const& other ) const noexcept -> bool; auto operator[] ( size_type index ) const noexcept -> char; - friend auto operator += ( std::string& lhs, StringRef const& rhs ) -> std::string&; - public: // named queries auto empty() const noexcept -> bool { return m_size == 0; @@ -108,16 +104,22 @@ namespace Catch { public: // substrings and searches auto substr( size_type start, size_type size ) const noexcept -> StringRef; + // Returns the current start pointer. + // Note that the pointer can change when if the StringRef is a substring + auto currentData() const noexcept -> char const*; + private: // ownership queries - may not be consistent between calls auto isOwned() const noexcept -> bool; auto isSubstring() const noexcept -> bool; - auto data() const noexcept -> char const*; }; auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; + auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; + inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { return StringRef( rawChars, size ); diff --git a/projects/SelfTest/Baselines/compact.sw.approved.txt b/projects/SelfTest/Baselines/compact.sw.approved.txt index 2cbed817..a4f85a68 100644 --- a/projects/SelfTest/Baselines/compact.sw.approved.txt +++ b/projects/SelfTest/Baselines/compact.sw.approved.txt @@ -637,11 +637,11 @@ String.tests.cpp:: passed: std::strcmp( ss.c_str(), "hello" ) == 0 String.tests.cpp:: passed: ss == "hello" for: hello == "hello" String.tests.cpp:: passed: isSubstring( ss ) for: true String.tests.cpp:: passed: isOwned( ss ) == false for: false == false -String.tests.cpp:: passed: rawChars == data( s ) for: "hello world!" == "hello world!" +String.tests.cpp:: passed: rawChars == s.currentData() for: "hello world!" == "hello world!" String.tests.cpp:: passed: ss.c_str() != rawChars for: "hello" != "hello world!" String.tests.cpp:: passed: isSubstring( ss ) == false for: false == false String.tests.cpp:: passed: isOwned( ss ) for: true -String.tests.cpp:: passed: data( ss ) != data( s ) for: "hello" != "hello world!" +String.tests.cpp:: passed: ss.currentData() != s.currentData() for: "hello" != "hello world!" String.tests.cpp:: passed: ss.size() == 6 for: 6 == 6 String.tests.cpp:: passed: std::strcmp( ss.c_str(), "world!" ) == 0 for: 0 == 0 String.tests.cpp:: passed: s.c_str() == s2.c_str() for: "hello world!" == "hello world!" diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index dd81bad9..9c738463 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -5076,7 +5076,7 @@ with expansion: String.tests.cpp:: PASSED: - REQUIRE( rawChars == data( s ) ) + REQUIRE( rawChars == s.currentData() ) with expansion: "hello world!" == "hello world!" @@ -5100,7 +5100,7 @@ with expansion: String.tests.cpp:: PASSED: - REQUIRE( data( ss ) != data( s ) ) + REQUIRE( ss.currentData() != s.currentData() ) with expansion: "hello" != "hello world!" diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 8942b851..70868b59 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -5808,7 +5808,7 @@ Message from section two - rawChars == data( s ) + rawChars == s.currentData() "hello world!" == "hello world!" @@ -5840,7 +5840,7 @@ Message from section two - data( ss ) != data( s ) + ss.currentData() != s.currentData() "hello" != "hello world!" diff --git a/projects/SelfTest/IntrospectiveTests/String.tests.cpp b/projects/SelfTest/IntrospectiveTests/String.tests.cpp index 59f73b11..ee6e4c58 100644 --- a/projects/SelfTest/IntrospectiveTests/String.tests.cpp +++ b/projects/SelfTest/IntrospectiveTests/String.tests.cpp @@ -14,9 +14,6 @@ namespace Catch { static auto isSubstring( StringRef const& stringRef ) -> bool { return stringRef.isSubstring(); } - static auto data( StringRef const& stringRef ) -> char const* { - return stringRef.data(); - } }; auto isOwned( StringRef const& stringRef ) -> bool { @@ -25,14 +22,11 @@ namespace Catch { auto isSubstring( StringRef const& stringRef ) -> bool { return StringRefTestAccess::isSubstring( stringRef ); } - auto data( StringRef const& stringRef ) -> char const* { - return StringRefTestAccess::data( stringRef ); - } } // namespace Catch2 namespace Catch { inline auto toString( Catch::StringRef const& stringRef ) -> std::string { - return std::string( data( stringRef ), stringRef.size() ); + return std::string( stringRef.currentData(), stringRef.size() ); } } // namespace Catch @@ -53,7 +47,7 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) { REQUIRE( s.size() == 5 ); REQUIRE( isSubstring( s ) == false ); - auto rawChars = data( s ); + auto rawChars = s.currentData(); REQUIRE( std::strcmp( rawChars, "hello" ) == 0 ); SECTION( "c_str() does not cause copy" ) { @@ -74,7 +68,6 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) { REQUIRE( isSubstring( original ) == false ); REQUIRE( isOwned( original ) ); - } @@ -92,14 +85,14 @@ TEST_CASE( "StringRef", "[Strings][StringRef]" ) { REQUIRE( isSubstring( ss ) ); REQUIRE( isOwned( ss ) == false ); - auto rawChars = data( ss ); - REQUIRE( rawChars == data( s ) ); // same pointer value + auto rawChars = ss.currentData(); + REQUIRE( rawChars == s.currentData() ); // same pointer value REQUIRE( ss.c_str() != rawChars ); REQUIRE( isSubstring( ss ) == false ); REQUIRE( isOwned( ss ) ); - REQUIRE( data( ss ) != data( s ) ); // different pointer value + REQUIRE( ss.currentData() != s.currentData() ); // different pointer value } SECTION( "non-zero-based substring") {