diff --git a/include/yaml-cpp/emitter.h b/include/yaml-cpp/emitter.h index 37de878..6f142b0 100644 --- a/include/yaml-cpp/emitter.h +++ b/include/yaml-cpp/emitter.h @@ -7,10 +7,13 @@ #pragma once #endif +#include #include +#include #include #include #include +#include #include "yaml-cpp/binary.h" #include "yaml-cpp/dll.h" @@ -153,7 +156,28 @@ inline Emitter& Emitter::WriteStreamable(T value) { std::stringstream stream; SetStreamablePrecision(stream); - stream << value; + + bool special = false; + if (std::is_floating_point::value) { + if ((std::numeric_limits::has_quiet_NaN || + std::numeric_limits::has_signaling_NaN) && + std::isnan(value)) { + special = true; + stream << ".nan"; + } else if (std::numeric_limits::has_infinity) { + if (value == std::numeric_limits::infinity()) { + special = true; + stream << ".inf"; + } else if (value == -std::numeric_limits::infinity()) { + special = true; + stream << "-.inf"; + } + } + } + + if (!special) { + stream << value; + } m_stream << stream.str(); StartedScalar(); diff --git a/test/integration/emitter_test.cpp b/test/integration/emitter_test.cpp index dfd4f34..3a5783b 100644 --- a/test/integration/emitter_test.cpp +++ b/test/integration/emitter_test.cpp @@ -253,8 +253,9 @@ TEST_F(EmitterTest, ScalarFormat) { out << DoubleQuoted << "explicit double-quoted scalar"; out << "auto-detected\ndouble-quoted scalar"; out << "a non-\"auto-detected\" double-quoted scalar"; - out << Literal << "literal scalar\nthat may span\nmany, many\nlines " - "and have \"whatever\" crazy\tsymbols that we like"; + out << Literal + << "literal scalar\nthat may span\nmany, many\nlines " + "and have \"whatever\" crazy\tsymbols that we like"; out << EndSeq; ExpectEmit( @@ -526,9 +527,10 @@ TEST_F(EmitterTest, SimpleComment) { TEST_F(EmitterTest, MultiLineComment) { out << BeginSeq; - out << "item 1" << Comment( - "really really long\ncomment that couldn't " - "possibly\nfit on one line"); + out << "item 1" + << Comment( + "really really long\ncomment that couldn't " + "possibly\nfit on one line"); out << "item 2"; out << EndSeq; @@ -984,6 +986,45 @@ TEST_F(EmitterTest, ValueOfBackslash) { ExpectEmit("foo: \"\\\\\""); } +TEST_F(EmitterTest, Infinity) { + out << YAML::BeginMap; + out << YAML::Key << "foo" << YAML::Value + << std::numeric_limits::infinity(); + out << YAML::Key << "bar" << YAML::Value + << std::numeric_limits::infinity(); + out << YAML::EndMap; + + ExpectEmit( + "foo: .inf\n" + "bar: .inf"); +} + +TEST_F(EmitterTest, NegInfinity) { + out << YAML::BeginMap; + out << YAML::Key << "foo" << YAML::Value + << -std::numeric_limits::infinity(); + out << YAML::Key << "bar" << YAML::Value + << -std::numeric_limits::infinity(); + out << YAML::EndMap; + + ExpectEmit( + "foo: -.inf\n" + "bar: -.inf"); +} + +TEST_F(EmitterTest, NaN) { + out << YAML::BeginMap; + out << YAML::Key << "foo" << YAML::Value + << std::numeric_limits::quiet_NaN(); + out << YAML::Key << "bar" << YAML::Value + << std::numeric_limits::quiet_NaN(); + out << YAML::EndMap; + + ExpectEmit( + "foo: .nan\n" + "bar: .nan"); +} + class EmitterErrorTest : public ::testing::Test { protected: void ExpectEmitError(const std::string& expectedError) { @@ -1034,5 +1075,5 @@ TEST_F(EmitterErrorTest, InvalidAlias) { ExpectEmitError(ErrorMsg::INVALID_ALIAS); } -} -} +} // namespace +} // namespace YAML