Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/src/catch2/internal
diff options
context:
space:
mode:
authorMartin Hořeňovský2023-11-16 22:17:21 +0100
committerMartin Hořeňovský2023-11-17 09:54:03 +0100
commit32d9ae24bc4a0fed9a136a73e116b4ded0ac84b7 (patch)
tree03e04865114507d294be9b2e15225aad3ab8344b /src/catch2/internal
parentde7ba4e8897bbe56c612b980d02f249a92d0eada (diff)
downloadcatch3-32d9ae24bc4a0fed9a136a73e116b4ded0ac84b7.tar.gz
JSONWriter deals in StringRefs instead of std::strings
Together with liberal use of `_sr` UDL to compile-time convert string literals into StringRefs, this will reduce the number of allocation and remove most of the strcpy calls inherent in converting string lits into `std::string`s.
Diffstat (limited to 'src/catch2/internal')
-rw-r--r--src/catch2/internal/catch_jsonwriter.cpp43
-rw-r--r--src/catch2/internal/catch_jsonwriter.hpp45
2 files changed, 51 insertions, 37 deletions
diff --git a/src/catch2/internal/catch_jsonwriter.cpp b/src/catch2/internal/catch_jsonwriter.cpp
index f6c279d8..ff65a9d3 100644
--- a/src/catch2/internal/catch_jsonwriter.cpp
+++ b/src/catch2/internal/catch_jsonwriter.cpp
@@ -29,7 +29,7 @@ namespace Catch {
JsonObjectWriter::JsonObjectWriter( std::ostream& os,
std::uint64_t indent_level ):
m_os{ os }, m_indent_level{ indent_level } {
- m_os << "{";
+ m_os << '{';
}
JsonObjectWriter::JsonObjectWriter( JsonObjectWriter&& source ):
m_os{ source.m_os },
@@ -47,11 +47,11 @@ namespace Catch {
m_os << '}';
}
- JsonValueWriter JsonObjectWriter::write( std::string const& key ) {
+ JsonValueWriter JsonObjectWriter::write( StringRef key ) {
JsonUtils::appendCommaNewline(
m_os, m_should_comma, m_indent_level + 1 );
- m_os << '"' << key << '"' << ": ";
+ m_os << '"' << key << "\": ";
return JsonValueWriter{ m_os, m_indent_level + 1 };
}
@@ -60,7 +60,7 @@ namespace Catch {
JsonArrayWriter::JsonArrayWriter( std::ostream& os,
std::uint64_t indent_level ):
m_os{ os }, m_indent_level{ indent_level } {
- m_os << "[";
+ m_os << '[';
}
JsonArrayWriter::JsonArrayWriter( JsonArrayWriter&& source ):
m_os{ source.m_os },
@@ -108,8 +108,41 @@ namespace Catch {
return JsonArrayWriter{ m_os, m_indent_level };
}
+ void JsonValueWriter::write( Catch::StringRef value ) && {
+ writeImpl( value, true );
+ }
+
void JsonValueWriter::write( bool value ) && {
- writeImpl( value ? "true" : "false", false );
+ writeImpl( value ? "true"_sr : "false"_sr, false );
+ }
+
+ void JsonValueWriter::writeImpl( Catch::StringRef value, bool quote ) {
+ if ( quote ) { m_os << '"'; }
+ for (char c : value) {
+ // Escape list taken from https://www.json.org/json-en.html,
+ // string definition.
+ // Note that while forward slash _can_ be escaped, it does
+ // not have to be, if JSON is not further embedded somewhere
+ // where forward slash is meaningful.
+ if ( c == '"' ) {
+ m_os << "\\\"";
+ } else if ( c == '\\' ) {
+ m_os << "\\\\";
+ } else if ( c == '\b' ) {
+ m_os << "\\b";
+ } else if ( c == '\f' ) {
+ m_os << "\\f";
+ } else if ( c == '\n' ) {
+ m_os << "\\n";
+ } else if ( c == '\r' ) {
+ m_os << "\\r";
+ } else if ( c == '\t' ) {
+ m_os << "\\t";
+ } else {
+ m_os << c;
+ }
+ }
+ if ( quote ) { m_os << '"'; }
}
} // namespace Catch
diff --git a/src/catch2/internal/catch_jsonwriter.hpp b/src/catch2/internal/catch_jsonwriter.hpp
index 1b6ac967..59c044e4 100644
--- a/src/catch2/internal/catch_jsonwriter.hpp
+++ b/src/catch2/internal/catch_jsonwriter.hpp
@@ -37,45 +37,26 @@ namespace Catch {
void write( T const& value ) && {
writeImpl( value, !std::is_arithmetic<T>::value );
}
-
+ void write( StringRef value ) &&;
void write( bool value ) &&;
private:
- template <typename T>
+ void writeImpl( StringRef value, bool quote );
+
+ // Without this SFINAE, this overload is a better match
+ // for `std::string`, `char const*`, `char const[N]` args.
+ // While it would still work, it would cause code bloat
+ // and multiple iteration over the strings
+ template <typename T,
+ typename = typename std::enable_if_t<
+ !std::is_convertible<T, StringRef>::value>>
void writeImpl( T const& value, bool quote_value ) {
- if ( quote_value ) { m_os << '"'; }
m_sstream << value;
- while ( true ) {
- char c = m_sstream.get();
- if ( m_sstream.eof() ) { break; }
-
- // see https://www.json.org/json-en.html, string definition for the escape list
- if ( c == '"' ) {
- m_os << "\\\"";
- } else if ( c == '\\' ) {
- m_os << "\\\\";
- // Note that while forward slash _can_ be escaped, it
- // does not have to be, if JSON is not further embedded
- // somewhere where forward slash is meaningful.
- } else if ( c == '\b' ) {
- m_os << "\\b";
- } else if ( c == '\f' ) {
- m_os << "\\f";
- } else if ( c == '\n' ) {
- m_os << "\\n";
- } else if ( c == '\r' ) {
- m_os << "\\r";
- } else if ( c == '\t') {
- m_os << "\\t";
- } else {
- m_os << c;
- }
- }
- if ( quote_value ) { m_os << '"'; }
+ writeImpl( m_sstream.str(), quote_value );
}
std::ostream& m_os;
- std::stringstream m_sstream{};
+ std::stringstream m_sstream;
std::uint64_t m_indent_level;
};
@@ -89,7 +70,7 @@ namespace Catch {
~JsonObjectWriter();
- JsonValueWriter write( std::string const& key );
+ JsonValueWriter write( StringRef key );
private:
std::ostream& m_os;