diff --git a/include/rapidjson/internal/ieee754.h b/include/rapidjson/internal/ieee754.h index 6890f89..82bb0b9 100644 --- a/include/rapidjson/internal/ieee754.h +++ b/include/rapidjson/internal/ieee754.h @@ -40,6 +40,7 @@ public: bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } + bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h index a450456..fab6740 100644 --- a/include/rapidjson/writer.h +++ b/include/rapidjson/writer.h @@ -139,7 +139,7 @@ public: } bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } - + bool EndObject(SizeType memberCount = 0) { (void)memberCount; RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); @@ -235,6 +235,9 @@ protected: } bool WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) + return false; + char buffer[25]; char* end = internal::dtoa(d, buffer); for (char* p = buffer; p != end; ++p) @@ -381,6 +384,9 @@ inline bool Writer::WriteUint64(uint64_t u) { template<> inline bool Writer::WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) + return false; + char *buffer = os_->Push(25); char* end = internal::dtoa(d, buffer); os_->Pop(static_cast(25 - (end - buffer))); diff --git a/test/unittest/writertest.cpp b/test/unittest/writertest.cpp index 2adb551..24a2c6c 100644 --- a/test/unittest/writertest.cpp +++ b/test/unittest/writertest.cpp @@ -375,3 +375,27 @@ TEST(Writer, InvalidEventSequence) { EXPECT_FALSE(writer.IsComplete()); } } + +double zero = 0.0; // Use global variable to prevent compiler warning + +TEST(Writer, NaN) { + double nan = zero / zero; + EXPECT_TRUE(internal::Double(nan).IsNan()); + StringBuffer buffer; + Writer writer(buffer); + EXPECT_FALSE(writer.Double(nan)); +} + +TEST(Writer, Inf) { + double inf = 1.0 / zero; + EXPECT_TRUE(internal::Double(inf).IsInf()); + StringBuffer buffer; + { + Writer writer(buffer); + EXPECT_FALSE(writer.Double(inf)); + } + { + Writer writer(buffer); + EXPECT_FALSE(writer.Double(-inf)); + } +}