From 7cb031cc03d510d05f2d7ea4348503e81bc6cf25 Mon Sep 17 00:00:00 2001 From: thebusytypist Date: Wed, 15 Apr 2015 14:45:07 +0800 Subject: [PATCH 1/6] Add unittests for parsing root JSON value other than array and object. --- test/unittest/readertest.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index bccfbd6..b9a5adc 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -1041,6 +1041,15 @@ TEST(Reader, IterativeParsing_ErrorHandling) { TESTERRORHANDLING("{\"a\"}", kParseErrorObjectMissColon, 4u); TESTERRORHANDLING("{\"a\": 1", kParseErrorObjectMissCommaOrCurlyBracket, 7u); TESTERRORHANDLING("[1 2 3]", kParseErrorArrayMissCommaOrSquareBracket, 3u); + + // Any JSON value can be a valid root element in RFC7159. + TESTERRORHANDLING("\"ab", kParseErrorStringMissQuotationMark, 2u); + TESTERRORHANDLING("truE", kParseErrorValueInvalid, 3u); + TESTERRORHANDLING("False", kParseErrorValueInvalid, 0u); + TESTERRORHANDLING("true, false", kParseErrorDocumentRootNotSingular, 4u); + TESTERRORHANDLING("false, false", kParseErrorDocumentRootNotSingular, 5u); + TESTERRORHANDLING("nulL", kParseErrorValueInvalid, 3u); + TESTERRORHANDLING("null , null", kParseErrorDocumentRootNotSingular, 5u); } template > From 857674737345c5aa2b4251480455578f1787d62f Mon Sep 17 00:00:00 2001 From: thebusytypist Date: Wed, 15 Apr 2015 14:51:48 +0800 Subject: [PATCH 2/6] Add unittest for state transition to IterativeParsingMemberKeyState. --- test/unittest/readertest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index b9a5adc..942f8d6 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -1041,6 +1041,7 @@ TEST(Reader, IterativeParsing_ErrorHandling) { TESTERRORHANDLING("{\"a\"}", kParseErrorObjectMissColon, 4u); TESTERRORHANDLING("{\"a\": 1", kParseErrorObjectMissCommaOrCurlyBracket, 7u); TESTERRORHANDLING("[1 2 3]", kParseErrorArrayMissCommaOrSquareBracket, 3u); + TESTERRORHANDLING("{\"a: 1", kParseErrorStringMissQuotationMark, 5u); // Any JSON value can be a valid root element in RFC7159. TESTERRORHANDLING("\"ab", kParseErrorStringMissQuotationMark, 2u); From 399333226b64f389e9358a07018c2798b91f7543 Mon Sep 17 00:00:00 2001 From: thebusytypist Date: Wed, 15 Apr 2015 14:54:44 +0800 Subject: [PATCH 3/6] Use assertion for impossible case(The Predict() can ensure the token is ColonToken, otherwise it would be marked as Error state. So there is no need to check ColonToken again). --- include/rapidjson/reader.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index d9da869..a2b6379 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -1273,12 +1273,9 @@ private: return dst; case IterativeParsingKeyValueDelimiterState: - if (token == ColonToken) { - is.Take(); - return dst; - } - else - return IterativeParsingErrorState; + RAPIDJSON_ASSERT(token == ColonToken); + is.Take(); + return dst; case IterativeParsingMemberValueState: // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. From 5ae48a0380b3377d43f1cb06d6061af796b5fa6d Mon Sep 17 00:00:00 2001 From: thebusytypist Date: Wed, 15 Apr 2015 15:21:42 +0800 Subject: [PATCH 4/6] Assert on impossible state transition in Transit(); Put the last case and all non-enumerated cases(also supply assertion for them) in for code coverage. --- include/rapidjson/reader.h | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index a2b6379..e0b9c8c 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -1228,13 +1228,6 @@ private: template RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) { switch (dst) { - case IterativeParsingStartState: - RAPIDJSON_ASSERT(false); - return IterativeParsingErrorState; - - case IterativeParsingFinishState: - return dst; - case IterativeParsingErrorState: return dst; @@ -1350,17 +1343,25 @@ private: } } - case IterativeParsingValueState: + default: + // This branch is for IterativeParsingValueState actually. + // Use `default:` rather than + // `case IterativeParsingValueState:` is for code coverage. + + // The IterativeParsingStartState is not enumerated in this switch-case. + // It is impossible for that case. And it can be caught by following assertion. + + // The IterativeParsingFinishState is not enumerated in this switch-case either. + // It is a "derivative" state which cannot triggered from Predict() directly. + // Therefore it cannot happen here. And it can be caught by following assertion. + RAPIDJSON_ASSERT(dst == IterativeParsingValueState); + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. ParseValue(is, handler); if (HasParseError()) { return IterativeParsingErrorState; } return IterativeParsingFinishState; - - default: - RAPIDJSON_ASSERT(false); - return IterativeParsingErrorState; } } From 0d28bb13c7833a8cdf5c946a9ab1622eed528492 Mon Sep 17 00:00:00 2001 From: thebusytypist Date: Wed, 15 Apr 2015 15:46:31 +0800 Subject: [PATCH 5/6] Add a missing error handling check(a single number as JSON root). --- test/unittest/readertest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 942f8d6..11f3e78 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -1051,6 +1051,7 @@ TEST(Reader, IterativeParsing_ErrorHandling) { TESTERRORHANDLING("false, false", kParseErrorDocumentRootNotSingular, 5u); TESTERRORHANDLING("nulL", kParseErrorValueInvalid, 3u); TESTERRORHANDLING("null , null", kParseErrorDocumentRootNotSingular, 5u); + TESTERRORHANDLING("1a", kParseErrorDocumentRootNotSingular, 1u); } template > From 6ef29ff431ece1a7a63283bfc568f919dc78b311 Mon Sep 17 00:00:00 2001 From: thebusytypist Date: Wed, 15 Apr 2015 16:09:29 +0800 Subject: [PATCH 6/6] Fix warning about unused argument. --- include/rapidjson/reader.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index e0b9c8c..31a145f 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -1227,6 +1227,8 @@ private: // May return a new state on state pop. template RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) { + (void)token; + switch (dst) { case IterativeParsingErrorState: return dst;