mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Added support of comments in JSON input (issue #88)
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | *.sh text eol=lf | ||||||
| @@ -8,6 +8,7 @@ v5.0 (currently in beta) | |||||||
| * Added `JsonBuffer::strdup()` to make a copy of a string (issues #10, #57) | * Added `JsonBuffer::strdup()` to make a copy of a string (issues #10, #57) | ||||||
| * Implicitly call `strdup()` for `String` but not for `char*` (issues #84, #87) | * Implicitly call `strdup()` for `String` but not for `char*` (issues #84, #87) | ||||||
| * Added support of non standard JSON input (issue #44) | * Added support of non standard JSON input (issue #44) | ||||||
|  | * Added support of comments in JSON input (issue #88) | ||||||
| * Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66) | * Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66) | ||||||
| * Switched to new the library layout (requires Arduino 1.0.6 or above) | * Switched to new the library layout (requires Arduino 1.0.6 or above) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								include/ArduinoJson/Internals/Comments.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								include/ArduinoJson/Internals/Comments.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2015 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  | const char *skipSpacesAndComments(const char *ptr); | ||||||
|  | } | ||||||
|  | } | ||||||
| @@ -1,16 +1,15 @@ | |||||||
| #!/bin/bash | #!/bin/bash | ||||||
|  |  | ||||||
| ZIP="C:\Program Files\7-Zip\7z.exe" |  | ||||||
| TAG=$(git describe) | TAG=$(git describe) | ||||||
| OUTPUT="ArduinoJson-$TAG.zip" | OUTPUT="ArduinoJson-$TAG.zip" | ||||||
|  |  | ||||||
| cd ../.. | cd $(dirname $0)/../.. | ||||||
|  |  | ||||||
| # remove existing file | # remove existing file | ||||||
| rm -f $OUTPUT | rm -f $OUTPUT | ||||||
|  |  | ||||||
| # create zip | # create zip | ||||||
| "$ZIP" a $OUTPUT \ | 7z a $OUTPUT \ | ||||||
| 	ArduinoJson/CHANGELOG.md \ | 	ArduinoJson/CHANGELOG.md \ | ||||||
| 	ArduinoJson/examples \ | 	ArduinoJson/examples \ | ||||||
| 	ArduinoJson/include \ | 	ArduinoJson/include \ | ||||||
|   | |||||||
| @@ -11,6 +11,12 @@ | |||||||
| #include <math.h>   // for isnan() and isinf() | #include <math.h>   // for isnan() and isinf() | ||||||
| #include <stdio.h>  // for sprintf() | #include <stdio.h>  // for sprintf() | ||||||
|  |  | ||||||
|  | // only for GCC 4.9+ | ||||||
|  | #if defined(__GNUC__) && \ | ||||||
|  |     (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) | ||||||
|  | #pragma GCC diagnostic ignored "-Wfloat-conversion" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| size_t Print::print(const char s[]) { | size_t Print::print(const char s[]) { | ||||||
|   size_t n = 0; |   size_t n = 0; | ||||||
|   while (*s) { |   while (*s) { | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								src/Internals/Comments.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/Internals/Comments.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2015 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  |  | ||||||
|  | #include "../../include/ArduinoJson/Internals/Comments.hpp" | ||||||
|  |  | ||||||
|  | inline static const char *skipCStyleComment(const char *ptr) { | ||||||
|  |   ptr += 2; | ||||||
|  |   for (;;) { | ||||||
|  |     if (ptr[0] == '\0') return ptr; | ||||||
|  |     if (ptr[0] == '*' && ptr[1] == '/') return ptr + 2; | ||||||
|  |     ptr++; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline static const char *skipCppStyleComment(const char *ptr) { | ||||||
|  |   ptr += 2; | ||||||
|  |   for (;;) { | ||||||
|  |     if (ptr[0] == '\0' || ptr[0] == '\n') return ptr; | ||||||
|  |     ptr++; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const char *ArduinoJson::Internals::skipSpacesAndComments(const char *ptr) { | ||||||
|  |   for (;;) { | ||||||
|  |     switch (ptr[0]) { | ||||||
|  |       case ' ': | ||||||
|  |       case '\t': | ||||||
|  |       case '\r': | ||||||
|  |       case '\n': | ||||||
|  |         ptr++; | ||||||
|  |         continue; | ||||||
|  |       case '/': | ||||||
|  |         switch (ptr[1]) { | ||||||
|  |           case '*': | ||||||
|  |             ptr = skipCStyleComment(ptr); | ||||||
|  |             break; | ||||||
|  |           case '/': | ||||||
|  |             ptr = skipCppStyleComment(ptr); | ||||||
|  |             break; | ||||||
|  |           default: | ||||||
|  |             return ptr; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |       default: | ||||||
|  |         return ptr; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -9,6 +9,7 @@ | |||||||
| #include <stdlib.h>  // for strtol, strtod | #include <stdlib.h>  // for strtol, strtod | ||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
|  |  | ||||||
|  | #include "../../include/ArduinoJson/Internals/Comments.hpp" | ||||||
| #include "../../include/ArduinoJson/Internals/Encoding.hpp" | #include "../../include/ArduinoJson/Internals/Encoding.hpp" | ||||||
| #include "../../include/ArduinoJson/JsonArray.hpp" | #include "../../include/ArduinoJson/JsonArray.hpp" | ||||||
| #include "../../include/ArduinoJson/JsonBuffer.hpp" | #include "../../include/ArduinoJson/JsonBuffer.hpp" | ||||||
| @@ -17,16 +18,11 @@ | |||||||
| using namespace ArduinoJson; | using namespace ArduinoJson; | ||||||
| using namespace ArduinoJson::Internals; | using namespace ArduinoJson::Internals; | ||||||
|  |  | ||||||
| static const char *skipSpaces(const char *ptr) { |  | ||||||
|   while (isspace(*ptr)) ptr++; |  | ||||||
|   return ptr; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool JsonParser::skip(char charToSkip) { | bool JsonParser::skip(char charToSkip) { | ||||||
|   register const char *ptr = skipSpaces(_readPtr); |   register const char *ptr = skipSpacesAndComments(_readPtr); | ||||||
|   if (*ptr != charToSkip) return false; |   if (*ptr != charToSkip) return false; | ||||||
|   ptr++; |   ptr++; | ||||||
|   _readPtr = skipSpaces(ptr); |   _readPtr = skipSpacesAndComments(ptr); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -50,7 +46,7 @@ bool JsonParser::parseAnythingTo(JsonVariant *destination) { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) { | inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) { | ||||||
|   _readPtr = skipSpaces(_readPtr); |   _readPtr = skipSpacesAndComments(_readPtr); | ||||||
|  |  | ||||||
|   switch (*_readPtr) { |   switch (*_readPtr) { | ||||||
|     case '[': |     case '[': | ||||||
| @@ -212,8 +208,13 @@ bool JsonParser::parseNullTo(JsonVariant *destination) { | |||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| static bool isStopChar(char c) { | static inline bool isInRange(char c, char min, char max) { | ||||||
|   return c == '\0' || c == ':' || c == '}' || c == ']' || c == ','; |   return min <= c && c <= max; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline bool isLetterOrNumber(char c) { | ||||||
|  |   return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') || | ||||||
|  |          isInRange(c, 'A', 'Z'); | ||||||
| } | } | ||||||
|  |  | ||||||
| const char *JsonParser::parseString() { | const char *JsonParser::parseString() { | ||||||
| @@ -222,7 +223,7 @@ const char *JsonParser::parseString() { | |||||||
|  |  | ||||||
|   char c = *readPtr; |   char c = *readPtr; | ||||||
|  |  | ||||||
|   if (c == '\'' || c == '\"') { |   if (c == '\'' || c == '\"') {  // quotes | ||||||
|     char stopChar = c; |     char stopChar = c; | ||||||
|     for (;;) { |     for (;;) { | ||||||
|       c = *++readPtr; |       c = *++readPtr; | ||||||
| @@ -241,9 +242,9 @@ const char *JsonParser::parseString() { | |||||||
|  |  | ||||||
|       *writePtr++ = c; |       *writePtr++ = c; | ||||||
|     } |     } | ||||||
|   } else { |   } else {  // no quotes | ||||||
|     for (;;) { |     for (;;) { | ||||||
|       if (isStopChar(c)) break; |       if (!isLetterOrNumber(c)) break; | ||||||
|       *writePtr++ = c; |       *writePtr++ = c; | ||||||
|       c = *++readPtr; |       c = *++readPtr; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -164,8 +164,26 @@ TEST_F(JsonParser_Array_Tests, MixedTrueFalse) { | |||||||
|   parseMustFail(); |   parseMustFail(); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_F(JsonParser_Array_Tests, TwoStrings) { | TEST_F(JsonParser_Array_Tests, TwoStringsDoubleQuotes) { | ||||||
|   whenInputIs("[\"hello\",\"world\"]"); |   whenInputIs("[ \"hello\" , \"world\" ]"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(2); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  |   secondElementMustBe("world"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, TwoStringsSingleQuotes) { | ||||||
|  |   whenInputIs("[ 'hello' , 'world' ]"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(2); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  |   secondElementMustBe("world"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, TwoStringsNoQuotes) { | ||||||
|  |   whenInputIs("[ hello , world ]"); | ||||||
|  |  | ||||||
|   parseMustSucceed(); |   parseMustSucceed(); | ||||||
|   sizeMustBe(2); |   sizeMustBe(2); | ||||||
| @@ -224,3 +242,118 @@ TEST_F(JsonParser_Array_Tests, StringWithUnterminatedEscapeSequence) { | |||||||
|   whenInputIs("\"\\\0\"", 4); |   whenInputIs("\"\\\0\"", 4); | ||||||
|   parseMustFail(); |   parseMustFail(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, CCommentBeforeOpeningBracket) { | ||||||
|  |   whenInputIs("/*COMMENT*/[\"hello\"]"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(1); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, CCommentAfterOpeningBracket) { | ||||||
|  |   whenInputIs("[/*COMMENT*/\"hello\"]"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(1); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, CCommentBeforeClosingBracket) { | ||||||
|  |   whenInputIs("[\"hello\"/*COMMENT*/]"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(1); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, CCommentAfterClosingBracket) { | ||||||
|  |   whenInputIs("[\"hello\"]/*COMMENT*/"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(1); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, CCommentBeforeComma) { | ||||||
|  |   whenInputIs("[\"hello\"/*COMMENT*/,\"world\"]"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(2); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  |   secondElementMustBe("world"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, CCommentAfterComma) { | ||||||
|  |   whenInputIs("[\"hello\",/*COMMENT*/\"world\"]"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(2); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  |   secondElementMustBe("world"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, CppCommentBeforeOpeningBracket) { | ||||||
|  |   whenInputIs("//COMMENT\n[\"hello\"]"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(1); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, CppCommentAfterOpeningBracket) { | ||||||
|  |   whenInputIs("[//COMMENT\n\"hello\"]"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(1); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, CppCommentBeforeClosingBracket) { | ||||||
|  |   whenInputIs("[\"hello\"//COMMENT\n]"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(1); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, CppCommentAfterClosingBracket) { | ||||||
|  |   whenInputIs("[\"hello\"]//COMMENT\n"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(1); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, CppCommentBeforeComma) { | ||||||
|  |   whenInputIs("[\"hello\"//COMMENT\n,\"world\"]"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(2); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  |   secondElementMustBe("world"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, CppCommentAfterComma) { | ||||||
|  |   whenInputIs("[\"hello\",//COMMENT\n\"world\"]"); | ||||||
|  |  | ||||||
|  |   parseMustSucceed(); | ||||||
|  |   sizeMustBe(2); | ||||||
|  |   firstElementMustBe("hello"); | ||||||
|  |   secondElementMustBe("world"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, InvalidCppComment) { | ||||||
|  |   whenInputIs("[/COMMENT\n]"); | ||||||
|  |   parseMustFail(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, InvalidComment) { | ||||||
|  |   whenInputIs("[/*/\n]"); | ||||||
|  |   parseMustFail(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonParser_Array_Tests, UnfinishedCComment) { | ||||||
|  |   whenInputIs("[/*COMMENT]"); | ||||||
|  |   parseMustFail(); | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user