diff options
| author | Martin Hořeňovský | 2023-11-16 22:17:21 +0100 |
|---|---|---|
| committer | Martin Hořeňovský | 2023-11-17 09:54:03 +0100 |
| commit | 32d9ae24bc4a0fed9a136a73e116b4ded0ac84b7 (patch) | |
| tree | 03e04865114507d294be9b2e15225aad3ab8344b /src/catch2/internal | |
| parent | de7ba4e8897bbe56c612b980d02f249a92d0eada (diff) | |
| download | catch3-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.cpp | 43 | ||||
| -rw-r--r-- | src/catch2/internal/catch_jsonwriter.hpp | 45 |
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; |