mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 12:41:17 +00:00
Make sure output of NaN, Infinity and -Infinity is identical on all platforms (#717)
Specifically, printing `.nan`, `.inf`, and `-.inf`, respectively, as per the spec section 10.2.1.4.
This commit is contained in:

committed by
Jesse Beder

parent
0122697561
commit
e0e01d53c2
@@ -7,10 +7,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include "yaml-cpp/binary.h"
|
#include "yaml-cpp/binary.h"
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
@@ -153,7 +156,28 @@ inline Emitter& Emitter::WriteStreamable(T value) {
|
|||||||
|
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
SetStreamablePrecision<T>(stream);
|
SetStreamablePrecision<T>(stream);
|
||||||
|
|
||||||
|
bool special = false;
|
||||||
|
if (std::is_floating_point<T>::value) {
|
||||||
|
if ((std::numeric_limits<T>::has_quiet_NaN ||
|
||||||
|
std::numeric_limits<T>::has_signaling_NaN) &&
|
||||||
|
std::isnan(value)) {
|
||||||
|
special = true;
|
||||||
|
stream << ".nan";
|
||||||
|
} else if (std::numeric_limits<T>::has_infinity) {
|
||||||
|
if (value == std::numeric_limits<T>::infinity()) {
|
||||||
|
special = true;
|
||||||
|
stream << ".inf";
|
||||||
|
} else if (value == -std::numeric_limits<T>::infinity()) {
|
||||||
|
special = true;
|
||||||
|
stream << "-.inf";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!special) {
|
||||||
stream << value;
|
stream << value;
|
||||||
|
}
|
||||||
m_stream << stream.str();
|
m_stream << stream.str();
|
||||||
|
|
||||||
StartedScalar();
|
StartedScalar();
|
||||||
|
@@ -253,7 +253,8 @@ TEST_F(EmitterTest, ScalarFormat) {
|
|||||||
out << DoubleQuoted << "explicit double-quoted scalar";
|
out << DoubleQuoted << "explicit double-quoted scalar";
|
||||||
out << "auto-detected\ndouble-quoted scalar";
|
out << "auto-detected\ndouble-quoted scalar";
|
||||||
out << "a non-\"auto-detected\" double-quoted scalar";
|
out << "a non-\"auto-detected\" double-quoted scalar";
|
||||||
out << Literal << "literal scalar\nthat may span\nmany, many\nlines "
|
out << Literal
|
||||||
|
<< "literal scalar\nthat may span\nmany, many\nlines "
|
||||||
"and have \"whatever\" crazy\tsymbols that we like";
|
"and have \"whatever\" crazy\tsymbols that we like";
|
||||||
out << EndSeq;
|
out << EndSeq;
|
||||||
|
|
||||||
@@ -526,7 +527,8 @@ TEST_F(EmitterTest, SimpleComment) {
|
|||||||
|
|
||||||
TEST_F(EmitterTest, MultiLineComment) {
|
TEST_F(EmitterTest, MultiLineComment) {
|
||||||
out << BeginSeq;
|
out << BeginSeq;
|
||||||
out << "item 1" << Comment(
|
out << "item 1"
|
||||||
|
<< Comment(
|
||||||
"really really long\ncomment that couldn't "
|
"really really long\ncomment that couldn't "
|
||||||
"possibly\nfit on one line");
|
"possibly\nfit on one line");
|
||||||
out << "item 2";
|
out << "item 2";
|
||||||
@@ -984,6 +986,45 @@ TEST_F(EmitterTest, ValueOfBackslash) {
|
|||||||
ExpectEmit("foo: \"\\\\\"");
|
ExpectEmit("foo: \"\\\\\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(EmitterTest, Infinity) {
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "foo" << YAML::Value
|
||||||
|
<< std::numeric_limits<float>::infinity();
|
||||||
|
out << YAML::Key << "bar" << YAML::Value
|
||||||
|
<< std::numeric_limits<double>::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<float>::infinity();
|
||||||
|
out << YAML::Key << "bar" << YAML::Value
|
||||||
|
<< -std::numeric_limits<double>::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<float>::quiet_NaN();
|
||||||
|
out << YAML::Key << "bar" << YAML::Value
|
||||||
|
<< std::numeric_limits<double>::quiet_NaN();
|
||||||
|
out << YAML::EndMap;
|
||||||
|
|
||||||
|
ExpectEmit(
|
||||||
|
"foo: .nan\n"
|
||||||
|
"bar: .nan");
|
||||||
|
}
|
||||||
|
|
||||||
class EmitterErrorTest : public ::testing::Test {
|
class EmitterErrorTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
void ExpectEmitError(const std::string& expectedError) {
|
void ExpectEmitError(const std::string& expectedError) {
|
||||||
@@ -1034,5 +1075,5 @@ TEST_F(EmitterErrorTest, InvalidAlias) {
|
|||||||
|
|
||||||
ExpectEmitError(ErrorMsg::INVALID_ALIAS);
|
ExpectEmitError(ErrorMsg::INVALID_ALIAS);
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
}
|
} // namespace YAML
|
||||||
|
Reference in New Issue
Block a user