diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index aa8ca01..084cb1e 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -65,7 +65,8 @@ enum ParseFlag { kParseDefaultFlags = 0, //!< Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer. kParseInsituFlag = 1, //!< In-situ(destructive) parsing. kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. - kParseIterativeFlag = 4 //!< Iterative(constant complexity in terms of function call stack size) parsing. + kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. + kParseStopWhenDoneFlag = 8 //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. }; /////////////////////////////////////////////////////////////////////////////// @@ -309,11 +310,13 @@ public: } RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); - SkipWhitespace(is); + if (!(parseFlags & kParseStopWhenDoneFlag)) { + SkipWhitespace(is); - if (is.Peek() != '\0') { - RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + if (is.Peek() != '\0') { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } } } @@ -1192,6 +1195,11 @@ private: } state = d; + + // Do not further consume streams if a root JSON has been parsed. + if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) + break; + SkipWhitespace(is); } diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index d6dd4c4..61bc38c 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -545,6 +545,39 @@ TEST(Reader, Parse_EmptyObject) { EXPECT_EQ(2u, h.step_); } +struct ParseMultipleRootHandler : BaseReaderHandler<> { + ParseMultipleRootHandler() : step_(0) {} + + bool Default() { ADD_FAILURE(); return false; } + bool StartObject() { EXPECT_EQ(0u, step_); step_++; return true; } + bool EndObject(SizeType) { EXPECT_EQ(1u, step_); step_++; return true; } + bool StartArray() { EXPECT_EQ(2u, step_); step_++; return true; } + bool EndArray(SizeType) { EXPECT_EQ(3u, step_); step_++; return true; } + + unsigned step_; +}; + +template +void TestMultipleRoot() { + StringStream s("{}[] a"); + ParseMultipleRootHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(2u, h.step_); + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(4u, h.step_); + EXPECT_EQ(' ', s.Take()); + EXPECT_EQ('a', s.Take()); +} + +TEST(Reader, Parse_MultipleRoot) { + TestMultipleRoot(); +} + +TEST(Reader, ParseIterative_MultipleRoot) { + TestMultipleRoot(); +} + #define TEST_ERROR(errorCode, str) \ { \ char buffer[1001]; \