From e23bc0d1a5ab65518d5df1924eb3f0dc3ffcd4e8 Mon Sep 17 00:00:00 2001 From: Sergey Kosarevsky Date: Mon, 29 Feb 2016 16:12:30 +0100 Subject: [PATCH] Fixed numbers-as-strings for in-situ streams --- include/rapidjson/reader.h | 40 +++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 721d8cd..8990441 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -1100,10 +1100,12 @@ private: template void ParseNumber(InputStream& is, Handler& handler) { internal::StreamLocalCopy copy(is); - NumberStream s(*this, copy.s); - size_t startOffset = s.Tell(); + NumberStream s(*this, copy.s); - typename InputStream::Ch *head = is.PutBegin(); + size_t startOffset = s.Tell(); // Parse minus bool minus = Consume(s, '-'); @@ -1189,6 +1191,9 @@ private: int expFrac = 0; size_t decimalPosition; if (Consume(s, '.')) { + if (((parseFlags & kParseNumbersAsStringsFlag) != 0) && ((parseFlags & kParseInsituFlag) == 0)) { + s.Push('.'); + } decimalPosition = s.Length(); if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9'))) @@ -1236,7 +1241,11 @@ private: // Parse exp = e [ minus / plus ] 1*DIGIT int exp = 0; if (Consume(s, 'e') || Consume(s, 'E')) { - if (!useDouble) { + if ( ((parseFlags & kParseNumbersAsStringsFlag) != 0) && ((parseFlags & kParseInsituFlag) == 0) ) { + s.Push( 'e' ); + } + + if (!useDouble) { d = static_cast(use64bit ? i64 : i); useDouble = true; } @@ -1277,15 +1286,24 @@ private: // Finish parsing, call event according to the type of number. bool cont = true; - if (parseFlags & kParseNumbersAsStringsFlag) - { - s.Pop(); // Pop stack no matter if it will be used or not. - const size_t length = s.Tell() - startOffset; + if (parseFlags & kParseNumbersAsStringsFlag) { + + if (parseFlags & kParseInsituFlag) { + s.Pop(); // Pop stack no matter if it will be used or not. + typename InputStream::Ch *head = is.PutBegin(); + const size_t length = s.Tell() - startOffset; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); + cont = handler.RawNumber(str, SizeType(length), false); + } + else { + const char* str = s.Pop(); + SizeType length = static_cast(s.Length()) - 1; + cont = handler.RawNumber(str, SizeType(length), true); + } - cont = handler.RawNumber(head, length, (parseFlags & kParseInsituFlag) ? false : true); } - else - { + else { size_t length = s.Length(); const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.