mirror of https://github.com/catchorg/Catch2.git
Various small string usage performance improvements.
* Empty strings are now direct constructed as `std::string()`, not as empty string literals. * `startsWith` and `endsWith` no longer construct new a string. This should be an improvement for libstdc++ when using older standards, as it doesn't use SSO but COW and thus even short strings are expensive to first create. * Various places now use char literal instead of string literals containing single char. ** `startsWith` and `endsWith` now also have overload that takes single char. Generally the performance improvements under VS2015 are small, as going from short string to char is mostly meaningless because of SSO (Catch doesn't push string handling that hard) and previous commit removed most string handling if tests pass, which is the expect case.
This commit is contained in:
parent
877fd523bc
commit
3b98a0166f
|
@ -85,10 +85,10 @@ namespace Catch {
|
||||||
std::string line;
|
std::string line;
|
||||||
while( std::getline( f, line ) ) {
|
while( std::getline( f, line ) ) {
|
||||||
line = trim(line);
|
line = trim(line);
|
||||||
if( !line.empty() && !startsWith( line, "#" ) ) {
|
if( !line.empty() && !startsWith( line, '#' ) ) {
|
||||||
if( !startsWith( line, "\"" ) )
|
if( !startsWith( line, '"' ) )
|
||||||
line = "\"" + line + "\"";
|
line = "\"" + line + "\"";
|
||||||
addTestOrTags( config, line + "," );
|
addTestOrTags( config, line + ',' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,10 @@ namespace Catch {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool startsWith( std::string const& s, std::string const& prefix );
|
bool startsWith( std::string const& s, std::string const& prefix );
|
||||||
|
bool startsWith( std::string const& s, char prefix );
|
||||||
bool endsWith( std::string const& s, std::string const& suffix );
|
bool endsWith( std::string const& s, std::string const& suffix );
|
||||||
|
bool endsWith( std::string const& s, char suffix );
|
||||||
|
bool contains( std::string const& s, std::string const& infix );
|
||||||
bool contains( std::string const& s, std::string const& infix );
|
bool contains( std::string const& s, std::string const& infix );
|
||||||
void toLowerInPlace( std::string& s );
|
void toLowerInPlace( std::string& s );
|
||||||
std::string toLower( std::string const& s );
|
std::string toLower( std::string const& s );
|
||||||
|
|
|
@ -10,17 +10,28 @@
|
||||||
|
|
||||||
#include "catch_common.h"
|
#include "catch_common.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
bool startsWith( std::string const& s, std::string const& prefix ) {
|
bool startsWith( std::string const& s, std::string const& prefix ) {
|
||||||
return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
|
return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
|
||||||
|
}
|
||||||
|
bool startsWith( std::string const& s, char prefix ) {
|
||||||
|
return !s.empty() && s.front() == prefix;
|
||||||
}
|
}
|
||||||
bool endsWith( std::string const& s, std::string const& suffix ) {
|
bool endsWith( std::string const& s, std::string const& suffix ) {
|
||||||
return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
|
return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
|
||||||
|
}
|
||||||
|
bool endsWith( std::string const& s, char suffix ) {
|
||||||
|
return !s.empty() && s.back() == suffix;
|
||||||
}
|
}
|
||||||
bool contains( std::string const& s, std::string const& infix ) {
|
bool contains( std::string const& s, std::string const& infix ) {
|
||||||
return s.find( infix ) != std::string::npos;
|
return s.find( infix ) != std::string::npos;
|
||||||
}
|
}
|
||||||
|
bool contains( std::string const& s, char infix ) {
|
||||||
|
return s.find(infix);
|
||||||
|
}
|
||||||
char toLowerCh(char c) {
|
char toLowerCh(char c) {
|
||||||
return static_cast<char>( ::tolower( c ) );
|
return static_cast<char>( ::tolower( c ) );
|
||||||
}
|
}
|
||||||
|
@ -37,7 +48,7 @@ namespace Catch {
|
||||||
std::string::size_type start = str.find_first_not_of( whitespaceChars );
|
std::string::size_type start = str.find_first_not_of( whitespaceChars );
|
||||||
std::string::size_type end = str.find_last_not_of( whitespaceChars );
|
std::string::size_type end = str.find_last_not_of( whitespaceChars );
|
||||||
|
|
||||||
return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
|
return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
|
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
|
||||||
|
@ -95,9 +106,9 @@ namespace Catch {
|
||||||
|
|
||||||
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
|
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
|
||||||
#ifndef __GNUG__
|
#ifndef __GNUG__
|
||||||
os << info.file << "(" << info.line << ")";
|
os << info.file << '(' << info.line << ')';
|
||||||
#else
|
#else
|
||||||
os << info.file << ":" << info.line;
|
os << info.file << ':' << info.line;
|
||||||
#endif
|
#endif
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,9 +51,9 @@ namespace Catch {
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !config.testSpec().hasFilters() )
|
if( !config.testSpec().hasFilters() )
|
||||||
Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
|
Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl;
|
||||||
else
|
else
|
||||||
Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
|
Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl;
|
||||||
return matchedTests;
|
return matchedTests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ namespace Catch {
|
||||||
++it ) {
|
++it ) {
|
||||||
matchedTests++;
|
matchedTests++;
|
||||||
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
|
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
|
||||||
if( startsWith( testCaseInfo.name, "#" ) )
|
if( startsWith( testCaseInfo.name, '#' ) )
|
||||||
Catch::cout() << "\"" << testCaseInfo.name << "\"" << std::endl;
|
Catch::cout() << "\"" << testCaseInfo.name << "\"" << std::endl;
|
||||||
else
|
else
|
||||||
Catch::cout() << testCaseInfo.name << std::endl;
|
Catch::cout() << testCaseInfo.name << std::endl;
|
||||||
|
|
|
@ -184,7 +184,7 @@ namespace Matchers {
|
||||||
{
|
{
|
||||||
return m_caseSensitivity == CaseSensitive::No
|
return m_caseSensitivity == CaseSensitive::No
|
||||||
? " (case insensitive)"
|
? " (case insensitive)"
|
||||||
: "";
|
: std::string();
|
||||||
}
|
}
|
||||||
CaseSensitive::Choice m_caseSensitivity;
|
CaseSensitive::Choice m_caseSensitivity;
|
||||||
std::string m_str;
|
std::string m_str;
|
||||||
|
|
|
@ -74,7 +74,7 @@ namespace Catch {
|
||||||
return new T( config );
|
return new T( config );
|
||||||
}
|
}
|
||||||
virtual std::string getDescription() const {
|
virtual std::string getDescription() const {
|
||||||
return "";
|
return std::string();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace Catch {
|
||||||
oss << other.oss.str();
|
oss << other.oss.str();
|
||||||
}
|
}
|
||||||
CopyableStream& operator=( CopyableStream const& other ) {
|
CopyableStream& operator=( CopyableStream const& other ) {
|
||||||
oss.str("");
|
oss.str(std::string());
|
||||||
oss << other.oss.str();
|
oss << other.oss.str();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,7 +146,7 @@ namespace Catch {
|
||||||
m_messages.clear();
|
m_messages.clear();
|
||||||
|
|
||||||
// Reset working state
|
// Reset working state
|
||||||
m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
|
m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
|
||||||
m_lastResult = result;
|
m_lastResult = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ namespace Catch {
|
||||||
virtual std::string getCurrentTestName() const {
|
virtual std::string getCurrentTestName() const {
|
||||||
return m_activeTestCase
|
return m_activeTestCase
|
||||||
? m_activeTestCase->getTestCaseInfo().name
|
? m_activeTestCase->getTestCaseInfo().name
|
||||||
: "";
|
: std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const AssertionResult* getLastResult() const {
|
virtual const AssertionResult* getLastResult() const {
|
||||||
|
@ -247,11 +247,11 @@ namespace Catch {
|
||||||
deltaTotals.testCases.failed = 1;
|
deltaTotals.testCases.failed = 1;
|
||||||
m_reporter->testCaseEnded( TestCaseStats( testInfo,
|
m_reporter->testCaseEnded( TestCaseStats( testInfo,
|
||||||
deltaTotals,
|
deltaTotals,
|
||||||
"",
|
std::string(),
|
||||||
"",
|
std::string(),
|
||||||
false ) );
|
false ) );
|
||||||
m_totals.testCases.failed++;
|
m_totals.testCases.failed++;
|
||||||
testGroupEnded( "", m_totals, 1, 1 );
|
testGroupEnded( std::string(), m_totals, 1, 1 );
|
||||||
m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
|
m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ namespace Catch {
|
||||||
Counts prevAssertions = m_totals.assertions;
|
Counts prevAssertions = m_totals.assertions;
|
||||||
double duration = 0;
|
double duration = 0;
|
||||||
try {
|
try {
|
||||||
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
|
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal );
|
||||||
|
|
||||||
seedRng( *m_config );
|
seedRng( *m_config );
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace Catch {
|
||||||
|
|
||||||
void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
|
void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
|
||||||
|
|
||||||
if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) {
|
if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo;
|
oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo;
|
||||||
throw std::domain_error( oss.str().c_str() );
|
throw std::domain_error( oss.str().c_str() );
|
||||||
|
@ -51,7 +51,7 @@ namespace Catch {
|
||||||
if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
|
if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "error: tag alias, \"" << alias << "\" already registered.\n"
|
oss << "error: tag alias, \"" << alias << "\" already registered.\n"
|
||||||
<< "\tFirst seen at " << find(alias)->lineInfo << "\n"
|
<< "\tFirst seen at " << find(alias)->lineInfo << '\n'
|
||||||
<< "\tRedefined at " << lineInfo;
|
<< "\tRedefined at " << lineInfo;
|
||||||
throw std::domain_error( oss.str().c_str() );
|
throw std::domain_error( oss.str().c_str() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
|
inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
|
||||||
if( startsWith( tag, "." ) ||
|
if( startsWith( tag, '.' ) ||
|
||||||
tag == "hide" ||
|
tag == "hide" ||
|
||||||
tag == "!hide" )
|
tag == "!hide" )
|
||||||
return TestCaseInfo::IsHidden;
|
return TestCaseInfo::IsHidden;
|
||||||
|
|
|
@ -78,7 +78,7 @@ namespace Catch {
|
||||||
|
|
||||||
ss << Colour( Colour::Red )
|
ss << Colour( Colour::Red )
|
||||||
<< "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
|
<< "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
|
||||||
<< "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
|
<< "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n'
|
||||||
<< "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
|
<< "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
|
||||||
|
|
||||||
throw std::runtime_error(ss.str());
|
throw std::runtime_error(ss.str());
|
||||||
|
@ -110,7 +110,7 @@ namespace Catch {
|
||||||
|
|
||||||
virtual void registerTest( TestCase const& testCase ) {
|
virtual void registerTest( TestCase const& testCase ) {
|
||||||
std::string name = testCase.getTestCaseInfo().name;
|
std::string name = testCase.getTestCaseInfo().name;
|
||||||
if( name == "" ) {
|
if( name.empty() ) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "Anonymous test case " << ++m_unnamedCount;
|
oss << "Anonymous test case " << ++m_unnamedCount;
|
||||||
return registerTest( testCase.withName( oss.str() ) );
|
return registerTest( testCase.withName( oss.str() ) );
|
||||||
|
@ -159,7 +159,7 @@ namespace Catch {
|
||||||
|
|
||||||
inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
|
inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
|
||||||
std::string className = classOrQualifiedMethodName;
|
std::string className = classOrQualifiedMethodName;
|
||||||
if( startsWith( className, "&" ) )
|
if( startsWith( className, '&' ) )
|
||||||
{
|
{
|
||||||
std::size_t lastColons = className.rfind( "::" );
|
std::size_t lastColons = className.rfind( "::" );
|
||||||
std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
|
std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
|
||||||
|
|
|
@ -102,7 +102,7 @@ std::string toString( int value ) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << value;
|
oss << value;
|
||||||
if( value > Detail::hexThreshold )
|
if( value > Detail::hexThreshold )
|
||||||
oss << " (0x" << std::hex << value << ")";
|
oss << " (0x" << std::hex << value << ')';
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ std::string toString( unsigned long value ) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << value;
|
oss << value;
|
||||||
if( value > Detail::hexThreshold )
|
if( value > Detail::hexThreshold )
|
||||||
oss << " (0x" << std::hex << value << ")";
|
oss << " (0x" << std::hex << value << ')';
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,14 +164,14 @@ std::string toString( long long value ) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << value;
|
oss << value;
|
||||||
if( value > Detail::hexThreshold )
|
if( value > Detail::hexThreshold )
|
||||||
oss << " (0x" << std::hex << value << ")";
|
oss << " (0x" << std::hex << value << ')';
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
std::string toString( unsigned long long value ) {
|
std::string toString( unsigned long long value ) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << value;
|
oss << value;
|
||||||
if( value > Detail::hexThreshold )
|
if( value > Detail::hexThreshold )
|
||||||
oss << " (0x" << std::hex << value << ")";
|
oss << " (0x" << std::hex << value << ')';
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,11 +27,11 @@ namespace Catch
|
||||||
m_wildcard( NoWildcard ),
|
m_wildcard( NoWildcard ),
|
||||||
m_pattern( adjustCase( pattern ) )
|
m_pattern( adjustCase( pattern ) )
|
||||||
{
|
{
|
||||||
if( startsWith( m_pattern, "*" ) ) {
|
if( startsWith( m_pattern, '*' ) ) {
|
||||||
m_pattern = m_pattern.substr( 1 );
|
m_pattern = m_pattern.substr( 1 );
|
||||||
m_wildcard = WildcardAtStart;
|
m_wildcard = WildcardAtStart;
|
||||||
}
|
}
|
||||||
if( endsWith( m_pattern, "*" ) ) {
|
if( endsWith( m_pattern, '*' ) ) {
|
||||||
m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
|
m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
|
||||||
m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
|
m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,7 +202,7 @@ namespace Catch {
|
||||||
|
|
||||||
XmlWriter& writeBlankLine() {
|
XmlWriter& writeBlankLine() {
|
||||||
ensureTagClosed();
|
ensureTagClosed();
|
||||||
stream() << "\n";
|
stream() << '\n';
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue