mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 08:42:39 +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) | ||||
| * Implicitly call `strdup()` for `String` but not for `char*` (issues #84, #87) | ||||
| * 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) | ||||
| * 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,22 +1,21 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| ZIP="C:\Program Files\7-Zip\7z.exe" | ||||
| TAG=$(git describe) | ||||
| OUTPUT="ArduinoJson-$TAG.zip" | ||||
|  | ||||
| cd ../.. | ||||
|  | ||||
| # remove existing file | ||||
| rm -f $OUTPUT | ||||
|  | ||||
| # create zip | ||||
| "$ZIP" a $OUTPUT \ | ||||
| 	ArduinoJson/CHANGELOG.md \ | ||||
| 	ArduinoJson/examples \ | ||||
| 	ArduinoJson/include \ | ||||
| 	ArduinoJson/keywords.txt \ | ||||
| 	ArduinoJson/library.properties \ | ||||
| 	ArduinoJson/LICENSE.md \ | ||||
| 	ArduinoJson/README.md \ | ||||
| 	ArduinoJson/src	\ | ||||
| 	-x!ArduinoJson/src/CMakeLists.txt | ||||
| #!/bin/bash | ||||
|  | ||||
| TAG=$(git describe) | ||||
| OUTPUT="ArduinoJson-$TAG.zip" | ||||
|  | ||||
| cd $(dirname $0)/../.. | ||||
|  | ||||
| # remove existing file | ||||
| rm -f $OUTPUT | ||||
|  | ||||
| # create zip | ||||
| 7z a $OUTPUT \ | ||||
| 	ArduinoJson/CHANGELOG.md \ | ||||
| 	ArduinoJson/examples \ | ||||
| 	ArduinoJson/include \ | ||||
| 	ArduinoJson/keywords.txt \ | ||||
| 	ArduinoJson/library.properties \ | ||||
| 	ArduinoJson/LICENSE.md \ | ||||
| 	ArduinoJson/README.md \ | ||||
| 	ArduinoJson/src	\ | ||||
| 	-x!ArduinoJson/src/CMakeLists.txt | ||||
|   | ||||
| @@ -11,6 +11,12 @@ | ||||
| #include <math.h>   // for isnan() and isinf() | ||||
| #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 n = 0; | ||||
|   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 <ctype.h> | ||||
|  | ||||
| #include "../../include/ArduinoJson/Internals/Comments.hpp" | ||||
| #include "../../include/ArduinoJson/Internals/Encoding.hpp" | ||||
| #include "../../include/ArduinoJson/JsonArray.hpp" | ||||
| #include "../../include/ArduinoJson/JsonBuffer.hpp" | ||||
| @@ -17,16 +18,11 @@ | ||||
| using namespace ArduinoJson; | ||||
| using namespace ArduinoJson::Internals; | ||||
|  | ||||
| static const char *skipSpaces(const char *ptr) { | ||||
|   while (isspace(*ptr)) ptr++; | ||||
|   return ptr; | ||||
| } | ||||
|  | ||||
| bool JsonParser::skip(char charToSkip) { | ||||
|   register const char *ptr = skipSpaces(_readPtr); | ||||
|   register const char *ptr = skipSpacesAndComments(_readPtr); | ||||
|   if (*ptr != charToSkip) return false; | ||||
|   ptr++; | ||||
|   _readPtr = skipSpaces(ptr); | ||||
|   _readPtr = skipSpacesAndComments(ptr); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| @@ -50,7 +46,7 @@ bool JsonParser::parseAnythingTo(JsonVariant *destination) { | ||||
| } | ||||
|  | ||||
| inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) { | ||||
|   _readPtr = skipSpaces(_readPtr); | ||||
|   _readPtr = skipSpacesAndComments(_readPtr); | ||||
|  | ||||
|   switch (*_readPtr) { | ||||
|     case '[': | ||||
| @@ -212,8 +208,13 @@ bool JsonParser::parseNullTo(JsonVariant *destination) { | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| static bool isStopChar(char c) { | ||||
|   return c == '\0' || c == ':' || c == '}' || c == ']' || c == ','; | ||||
| static inline bool isInRange(char c, char min, char max) { | ||||
|   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() { | ||||
| @@ -222,7 +223,7 @@ const char *JsonParser::parseString() { | ||||
|  | ||||
|   char c = *readPtr; | ||||
|  | ||||
|   if (c == '\'' || c == '\"') { | ||||
|   if (c == '\'' || c == '\"') {  // quotes | ||||
|     char stopChar = c; | ||||
|     for (;;) { | ||||
|       c = *++readPtr; | ||||
| @@ -241,9 +242,9 @@ const char *JsonParser::parseString() { | ||||
|  | ||||
|       *writePtr++ = c; | ||||
|     } | ||||
|   } else { | ||||
|   } else {  // no quotes | ||||
|     for (;;) { | ||||
|       if (isStopChar(c)) break; | ||||
|       if (!isLetterOrNumber(c)) break; | ||||
|       *writePtr++ = c; | ||||
|       c = *++readPtr; | ||||
|     } | ||||
|   | ||||
| @@ -164,8 +164,26 @@ TEST_F(JsonParser_Array_Tests, MixedTrueFalse) { | ||||
|   parseMustFail(); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonParser_Array_Tests, TwoStrings) { | ||||
|   whenInputIs("[\"hello\",\"world\"]"); | ||||
| TEST_F(JsonParser_Array_Tests, TwoStringsDoubleQuotes) { | ||||
|   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(); | ||||
|   sizeMustBe(2); | ||||
| @@ -224,3 +242,118 @@ TEST_F(JsonParser_Array_Tests, StringWithUnterminatedEscapeSequence) { | ||||
|   whenInputIs("\"\\\0\"", 4); | ||||
|   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