From e79526ce13cc0e3a5006e2ae34c667c465bb0730 Mon Sep 17 00:00:00 2001 From: Michael Thon Date: Tue, 17 May 2016 14:01:33 +0200 Subject: [PATCH 1/2] json.hpp: write and parse double in full precision --- include/cereal/archives/json.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/cereal/archives/json.hpp b/include/cereal/archives/json.hpp index 34a80a685..c4c61d070 100644 --- a/include/cereal/archives/json.hpp +++ b/include/cereal/archives/json.hpp @@ -108,7 +108,7 @@ namespace cereal static Options Default(){ return Options(); } //! Default options with no indentation - static Options NoIndent(){ return Options( std::numeric_limits::max_digits10, IndentChar::space, 0 ); } + static Options NoIndent(){ return Options( JSONWriter::kDefaultMaxDecimalPlaces, IndentChar::space, 0 ); } //! The character to use for indenting enum class IndentChar : char @@ -124,7 +124,7 @@ namespace cereal @param indentChar The type of character to indent with @param indentLength The number of indentChar to use for indentation (0 corresponds to no indentation) */ - explicit Options( int precision = std::numeric_limits::max_digits10, + explicit Options( int precision = JSONWriter::kDefaultMaxDecimalPlaces, IndentChar indentChar = IndentChar::space, unsigned int indentLength = 4 ) : itsPrecision( precision ), @@ -420,7 +420,7 @@ namespace cereal itsNextName( nullptr ), itsReadStream(stream) { - itsDocument.ParseStream<0>(itsReadStream); + itsDocument.ParseStream(itsReadStream); if (itsDocument.IsArray()) itsIteratorStack.emplace_back(itsDocument.Begin(), itsDocument.End()); else From e5911ad79ef3ddeb44f14d89c5a008213a96c9d0 Mon Sep 17 00:00:00 2001 From: Michael Thon Date: Tue, 17 May 2016 14:03:41 +0200 Subject: [PATCH 2/2] rapidjson: add ability to write and parse nan/inf/-inf --- include/cereal/external/rapidjson/reader.h | 15 +++++++++++++-- include/cereal/external/rapidjson/writer.h | 19 ++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/include/cereal/external/rapidjson/reader.h b/include/cereal/external/rapidjson/reader.h index 86dbbbde9..38c963097 100644 --- a/include/cereal/external/rapidjson/reader.h +++ b/include/cereal/external/rapidjson/reader.h @@ -23,6 +23,7 @@ #include "internal/meta.h" #include "internal/stack.h" #include "internal/strtod.h" +#include #if defined(CEREAL_RAPIDJSON_SIMD) && defined(_MSC_VER) #include @@ -699,7 +700,7 @@ class GenericReader { } template - void ParseNull(InputStream& is, Handler& handler) { + void ParseNullOrNan(InputStream& is, Handler& handler) { CEREAL_RAPIDJSON_ASSERT(is.Peek() == 'n'); is.Take(); @@ -707,6 +708,10 @@ class GenericReader { if (CEREAL_RAPIDJSON_UNLIKELY(!handler.Null())) CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); } + else if (Consume(is, 'a') && Consume(is, 'n')) { + if (CEREAL_RAPIDJSON_UNLIKELY(!handler.Double( std::numeric_limits::quiet_NaN() ))) + CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } else CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); } @@ -1178,6 +1183,12 @@ class GenericReader { significandDigit++; } } + else if (CEREAL_RAPIDJSON_UNLIKELY(Consume(s, 'i')) && Consume(s, 'n') && Consume(s, 'f')) { + double inf = std::numeric_limits::infinity(); + if (CEREAL_RAPIDJSON_UNLIKELY(!handler.Double(minus ? -inf : inf))) + CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset); + return; + } else CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); @@ -1369,7 +1380,7 @@ class GenericReader { template void ParseValue(InputStream& is, Handler& handler) { switch (is.Peek()) { - case 'n': ParseNull (is, handler); break; + case 'n': ParseNullOrNan(is, handler); break; case 't': ParseTrue (is, handler); break; case 'f': ParseFalse (is, handler); break; case '"': ParseString(is, handler); break; diff --git a/include/cereal/external/rapidjson/writer.h b/include/cereal/external/rapidjson/writer.h index 5112ded10..10f3d1c93 100644 --- a/include/cereal/external/rapidjson/writer.h +++ b/include/cereal/external/rapidjson/writer.h @@ -319,8 +319,25 @@ class Writer { } bool WriteDouble(double d) { - if (internal::Double(d).IsNanOrInf()) + if (internal::Double(d).IsNanOrInf()) { + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, static_cast('n')); + PutUnsafe(*os_, static_cast('a')); + PutUnsafe(*os_, static_cast('n')); + } else { + if (internal::Double(d).Sign()) { + PutReserve(*os_, 4); + PutUnsafe(*os_, static_cast('-')); + } else { + PutReserve(*os_, 3); + } + PutUnsafe(*os_, static_cast('i')); + PutUnsafe(*os_, static_cast('n')); + PutUnsafe(*os_, static_cast('f')); + } return false; + } char buffer[25]; char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);