Better support for infs and NaNs in JSON writer

As the types and values sent into the writer are determined by Catch2,
I do not expect to actually need this support, but it is better to have
it and not be surprised in the future.
This commit is contained in:
Martin Hořeňovský committed 2026-07-23 14:26:26 +02:00
1 parent 0cc833ea95
commit c267251e70
20 files changed
+441 -18

No files matched your search

+22
View File
@@ -7,8 +7,10 @@
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_jsonwriter.hpp>
#include <catch2/internal/catch_polyfills.hpp>
#include <catch2/internal/catch_unreachable.hpp>
#include <cmath>
#include <locale>
namespace Catch {
@@ -145,10 +147,30 @@ namespace Catch {
writeImpl( value, true );
}
void JsonValueWriter::write( float value ) && {
writeFloatingPoint( value );
}
void JsonValueWriter::write( double value ) && {
writeFloatingPoint( value );
}
void JsonValueWriter::write( bool value ) && {
writeImpl( value ? "true"_sr : "false"_sr, false );
}
template <typename T>
void JsonValueWriter::writeFloatingPoint( T value ) {
if ( Catch::isnan( value ) ) {
writeImpl( "NaN"_sr, false );
} else if ( std::isinf( value ) ) {
writeImpl( value < 0 ? "-Infinity"_sr : "Infinity"_sr, false );
} else {
m_sstream << value;
writeImpl( m_sstream.str(), false );
}
}
void JsonValueWriter::writeImpl( Catch::StringRef value, bool quote ) {
if ( quote ) { m_os << '"'; }
size_t current_start = 0;
+8
View File
@@ -39,11 +39,19 @@ namespace Catch {
writeImpl( value, !std::is_arithmetic<T>::value );
}
void write( StringRef value ) &&;
void write( float value ) &&;
void write( double value ) &&;
void write( bool value ) &&;
private:
void writeImpl( StringRef value, bool quote );
// Helper to deal with non-finite floating point values, which
// are not standard JSON, but we use JS/Python/etc. approach of
// emitting `NaN`, `Infinity`, `-Infinity` as number(like).
template <typename T>
void writeFloatingPoint( T value );
// 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