Add StringRef::compare for three way comparison

This commit is contained in:
Martin Hořeňovský 2021-09-27 18:30:31 +02:00
parent d42e7a23a0
commit 21b99d6f58
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
12 changed files with 254 additions and 10 deletions

View File

@ -29,6 +29,27 @@ namespace Catch {
return strncmp(m_start, rhs.m_start, rhs.m_size) < 0;
}
int StringRef::compare( StringRef rhs ) const {
auto cmpResult =
strncmp( m_start, rhs.m_start, std::min( m_size, rhs.m_size ) );
// This means that strncmp found a difference before the strings
// ended, and we can return it directly
if ( cmpResult != 0 ) {
return cmpResult;
}
// If strings are equal up to length, then their comparison results on
// their size
if ( m_size < rhs.m_size ) {
return -1;
} else if ( m_size > rhs.m_size ) {
return 1;
} else {
return 0;
}
}
auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
return os.write(str.data(), str.size());
}

View File

@ -69,7 +69,6 @@ namespace Catch {
return m_size;
}
public: // substrings and searches
// Returns a substring of [start, start + length).
// If start + length > size(), then the substring is [start, start + size()).
// If start > size(), then the substring is empty.
@ -87,7 +86,6 @@ namespace Catch {
return m_start;
}
public: // iterators
constexpr const_iterator begin() const { return m_start; }
constexpr const_iterator end() const { return m_start + m_size; }
@ -95,6 +93,14 @@ namespace Catch {
friend std::string& operator += (std::string& lhs, StringRef const& sr);
friend std::ostream& operator << (std::ostream& os, StringRef const& sr);
friend std::string operator+(StringRef lhs, StringRef rhs);
/**
* Provides a three-way comparison with rhs
*
* Returns negative number if lhs < rhs, 0 if lhs == rhs, and a positive
* number if lhs > rhs
*/
int compare( StringRef rhs ) const;
};

View File

@ -207,6 +207,7 @@ Message from section two
:test-result: PASS String matchers
:test-result: PASS StringRef
:test-result: PASS StringRef at compilation time
:test-result: PASS StringRef::compare
:test-result: PASS Stringifying char arrays with statically known sizes - char
:test-result: PASS Stringifying char arrays with statically known sizes - signed char
:test-result: PASS Stringifying char arrays with statically known sizes - unsigned char

View File

@ -1537,6 +1537,16 @@ String.tests.cpp:<line number>: passed: with 1 message: '!(sr1.empty())'
String.tests.cpp:<line number>: passed: with 1 message: 'sr1.size() == 3'
String.tests.cpp:<line number>: passed: with 1 message: 'sr2.empty()'
String.tests.cpp:<line number>: passed: with 1 message: 'sr2.size() == 0'
String.tests.cpp:<line number>: passed: sr1.compare(sr2) < 0 for: -1 < 0
String.tests.cpp:<line number>: passed: sr2.compare(sr1) > 0 for: 1 > 0
String.tests.cpp:<line number>: passed: sr1.compare(sr3) == 0 for: 0 == 0
String.tests.cpp:<line number>: passed: sr3.compare(sr1) == 0 for: 0 == 0
String.tests.cpp:<line number>: passed: sr1.compare(sr2) < 0 for: -1 < 0
String.tests.cpp:<line number>: passed: sr2.compare(sr1) > 0 for: 1 > 0
String.tests.cpp:<line number>: passed: sr1.compare(sr3) > 0 for: 3 > 0
String.tests.cpp:<line number>: passed: sr2.compare(sr3) > 0 for: 3 > 0
String.tests.cpp:<line number>: passed: sr3.compare(sr1) < 0 for: -3 < 0
String.tests.cpp:<line number>: passed: sr3.compare(sr2) < 0 for: -3 < 0
ToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( with_null_terminator ) == R"("abc")"s for: ""abc"" == ""abc""
ToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( no_null_terminator ) == R"("abc")"s for: ""abc"" == ""abc""
ToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( with_null_terminator ) == R"("abc")"s for: ""abc"" == ""abc""

View File

@ -1386,6 +1386,6 @@ due to unexpected exception with message:
Why would you throw a std::string?
===============================================================================
test cases: 369 | 293 passed | 70 failed | 6 failed as expected
assertions: 2106 | 1954 passed | 129 failed | 23 failed as expected
test cases: 370 | 294 passed | 70 failed | 6 failed as expected
assertions: 2116 | 1964 passed | 129 failed | 23 failed as expected

View File

@ -10906,6 +10906,70 @@ String.tests.cpp:<line number>: PASSED:
with message:
sr2.size() == 0
-------------------------------------------------------------------------------
StringRef::compare
Same length on both sides
-------------------------------------------------------------------------------
String.tests.cpp:<line number>
...............................................................................
String.tests.cpp:<line number>: PASSED:
REQUIRE( sr1.compare(sr2) < 0 )
with expansion:
-1 < 0
String.tests.cpp:<line number>: PASSED:
REQUIRE( sr2.compare(sr1) > 0 )
with expansion:
1 > 0
String.tests.cpp:<line number>: PASSED:
REQUIRE( sr1.compare(sr3) == 0 )
with expansion:
0 == 0
String.tests.cpp:<line number>: PASSED:
REQUIRE( sr3.compare(sr1) == 0 )
with expansion:
0 == 0
-------------------------------------------------------------------------------
StringRef::compare
Different lengths
-------------------------------------------------------------------------------
String.tests.cpp:<line number>
...............................................................................
String.tests.cpp:<line number>: PASSED:
REQUIRE( sr1.compare(sr2) < 0 )
with expansion:
-1 < 0
String.tests.cpp:<line number>: PASSED:
REQUIRE( sr2.compare(sr1) > 0 )
with expansion:
1 > 0
String.tests.cpp:<line number>: PASSED:
REQUIRE( sr1.compare(sr3) > 0 )
with expansion:
3 > 0
String.tests.cpp:<line number>: PASSED:
REQUIRE( sr2.compare(sr3) > 0 )
with expansion:
3 > 0
String.tests.cpp:<line number>: PASSED:
REQUIRE( sr3.compare(sr1) < 0 )
with expansion:
-3 < 0
String.tests.cpp:<line number>: PASSED:
REQUIRE( sr3.compare(sr2) < 0 )
with expansion:
-3 < 0
-------------------------------------------------------------------------------
Stringifying char arrays with statically known sizes - char
-------------------------------------------------------------------------------
@ -16954,6 +17018,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED:
===============================================================================
test cases: 369 | 277 passed | 86 failed | 6 failed as expected
assertions: 2123 | 1954 passed | 146 failed | 23 failed as expected
test cases: 370 | 278 passed | 86 failed | 6 failed as expected
assertions: 2133 | 1964 passed | 146 failed | 23 failed as expected

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact
>
<testsuite name="<exe-name>" errors="17" failures="129" tests="2123" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="129" tests="2133" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/>
<property name="random-seed" value="1"/>
@ -1196,6 +1196,8 @@ Matchers.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="StringRef/StringRef + StringRef" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="StringRef at compilation time/Simple constructors" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="StringRef at compilation time/UDL construction" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="StringRef::compare/Same length on both sides" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="StringRef::compare/Different lengths" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Stringifying char arrays with statically known sizes - char" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Stringifying char arrays with statically known sizes - signed char" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Stringifying char arrays with statically known sizes - unsigned char" time="{duration}" status="run"/>

View File

@ -204,6 +204,8 @@
<testCase name="StringRef/StringRef + StringRef" duration="{duration}"/>
<testCase name="StringRef at compilation time/Simple constructors" duration="{duration}"/>
<testCase name="StringRef at compilation time/UDL construction" duration="{duration}"/>
<testCase name="StringRef::compare/Same length on both sides" duration="{duration}"/>
<testCase name="StringRef::compare/Different lengths" duration="{duration}"/>
</file>
<file path="tests/<exe-name>/IntrospectiveTests/StringManip.tests.cpp">
<testCase name="Trim strings" duration="{duration}"/>

View File

@ -2753,6 +2753,26 @@ ok {test-number} - with 1 message: 'sr1.size() == 3'
ok {test-number} - with 1 message: 'sr2.empty()'
# StringRef at compilation time
ok {test-number} - with 1 message: 'sr2.size() == 0'
# StringRef::compare
ok {test-number} - sr1.compare(sr2) < 0 for: -1 < 0
# StringRef::compare
ok {test-number} - sr2.compare(sr1) > 0 for: 1 > 0
# StringRef::compare
ok {test-number} - sr1.compare(sr3) == 0 for: 0 == 0
# StringRef::compare
ok {test-number} - sr3.compare(sr1) == 0 for: 0 == 0
# StringRef::compare
ok {test-number} - sr1.compare(sr2) < 0 for: -1 < 0
# StringRef::compare
ok {test-number} - sr2.compare(sr1) > 0 for: 1 > 0
# StringRef::compare
ok {test-number} - sr1.compare(sr3) > 0 for: 3 > 0
# StringRef::compare
ok {test-number} - sr2.compare(sr3) > 0 for: 3 > 0
# StringRef::compare
ok {test-number} - sr3.compare(sr1) < 0 for: -3 < 0
# StringRef::compare
ok {test-number} - sr3.compare(sr2) < 0 for: -3 < 0
# Stringifying char arrays with statically known sizes - char
ok {test-number} - ::Catch::Detail::stringify( with_null_terminator ) == R"("abc")"s for: ""abc"" == ""abc""
# Stringifying char arrays with statically known sizes - char
@ -4248,5 +4268,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
ok {test-number} -
# xmlentitycheck
ok {test-number} -
1..2123
1..2133

View File

@ -514,6 +514,8 @@ Matchers.tests.cpp:<line number>|nexpression failed|n CHECK_THAT( testStringFor
##teamcity[testFinished name='StringRef' duration="{duration}"]
##teamcity[testStarted name='StringRef at compilation time']
##teamcity[testFinished name='StringRef at compilation time' duration="{duration}"]
##teamcity[testStarted name='StringRef::compare']
##teamcity[testFinished name='StringRef::compare' duration="{duration}"]
##teamcity[testStarted name='Stringifying char arrays with statically known sizes - char']
##teamcity[testFinished name='Stringifying char arrays with statically known sizes - char' duration="{duration}"]
##teamcity[testStarted name='Stringifying char arrays with statically known sizes - signed char']

View File

@ -12945,6 +12945,95 @@ Message from section two
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="StringRef::compare" tags="[StringRef][Strings]" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Section name="Same length on both sides" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
sr1.compare(sr2) &lt; 0
</Original>
<Expanded>
-1 &lt; 0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
sr2.compare(sr1) > 0
</Original>
<Expanded>
1 > 0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
sr1.compare(sr3) == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
sr3.compare(sr1) == 0
</Original>
<Expanded>
0 == 0
</Expanded>
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<Section name="Different lengths" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
sr1.compare(sr2) &lt; 0
</Original>
<Expanded>
-1 &lt; 0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
sr2.compare(sr1) > 0
</Original>
<Expanded>
1 > 0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
sr1.compare(sr3) > 0
</Original>
<Expanded>
3 > 0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
sr2.compare(sr3) > 0
</Original>
<Expanded>
3 > 0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
sr3.compare(sr1) &lt; 0
</Original>
<Expanded>
-3 &lt; 0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
sr3.compare(sr2) &lt; 0
</Original>
<Expanded>
-3 &lt; 0
</Expanded>
</Expression>
<OverallResults successes="6" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Stringifying char arrays with statically known sizes - char" tags="[toString]" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/ToString.tests.cpp" >
<Original>
@ -19953,6 +20042,6 @@ loose text artifact
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="1954" failures="146" expectedFailures="23"/>
<OverallResultsCases successes="277" failures="86" expectedFailures="6"/>
<OverallResults successes="1964" failures="146" expectedFailures="23"/>
<OverallResultsCases successes="278" failures="86" expectedFailures="6"/>
</Catch2TestRun>

View File

@ -165,3 +165,30 @@ TEST_CASE("StringRef at compilation time", "[Strings][StringRef][constexpr]") {
STATIC_REQUIRE(sr2.size() == 0);
}
}
TEST_CASE("StringRef::compare", "[Strings][StringRef]") {
using Catch::StringRef;
SECTION("Same length on both sides") {
StringRef sr1("abcdc");
StringRef sr2("abcdd");
StringRef sr3("abcdc");
REQUIRE(sr1.compare(sr2) < 0);
REQUIRE(sr2.compare(sr1) > 0);
REQUIRE(sr1.compare(sr3) == 0);
REQUIRE(sr3.compare(sr1) == 0);
}
SECTION("Different lengths") {
StringRef sr1("def");
StringRef sr2("deff");
StringRef sr3("ab");
REQUIRE(sr1.compare(sr2) < 0);
REQUIRE(sr2.compare(sr1) > 0);
REQUIRE(sr1.compare(sr3) > 0);
REQUIRE(sr2.compare(sr3) > 0);
REQUIRE(sr3.compare(sr1) < 0);
REQUIRE(sr3.compare(sr2) < 0);
}
}