mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 08:42:39 +01:00 
			
		
		
		
	ArduinoJson is now a header-only library (issue #199)
This commit is contained in:
		| @@ -1,4 +1,5 @@ | |||||||
| # http://clang.llvm.org/docs/ClangFormatStyleOptions.html | # http://clang.llvm.org/docs/ClangFormatStyleOptions.html | ||||||
|  |  | ||||||
| BasedOnStyle: Google | BasedOnStyle: Google | ||||||
| Standard: Cpp03 | Standard: Cpp03 | ||||||
|  | AllowShortFunctionsOnASingleLine: Empty | ||||||
|   | |||||||
| @@ -5,10 +5,4 @@ | |||||||
| // https://github.com/bblanchon/ArduinoJson | // https://github.com/bblanchon/ArduinoJson | ||||||
| // If you like this project, please add a star! | // If you like this project, please add a star! | ||||||
|  |  | ||||||
| // About this file |  | ||||||
| // --------------- |  | ||||||
| // This file is here for [PlatformIO](http://platformio.org/). |  | ||||||
| // It must be present in the root for the tool to find it. |  | ||||||
| // Feel free to ignore this file if your working in another environment. |  | ||||||
|  |  | ||||||
| #include "include/ArduinoJson.h" | #include "include/ArduinoJson.h" | ||||||
|   | |||||||
| @@ -1,6 +1,11 @@ | |||||||
| ArduinoJson: change log | ArduinoJson: change log | ||||||
| ======================= | ======================= | ||||||
|  |  | ||||||
|  | HEAD | ||||||
|  | ---- | ||||||
|  |  | ||||||
|  | * ArduinoJson is now a header-only library (issue #199) | ||||||
|  |  | ||||||
| v5.5.1 | v5.5.1 | ||||||
| ------ | ------ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| # https://github.com/bblanchon/ArduinoJson | # https://github.com/bblanchon/ArduinoJson | ||||||
| # If you like this project, please add a star! | # If you like this project, please add a star! | ||||||
|  |  | ||||||
| cmake_minimum_required(VERSION 2.8.12) | cmake_minimum_required(VERSION 3.0) | ||||||
| project(ArduinoJson) | project(ArduinoJson) | ||||||
|  |  | ||||||
| enable_testing() | enable_testing() | ||||||
| @@ -18,5 +18,4 @@ if(${COVERAGE}) | |||||||
| 	set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") | 	set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
| add_subdirectory(src) |  | ||||||
| add_subdirectory(test) | add_subdirectory(test) | ||||||
|   | |||||||
| @@ -5,9 +5,5 @@ | |||||||
| // https://github.com/bblanchon/ArduinoJson | // https://github.com/bblanchon/ArduinoJson | ||||||
| // If you like this project, please add a star! | // If you like this project, please add a star! | ||||||
|  |  | ||||||
| #include "ArduinoJson/DynamicJsonBuffer.hpp" | #include "ArduinoJson.hpp" | ||||||
| #include "ArduinoJson/JsonArray.hpp" |  | ||||||
| #include "ArduinoJson/JsonObject.hpp" |  | ||||||
| #include "ArduinoJson/StaticJsonBuffer.hpp" |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson; | using namespace ArduinoJson; | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								include/ArduinoJson.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								include/ArduinoJson.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #include "ArduinoJson/DynamicJsonBuffer.hpp" | ||||||
|  | #include "ArduinoJson/JsonArray.hpp" | ||||||
|  | #include "ArduinoJson/JsonObject.hpp" | ||||||
|  | #include "ArduinoJson/StaticJsonBuffer.hpp" | ||||||
|  |  | ||||||
|  | #include "ArduinoJson/Internals/JsonParser.ipp" | ||||||
|  | #include "ArduinoJson/JsonArray.ipp" | ||||||
|  | #include "ArduinoJson/JsonBuffer.ipp" | ||||||
|  | #include "ArduinoJson/JsonObject.ipp" | ||||||
|  | #include "ArduinoJson/JsonVariant.ipp" | ||||||
|  |  | ||||||
|  | using namespace ArduinoJson; | ||||||
| @@ -11,12 +11,26 @@ | |||||||
|  |  | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | #if defined(__clang__) | ||||||
|  | #pragma clang diagnostic push | ||||||
|  | #pragma clang diagnostic ignored "-Wnon-virtual-dtor" | ||||||
|  | #elif defined(__GNUC__) | ||||||
|  | #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) | ||||||
|  | #pragma GCC diagnostic push | ||||||
|  | #endif | ||||||
|  | #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
| class DefaultAllocator { | class DefaultAllocator { | ||||||
|  public: |  public: | ||||||
|   void* allocate(size_t size) { return malloc(size); } |   void* allocate(size_t size) { | ||||||
|   void deallocate(void* pointer) { free(pointer); } |     return malloc(size); | ||||||
|  |   } | ||||||
|  |   void deallocate(void* pointer) { | ||||||
|  |     free(pointer); | ||||||
|  |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| template <typename TAllocator> | template <typename TAllocator> | ||||||
| @@ -51,7 +65,6 @@ class BlockJsonBuffer : public JsonBuffer { | |||||||
|     return total; |     return total; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  protected: |  | ||||||
|   virtual void* alloc(size_t bytes) { |   virtual void* alloc(size_t bytes) { | ||||||
|     return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes); |     return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes); | ||||||
|   } |   } | ||||||
| @@ -92,3 +105,11 @@ class BlockJsonBuffer : public JsonBuffer { | |||||||
| }; | }; | ||||||
| } | } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #if defined(__clang__) | ||||||
|  | #pragma clang diagnostic pop | ||||||
|  | #elif defined(__GNUC__) | ||||||
|  | #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) | ||||||
|  | #pragma GCC diagnostic pop | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|   | |||||||
| @@ -9,6 +9,48 @@ | |||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
| const char *skipSpacesAndComments(const char *ptr); | inline 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 const char *skipCppStyleComment(const char *ptr) { | ||||||
|  |   ptr += 2; | ||||||
|  |   for (;;) { | ||||||
|  |     if (ptr[0] == '\0' || ptr[0] == '\n') return ptr; | ||||||
|  |     ptr++; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline const char *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; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ class Encoding { | |||||||
|  public: |  public: | ||||||
|   // Optimized for code size on a 8-bit AVR |   // Optimized for code size on a 8-bit AVR | ||||||
|   static char escapeChar(char c) { |   static char escapeChar(char c) { | ||||||
|     const char *p = _escapeTable; |     const char *p = escapeTable(false); | ||||||
|     while (p[0] && p[1] != c) { |     while (p[0] && p[1] != c) { | ||||||
|       p += 2; |       p += 2; | ||||||
|     } |     } | ||||||
| @@ -25,7 +25,7 @@ class Encoding { | |||||||
|  |  | ||||||
|   // Optimized for code size on a 8-bit AVR |   // Optimized for code size on a 8-bit AVR | ||||||
|   static char unescapeChar(char c) { |   static char unescapeChar(char c) { | ||||||
|     const char *p = _escapeTable + 4; |     const char *p = escapeTable(true); | ||||||
|     for (;;) { |     for (;;) { | ||||||
|       if (p[0] == '\0') return c; |       if (p[0] == '\0') return c; | ||||||
|       if (p[0] == c) return p[1]; |       if (p[0] == c) return p[1]; | ||||||
| @@ -34,7 +34,9 @@ class Encoding { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   static const char _escapeTable[]; |   static const char *escapeTable(bool excludeIdenticals) { | ||||||
|  |     return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0]; | ||||||
|  |   } | ||||||
| }; | }; | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -23,7 +23,13 @@ class IndentedPrint : public Print { | |||||||
|     isNewLine = true; |     isNewLine = true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   virtual size_t write(uint8_t); |   virtual size_t write(uint8_t c) { | ||||||
|  |     size_t n = 0; | ||||||
|  |     if (isNewLine) n += writeTabs(); | ||||||
|  |     n += sink->write(c); | ||||||
|  |     isNewLine = c == '\n'; | ||||||
|  |     return n; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Adds one level of indentation |   // Adds one level of indentation | ||||||
|   void indent() { |   void indent() { | ||||||
| @@ -46,7 +52,11 @@ class IndentedPrint : public Print { | |||||||
|   uint8_t tabSize : 3; |   uint8_t tabSize : 3; | ||||||
|   bool isNewLine : 1; |   bool isNewLine : 1; | ||||||
|  |  | ||||||
|   size_t writeTabs(); |   size_t writeTabs() { | ||||||
|  |     size_t n = 0; | ||||||
|  |     for (int i = 0; i < level * tabSize; i++) n += sink->write(' '); | ||||||
|  |     return n; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   static const int MAX_LEVEL = 15;    // because it's only 4 bits |   static const int MAX_LEVEL = 15;    // because it's only 4 bits | ||||||
|   static const int MAX_TAB_SIZE = 7;  // because it's only 3 bits |   static const int MAX_TAB_SIZE = 7;  // because it's only 3 bits | ||||||
|   | |||||||
| @@ -44,6 +44,19 @@ class JsonParser { | |||||||
|   inline bool parseObjectTo(JsonVariant *destination); |   inline bool parseObjectTo(JsonVariant *destination); | ||||||
|   inline bool parseStringTo(JsonVariant *destination); |   inline bool parseStringTo(JsonVariant *destination); | ||||||
|  |  | ||||||
|  |   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') || c == '-' || c == '.'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static inline bool isQuote(char c) { | ||||||
|  |     return c == '\'' || c == '\"'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   JsonBuffer *_buffer; |   JsonBuffer *_buffer; | ||||||
|   const char *_readPtr; |   const char *_readPtr; | ||||||
|   char *_writePtr; |   char *_writePtr; | ||||||
|   | |||||||
| @@ -5,18 +5,10 @@ | |||||||
| // https://github.com/bblanchon/ArduinoJson | // https://github.com/bblanchon/ArduinoJson | ||||||
| // If you like this project, please add a star! | // If you like this project, please add a star! | ||||||
| 
 | 
 | ||||||
| #include "../../include/ArduinoJson/Internals/JsonParser.hpp" | #include "JsonParser.hpp" | ||||||
|  | #include "Comments.hpp" | ||||||
| 
 | 
 | ||||||
| #include "../../include/ArduinoJson/Internals/Comments.hpp" | inline bool ArduinoJson::Internals::JsonParser::skip(char charToSkip) { | ||||||
| #include "../../include/ArduinoJson/Internals/Encoding.hpp" |  | ||||||
| #include "../../include/ArduinoJson/JsonArray.hpp" |  | ||||||
| #include "../../include/ArduinoJson/JsonBuffer.hpp" |  | ||||||
| #include "../../include/ArduinoJson/JsonObject.hpp" |  | ||||||
| 
 |  | ||||||
| using namespace ArduinoJson; |  | ||||||
| using namespace ArduinoJson::Internals; |  | ||||||
| 
 |  | ||||||
| bool JsonParser::skip(char charToSkip) { |  | ||||||
|   const char *ptr = skipSpacesAndComments(_readPtr); |   const char *ptr = skipSpacesAndComments(_readPtr); | ||||||
|   if (*ptr != charToSkip) return false; |   if (*ptr != charToSkip) return false; | ||||||
|   ptr++; |   ptr++; | ||||||
| @@ -24,7 +16,8 @@ bool JsonParser::skip(char charToSkip) { | |||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool JsonParser::parseAnythingTo(JsonVariant *destination) { | inline bool ArduinoJson::Internals::JsonParser::parseAnythingTo( | ||||||
|  |     JsonVariant *destination) { | ||||||
|   if (_nestingLimit == 0) return false; |   if (_nestingLimit == 0) return false; | ||||||
|   _nestingLimit--; |   _nestingLimit--; | ||||||
|   bool success = parseAnythingToUnsafe(destination); |   bool success = parseAnythingToUnsafe(destination); | ||||||
| @@ -32,7 +25,8 @@ bool JsonParser::parseAnythingTo(JsonVariant *destination) { | |||||||
|   return success; |   return success; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) { | inline bool ArduinoJson::Internals::JsonParser::parseAnythingToUnsafe( | ||||||
|  |     JsonVariant *destination) { | ||||||
|   _readPtr = skipSpacesAndComments(_readPtr); |   _readPtr = skipSpacesAndComments(_readPtr); | ||||||
| 
 | 
 | ||||||
|   switch (*_readPtr) { |   switch (*_readPtr) { | ||||||
| @@ -47,7 +41,8 @@ inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| JsonArray &JsonParser::parseArray() { | inline ArduinoJson::JsonArray & | ||||||
|  | ArduinoJson::Internals::JsonParser::parseArray() { | ||||||
|   // Create an empty array |   // Create an empty array | ||||||
|   JsonArray &array = _buffer->createArray(); |   JsonArray &array = _buffer->createArray(); | ||||||
| 
 | 
 | ||||||
| @@ -78,7 +73,8 @@ ERROR_NO_MEMORY: | |||||||
|   return JsonArray::invalid(); |   return JsonArray::invalid(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool JsonParser::parseArrayTo(JsonVariant *destination) { | inline bool ArduinoJson::Internals::JsonParser::parseArrayTo( | ||||||
|  |     JsonVariant *destination) { | ||||||
|   JsonArray &array = parseArray(); |   JsonArray &array = parseArray(); | ||||||
|   if (!array.success()) return false; |   if (!array.success()) return false; | ||||||
| 
 | 
 | ||||||
| @@ -86,7 +82,8 @@ bool JsonParser::parseArrayTo(JsonVariant *destination) { | |||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| JsonObject &JsonParser::parseObject() { | inline ArduinoJson::JsonObject & | ||||||
|  | ArduinoJson::Internals::JsonParser::parseObject() { | ||||||
|   // Create an empty object |   // Create an empty object | ||||||
|   JsonObject &object = _buffer->createObject(); |   JsonObject &object = _buffer->createObject(); | ||||||
| 
 | 
 | ||||||
| @@ -124,7 +121,8 @@ ERROR_NO_MEMORY: | |||||||
|   return JsonObject::invalid(); |   return JsonObject::invalid(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool JsonParser::parseObjectTo(JsonVariant *destination) { | inline bool ArduinoJson::Internals::JsonParser::parseObjectTo( | ||||||
|  |     JsonVariant *destination) { | ||||||
|   JsonObject &object = parseObject(); |   JsonObject &object = parseObject(); | ||||||
|   if (!object.success()) return false; |   if (!object.success()) return false; | ||||||
| 
 | 
 | ||||||
| @@ -132,18 +130,7 @@ bool JsonParser::parseObjectTo(JsonVariant *destination) { | |||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline bool isInRange(char c, char min, char max) { | inline const char *ArduinoJson::Internals::JsonParser::parseString() { | ||||||
|   return min <= c && c <= max; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline bool isLetterOrNumber(char c) { |  | ||||||
|   return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') || |  | ||||||
|          isInRange(c, 'A', 'Z') || c == '-' || c == '.'; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline bool isQuote(char c) { return c == '\'' || c == '\"'; } |  | ||||||
| 
 |  | ||||||
| const char *JsonParser::parseString() { |  | ||||||
|   const char *readPtr = _readPtr; |   const char *readPtr = _readPtr; | ||||||
|   char *writePtr = _writePtr; |   char *writePtr = _writePtr; | ||||||
| 
 | 
 | ||||||
| @@ -188,7 +175,8 @@ const char *JsonParser::parseString() { | |||||||
|   return startPtr; |   return startPtr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool JsonParser::parseStringTo(JsonVariant *destination) { | inline bool ArduinoJson::Internals::JsonParser::parseStringTo( | ||||||
|  |     JsonVariant *destination) { | ||||||
|   bool hasQuotes = isQuote(_readPtr[0]); |   bool hasQuotes = isQuote(_readPtr[0]); | ||||||
|   const char *value = parseString(); |   const char *value = parseString(); | ||||||
|   if (value == NULL) return false; |   if (value == NULL) return false; | ||||||
| @@ -7,12 +7,12 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include "../Polyfills/attributes.hpp" | ||||||
| #include "../Polyfills/isInfinity.hpp" | #include "../Polyfills/isInfinity.hpp" | ||||||
| #include "../Polyfills/isNaN.hpp" | #include "../Polyfills/isNaN.hpp" | ||||||
| #include "../Polyfills/normalize.hpp" | #include "../Polyfills/normalize.hpp" | ||||||
| #include "../Print.hpp" | #include "../Print.hpp" | ||||||
| #include "Encoding.hpp" | #include "Encoding.hpp" | ||||||
| #include "ForceInline.hpp" |  | ||||||
| #include "JsonFloat.hpp" | #include "JsonFloat.hpp" | ||||||
| #include "JsonInteger.hpp" | #include "JsonInteger.hpp" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -36,21 +36,56 @@ class List { | |||||||
|   // Would return false in the following situation: |   // Would return false in the following situation: | ||||||
|   // - the memory allocation failed (StaticJsonBuffer was too small) |   // - the memory allocation failed (StaticJsonBuffer was too small) | ||||||
|   // - the JSON parsing failed |   // - the JSON parsing failed | ||||||
|   bool success() const { return _buffer != NULL; } |   bool success() const { | ||||||
|  |     return _buffer != NULL; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Returns the numbers of elements in the list. |   // Returns the numbers of elements in the list. | ||||||
|   // For a JsonObject, it would return the number of key-value pairs |   // For a JsonObject, it would return the number of key-value pairs | ||||||
|   size_t size() const; |   size_t size() const { | ||||||
|  |     size_t nodeCount = 0; | ||||||
|  |     for (node_type *node = _firstNode; node; node = node->next) nodeCount++; | ||||||
|  |     return nodeCount; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   iterator begin() { return iterator(_firstNode); } |   iterator begin() { | ||||||
|   iterator end() { return iterator(NULL); } |     return iterator(_firstNode); | ||||||
|  |   } | ||||||
|  |   iterator end() { | ||||||
|  |     return iterator(NULL); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   const_iterator begin() const { return const_iterator(_firstNode); } |   const_iterator begin() const { | ||||||
|   const_iterator end() const { return const_iterator(NULL); } |     return const_iterator(_firstNode); | ||||||
|  |   } | ||||||
|  |   const_iterator end() const { | ||||||
|  |     return const_iterator(NULL); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   node_type *addNewNode(); |   node_type *addNewNode() { | ||||||
|   void removeNode(node_type *nodeToRemove); |     node_type *newNode = new (_buffer) node_type(); | ||||||
|  |  | ||||||
|  |     if (_firstNode) { | ||||||
|  |       node_type *lastNode = _firstNode; | ||||||
|  |       while (lastNode->next) lastNode = lastNode->next; | ||||||
|  |       lastNode->next = newNode; | ||||||
|  |     } else { | ||||||
|  |       _firstNode = newNode; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return newNode; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void removeNode(node_type *nodeToRemove) { | ||||||
|  |     if (!nodeToRemove) return; | ||||||
|  |     if (nodeToRemove == _firstNode) { | ||||||
|  |       _firstNode = nodeToRemove->next; | ||||||
|  |     } else { | ||||||
|  |       for (node_type *node = _firstNode; node; node = node->next) | ||||||
|  |         if (node->next == nodeToRemove) node->next = nodeToRemove->next; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   JsonBuffer *_buffer; |   JsonBuffer *_buffer; | ||||||
|   node_type *_firstNode; |   node_type *_firstNode; | ||||||
|   | |||||||
| @@ -20,24 +20,89 @@ class Prettyfier : public Print { | |||||||
|     _inString = false; |     _inString = false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   virtual size_t write(uint8_t); |   virtual size_t write(uint8_t c) { | ||||||
|  |     size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c); | ||||||
|  |     _previousChar = c; | ||||||
|  |     return n; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   Prettyfier& operator=(const Prettyfier&);  // cannot be assigned |   Prettyfier& operator=(const Prettyfier&);  // cannot be assigned | ||||||
|  |  | ||||||
|   bool inEmptyBlock() { return _previousChar == '{' || _previousChar == '['; } |   bool inEmptyBlock() { | ||||||
|  |     return _previousChar == '{' || _previousChar == '['; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   size_t handleStringChar(uint8_t); |   size_t handleStringChar(uint8_t c) { | ||||||
|   size_t handleMarkupChar(uint8_t); |     bool isQuote = c == '"' && _previousChar != '\\'; | ||||||
|  |  | ||||||
|   size_t handleBlockClose(uint8_t); |     if (isQuote) _inString = false; | ||||||
|   size_t handleBlockOpen(uint8_t); |  | ||||||
|   size_t handleColon(); |     return _sink.write(c); | ||||||
|   size_t handleComma(); |   } | ||||||
|   size_t handleQuoteOpen(); |  | ||||||
|   size_t handleNormalChar(uint8_t); |   size_t handleMarkupChar(uint8_t c) { | ||||||
|   size_t indentIfNeeded(); |     switch (c) { | ||||||
|   size_t unindentIfNeeded(); |       case '{': | ||||||
|  |       case '[': | ||||||
|  |         return writeBlockOpen(c); | ||||||
|  |  | ||||||
|  |       case '}': | ||||||
|  |       case ']': | ||||||
|  |         return writeBlockClose(c); | ||||||
|  |  | ||||||
|  |       case ':': | ||||||
|  |         return writeColon(); | ||||||
|  |  | ||||||
|  |       case ',': | ||||||
|  |         return writeComma(); | ||||||
|  |  | ||||||
|  |       case '"': | ||||||
|  |         return writeQuoteOpen(); | ||||||
|  |  | ||||||
|  |       default: | ||||||
|  |         return writeNormalChar(c); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t writeBlockClose(uint8_t c) { | ||||||
|  |     return unindentIfNeeded() + _sink.write(c); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t writeBlockOpen(uint8_t c) { | ||||||
|  |     return indentIfNeeded() + _sink.write(c); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t writeColon() { | ||||||
|  |     return _sink.write(':') + _sink.write(' '); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t writeComma() { | ||||||
|  |     return _sink.write(',') + _sink.println(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t writeQuoteOpen() { | ||||||
|  |     _inString = true; | ||||||
|  |     return indentIfNeeded() + _sink.write('"'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t writeNormalChar(uint8_t c) { | ||||||
|  |     return indentIfNeeded() + _sink.write(c); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t indentIfNeeded() { | ||||||
|  |     if (!inEmptyBlock()) return 0; | ||||||
|  |  | ||||||
|  |     _sink.indent(); | ||||||
|  |     return _sink.println(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t unindentIfNeeded() { | ||||||
|  |     if (inEmptyBlock()) return 0; | ||||||
|  |  | ||||||
|  |     _sink.unindent(); | ||||||
|  |     return _sink.println(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   uint8_t _previousChar; |   uint8_t _previousChar; | ||||||
|   IndentedPrint& _sink; |   IndentedPrint& _sink; | ||||||
|   | |||||||
| @@ -20,7 +20,13 @@ class StaticStringBuilder : public Print { | |||||||
|     buffer[0] = '\0'; |     buffer[0] = '\0'; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   virtual size_t write(uint8_t c); |   virtual size_t write(uint8_t c) { | ||||||
|  |     if (length >= capacity) return 0; | ||||||
|  |  | ||||||
|  |     buffer[length++] = c; | ||||||
|  |     buffer[length] = '\0'; | ||||||
|  |     return 1; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   char *buffer; |   char *buffer; | ||||||
|   | |||||||
| @@ -56,10 +56,12 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|       : Internals::List<JsonVariant>(buffer) {} |       : Internals::List<JsonVariant>(buffer) {} | ||||||
|  |  | ||||||
|   // Gets the value at the specified index |   // Gets the value at the specified index | ||||||
|   FORCE_INLINE JsonVariant operator[](size_t index) const; |   JsonVariant operator[](size_t index) const { | ||||||
|  |     return get(index); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Gets or sets the value at specified index |   // Gets or sets the value at specified index | ||||||
|   FORCE_INLINE JsonArraySubscript operator[](size_t index); |   JsonArraySubscript operator[](size_t index); | ||||||
|  |  | ||||||
|   // Adds the specified value at the end of the array. |   // Adds the specified value at the end of the array. | ||||||
|   // |   // | ||||||
| @@ -72,7 +74,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   // bool add(double value); |   // bool add(double value); | ||||||
|   // bool add(const char*); |   // bool add(const char*); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool add( |   bool add( | ||||||
|       T value, |       T value, | ||||||
|       typename TypeTraits::EnableIf< |       typename TypeTraits::EnableIf< | ||||||
|           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) { |           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) { | ||||||
| @@ -83,18 +85,16 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   // bool add(JsonArray&); |   // bool add(JsonArray&); | ||||||
|   // bool add(JsonObject&); |   // bool add(JsonObject&); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool add( |   bool add(const T &value, | ||||||
|       const T &value, |            typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) { | ||||||
|       typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) { |  | ||||||
|     return addNode<T &>(const_cast<T &>(value)); |     return addNode<T &>(const_cast<T &>(value)); | ||||||
|   } |   } | ||||||
|   // bool add(float value, uint8_t decimals); |   // bool add(float value, uint8_t decimals); | ||||||
|   // bool add(double value, uint8_t decimals); |   // bool add(double value, uint8_t decimals); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool add( |   bool add(T value, uint8_t decimals, | ||||||
|       T value, uint8_t decimals, |            typename TypeTraits::EnableIf< | ||||||
|       typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value>::type |                TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { | ||||||
|           * = 0) { |  | ||||||
|     return addNode<JsonVariant>(JsonVariant(value, decimals)); |     return addNode<JsonVariant>(JsonVariant(value, decimals)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -105,7 +105,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   // bool set(size_t index, int value); |   // bool set(size_t index, int value); | ||||||
|   // bool set(size_t index, short value); |   // bool set(size_t index, short value); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool set( |   bool set( | ||||||
|       size_t index, T value, |       size_t index, T value, | ||||||
|       typename TypeTraits::EnableIf< |       typename TypeTraits::EnableIf< | ||||||
|           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) { |           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) { | ||||||
| @@ -116,31 +116,38 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   // bool set(size_t index, JsonArray&); |   // bool set(size_t index, JsonArray&); | ||||||
|   // bool set(size_t index, JsonObject&); |   // bool set(size_t index, JsonObject&); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool set( |   bool set(size_t index, const T &value, | ||||||
|       size_t index, const T &value, |            typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) { | ||||||
|       typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) { |  | ||||||
|     return setNodeAt<T &>(index, const_cast<T &>(value)); |     return setNodeAt<T &>(index, const_cast<T &>(value)); | ||||||
|   } |   } | ||||||
|   // bool set(size_t index, float value, uint8_t decimals = 2); |   // bool set(size_t index, float value, uint8_t decimals = 2); | ||||||
|   // bool set(size_t index, double value, uint8_t decimals = 2); |   // bool set(size_t index, double value, uint8_t decimals = 2); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool set( |   bool set(size_t index, T value, uint8_t decimals, | ||||||
|       size_t index, T value, uint8_t decimals, |            typename TypeTraits::EnableIf< | ||||||
|       typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value>::type |                TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { | ||||||
|           * = 0) { |  | ||||||
|     return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals)); |     return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Gets the value at the specified index. |   // Gets the value at the specified index. | ||||||
|   FORCE_INLINE JsonVariant get(size_t index) const; |   JsonVariant get(size_t index) const { | ||||||
|  |     node_type *node = getNodeAt(index); | ||||||
|  |     return node ? node->content : JsonVariant(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Gets the value at the specified index. |   // Gets the value at the specified index. | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE T get(size_t index) const; |   T get(size_t index) const { | ||||||
|  |     node_type *node = getNodeAt(index); | ||||||
|  |     return node ? node->content.as<T>() : JsonVariant::defaultValue<T>(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Check the type of the value at specified index. |   // Check the type of the value at specified index. | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool is(size_t index) const; |   bool is(size_t index) const { | ||||||
|  |     node_type *node = getNodeAt(index); | ||||||
|  |     return node ? node->content.is<T>() : false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Creates a JsonArray and adds a reference at the end of the array. |   // Creates a JsonArray and adds a reference at the end of the array. | ||||||
|   // It's a shortcut for JsonBuffer::createArray() and JsonArray::add() |   // It's a shortcut for JsonBuffer::createArray() and JsonArray::add() | ||||||
| @@ -151,15 +158,34 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   JsonObject &createNestedObject(); |   JsonObject &createNestedObject(); | ||||||
|  |  | ||||||
|   // Removes element at specified index. |   // Removes element at specified index. | ||||||
|   void removeAt(size_t index); |   void removeAt(size_t index) { | ||||||
|  |     removeNode(getNodeAt(index)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Returns a reference an invalid JsonArray. |   // Returns a reference an invalid JsonArray. | ||||||
|   // This object is meant to replace a NULL pointer. |   // This object is meant to replace a NULL pointer. | ||||||
|   // This is used when memory allocation or JSON parsing fail. |   // This is used when memory allocation or JSON parsing fail. | ||||||
|   static JsonArray &invalid() { return _invalid; } |   static JsonArray &invalid() { | ||||||
|  |     static JsonArray instance(NULL); | ||||||
|  |     return instance; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Serialize the array to the specified JsonWriter. |   // Serialize the array to the specified JsonWriter. | ||||||
|   void writeTo(Internals::JsonWriter &writer) const; |   void writeTo(Internals::JsonWriter &writer) const { | ||||||
|  |     writer.beginArray(); | ||||||
|  |  | ||||||
|  |     const node_type *child = _firstNode; | ||||||
|  |     while (child) { | ||||||
|  |       child->content.writeTo(writer); | ||||||
|  |  | ||||||
|  |       child = child->next; | ||||||
|  |       if (!child) break; | ||||||
|  |  | ||||||
|  |       writer.writeComma(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     writer.endArray(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Imports a 1D array |   // Imports a 1D array | ||||||
|   template <typename T, size_t N> |   template <typename T, size_t N> | ||||||
| @@ -215,20 +241,28 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   node_type *getNodeAt(size_t index) const; |   node_type *getNodeAt(size_t index) const { | ||||||
|  |     node_type *node = _firstNode; | ||||||
|  |     while (node && index--) node = node->next; | ||||||
|  |     return node; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   bool setNodeAt(size_t index, TValue value); |   bool setNodeAt(size_t index, TValue value) { | ||||||
|  |     node_type *node = getNodeAt(index); | ||||||
|  |     return node != NULL && setNodeValue<TValue>(node, value); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   bool addNode(TValue); |   bool addNode(TValue value) { | ||||||
|  |     node_type *node = addNewNode(); | ||||||
|  |     return node != NULL && setNodeValue<TValue>(node, value); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool setNodeValue(node_type *, T value); |   bool setNodeValue(node_type *node, T value) { | ||||||
|  |     node->content = value; | ||||||
|   // The instance returned by JsonArray::invalid() |     return true; | ||||||
|   static JsonArray _invalid; |   } | ||||||
| }; | }; | ||||||
| } | } | ||||||
|  |  | ||||||
| #include "JsonArray.ipp" |  | ||||||
|   | |||||||
| @@ -13,32 +13,6 @@ | |||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| inline JsonArraySubscript JsonArray::operator[](size_t index) { |  | ||||||
|   return JsonArraySubscript(*this, index); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant JsonArray::operator[](size_t index) const { |  | ||||||
|   return get(index); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename TValue> |  | ||||||
| inline bool JsonArray::addNode(TValue value) { |  | ||||||
|   node_type *node = addNewNode(); |  | ||||||
|   return node != NULL && setNodeValue<TValue>(node, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename TValue> |  | ||||||
| inline bool JsonArray::setNodeAt(size_t index, TValue value) { |  | ||||||
|   node_type *node = getNodeAt(index); |  | ||||||
|   return node != NULL && setNodeValue<TValue>(node, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename TValue> |  | ||||||
| inline bool JsonArray::setNodeValue(node_type *node, TValue value) { |  | ||||||
|   node->content = value; |  | ||||||
|   return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> | template <> | ||||||
| inline bool JsonArray::setNodeValue(node_type *node, String &value) { | inline bool JsonArray::setNodeValue(node_type *node, String &value) { | ||||||
|   const char *copy = _buffer->strdup(value); |   const char *copy = _buffer->strdup(value); | ||||||
| @@ -47,29 +21,6 @@ inline bool JsonArray::setNodeValue(node_type *node, String &value) { | |||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonVariant JsonArray::get(size_t index) const { |  | ||||||
|   node_type *node = getNodeAt(index); |  | ||||||
|   return node ? node->content : JsonVariant(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline T JsonArray::get(size_t index) const { |  | ||||||
|   node_type *node = getNodeAt(index); |  | ||||||
|   return node ? node->content.as<T>() : JsonVariant::defaultValue<T>(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline bool JsonArray::is(size_t index) const { |  | ||||||
|   node_type *node = getNodeAt(index); |  | ||||||
|   return node ? node->content.is<T>() : false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename TImplem> |  | ||||||
| inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[]( |  | ||||||
|     int index) const { |  | ||||||
|   return asArray()[index]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> | template <> | ||||||
| inline JsonArray &JsonVariant::defaultValue<JsonArray &>() { | inline JsonArray &JsonVariant::defaultValue<JsonArray &>() { | ||||||
|   return JsonArray::invalid(); |   return JsonArray::invalid(); | ||||||
|   | |||||||
| @@ -77,6 +77,16 @@ inline std::ostream& operator<<(std::ostream& os, | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | inline JsonArraySubscript JsonArray::operator[](size_t index) { | ||||||
|  |   return JsonArraySubscript(*this, index); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TImplem> | ||||||
|  | inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[]( | ||||||
|  |     int index) const { | ||||||
|  |   return asArray()[index]; | ||||||
|  | } | ||||||
|  |  | ||||||
| }  // namespace ArduinoJson | }  // namespace ArduinoJson | ||||||
|  |  | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
|   | |||||||
							
								
								
									
										44
									
								
								include/ArduinoJson/JsonBuffer.ipp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								include/ArduinoJson/JsonBuffer.ipp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #include "Internals/JsonParser.hpp" | ||||||
|  |  | ||||||
|  | inline ArduinoJson::JsonArray &ArduinoJson::JsonBuffer::createArray() { | ||||||
|  |   JsonArray *ptr = new (this) JsonArray(this); | ||||||
|  |   return ptr ? *ptr : JsonArray::invalid(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline ArduinoJson::JsonObject &ArduinoJson::JsonBuffer::createObject() { | ||||||
|  |   JsonObject *ptr = new (this) JsonObject(this); | ||||||
|  |   return ptr ? *ptr : JsonObject::invalid(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline ArduinoJson::JsonArray &ArduinoJson::JsonBuffer::parseArray( | ||||||
|  |     char *json, uint8_t nestingLimit) { | ||||||
|  |   Internals::JsonParser parser(this, json, nestingLimit); | ||||||
|  |   return parser.parseArray(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline ArduinoJson::JsonObject &ArduinoJson::JsonBuffer::parseObject( | ||||||
|  |     char *json, uint8_t nestingLimit) { | ||||||
|  |   Internals::JsonParser parser(this, json, nestingLimit); | ||||||
|  |   return parser.parseObject(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline ArduinoJson::JsonVariant ArduinoJson::JsonBuffer::parse( | ||||||
|  |     char *json, uint8_t nestingLimit) { | ||||||
|  |   Internals::JsonParser parser(this, json, nestingLimit); | ||||||
|  |   return parser.parseVariant(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline char *ArduinoJson::JsonBuffer::strdup(const char *source, | ||||||
|  |                                              size_t length) { | ||||||
|  |   size_t size = length + 1; | ||||||
|  |   char *dest = static_cast<char *>(alloc(size)); | ||||||
|  |   if (dest != NULL) memcpy(dest, source, size); | ||||||
|  |   return dest; | ||||||
|  | } | ||||||
| @@ -52,15 +52,16 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // Create an empty JsonArray attached to the specified JsonBuffer. |   // Create an empty JsonArray attached to the specified JsonBuffer. | ||||||
|   // You should not use this constructor directly. |   // You should not use this constructor directly. | ||||||
|   // Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject(). |   // Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject(). | ||||||
|   FORCE_INLINE explicit JsonObject(JsonBuffer* buffer) |   explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {} | ||||||
|       : Internals::List<JsonPair>(buffer) {} |  | ||||||
|  |  | ||||||
|   // Gets or sets the value associated with the specified key. |   // Gets or sets the value associated with the specified key. | ||||||
|   FORCE_INLINE JsonObjectSubscript<const char*> operator[](const char* key); |   JsonObjectSubscript<const char*> operator[](const char* key); | ||||||
|   FORCE_INLINE JsonObjectSubscript<const String&> operator[](const String& key); |   JsonObjectSubscript<const String&> operator[](const String& key); | ||||||
|  |  | ||||||
|   // Gets the value associated with the specified key. |   // Gets the value associated with the specified key. | ||||||
|   FORCE_INLINE JsonVariant operator[](JsonObjectKey key) const; |   JsonVariant operator[](JsonObjectKey key) const { | ||||||
|  |     return get(key); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Sets the specified key with the specified value. |   // Sets the specified key with the specified value. | ||||||
|   // bool set(TKey key, bool value); |   // bool set(TKey key, bool value); | ||||||
| @@ -73,7 +74,7 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // bool set(TKey key, const char* value); |   // bool set(TKey key, const char* value); | ||||||
|   // bool set(TKey key, RawJson value); |   // bool set(TKey key, RawJson value); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool set( |   bool set( | ||||||
|       JsonObjectKey key, T value, |       JsonObjectKey key, T value, | ||||||
|       typename TypeTraits::EnableIf< |       typename TypeTraits::EnableIf< | ||||||
|           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type* = 0) { |           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type* = 0) { | ||||||
| @@ -84,71 +85,117 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // bool set(Key, JsonObject&); |   // bool set(Key, JsonObject&); | ||||||
|   // bool set(Key, JsonVariant&); |   // bool set(Key, JsonVariant&); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool set( |   bool set(JsonObjectKey key, const T& value, | ||||||
|       JsonObjectKey key, const T& value, |            typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) { | ||||||
|       typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) { |  | ||||||
|     return setNodeAt<T&>(key, const_cast<T&>(value)); |     return setNodeAt<T&>(key, const_cast<T&>(value)); | ||||||
|   } |   } | ||||||
|   // bool set(Key, float value, uint8_t decimals); |   // bool set(Key, float value, uint8_t decimals); | ||||||
|   // bool set(Key, double value, uint8_t decimals); |   // bool set(Key, double value, uint8_t decimals); | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set( |   bool set(JsonObjectKey key, TValue value, uint8_t decimals, | ||||||
|       JsonObjectKey key, TValue value, uint8_t decimals, |            typename TypeTraits::EnableIf< | ||||||
|       typename TypeTraits::EnableIf< |                TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) { | ||||||
|           TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) { |  | ||||||
|     return setNodeAt<const JsonVariant&>(key, JsonVariant(value, decimals)); |     return setNodeAt<const JsonVariant&>(key, JsonVariant(value, decimals)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Gets the value associated with the specified key. |   // Gets the value associated with the specified key. | ||||||
|   FORCE_INLINE JsonVariant get(JsonObjectKey) const; |   JsonVariant get(JsonObjectKey key) const { | ||||||
|  |     node_type* node = getNodeAt(key.c_str()); | ||||||
|  |     return node ? node->content.value : JsonVariant(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Gets the value associated with the specified key. |   // Gets the value associated with the specified key. | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE T get(JsonObjectKey) const; |   T get(JsonObjectKey key) const { | ||||||
|  |     node_type* node = getNodeAt(key.c_str()); | ||||||
|  |     return node ? node->content.value.as<T>() : JsonVariant::defaultValue<T>(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Checks the type of the value associated with the specified key. |   // Checks the type of the value associated with the specified key. | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool is(JsonObjectKey) const; |   bool is(JsonObjectKey key) const { | ||||||
|  |     node_type* node = getNodeAt(key.c_str()); | ||||||
|  |     return node ? node->content.value.is<T>() : false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Creates and adds a JsonArray. |   // Creates and adds a JsonArray. | ||||||
|   // This is a shortcut for JsonBuffer::createArray() and JsonObject::add(). |   // This is a shortcut for JsonBuffer::createArray() and JsonObject::add(). | ||||||
|   FORCE_INLINE JsonArray& createNestedArray(JsonObjectKey key); |   JsonArray& createNestedArray(JsonObjectKey key); | ||||||
|  |  | ||||||
|   // Creates and adds a JsonObject. |   // Creates and adds a JsonObject. | ||||||
|   // This is a shortcut for JsonBuffer::createObject() and JsonObject::add(). |   // This is a shortcut for JsonBuffer::createObject() and JsonObject::add(). | ||||||
|   FORCE_INLINE JsonObject& createNestedObject(JsonObjectKey key); |   JsonObject& createNestedObject(JsonObjectKey key); | ||||||
|  |  | ||||||
|   // Tells weither the specified key is present and associated with a value. |   // Tells weither the specified key is present and associated with a value. | ||||||
|   FORCE_INLINE bool containsKey(JsonObjectKey key) const; |   bool containsKey(JsonObjectKey key) const { | ||||||
|  |     return getNodeAt(key.c_str()) != NULL; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Removes the specified key and the associated value. |   // Removes the specified key and the associated value. | ||||||
|   void remove(JsonObjectKey key); |   void remove(JsonObjectKey key) { | ||||||
|  |     removeNode(getNodeAt(key.c_str())); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Returns a reference an invalid JsonObject. |   // Returns a reference an invalid JsonObject. | ||||||
|   // This object is meant to replace a NULL pointer. |   // This object is meant to replace a NULL pointer. | ||||||
|   // This is used when memory allocation or JSON parsing fail. |   // This is used when memory allocation or JSON parsing fail. | ||||||
|   static JsonObject& invalid() { return _invalid; } |   static JsonObject& invalid() { | ||||||
|  |     static JsonObject instance(NULL); | ||||||
|  |     return instance; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Serialize the object to the specified JsonWriter |   // Serialize the object to the specified JsonWriter | ||||||
|   void writeTo(Internals::JsonWriter& writer) const; |   void writeTo(Internals::JsonWriter& writer) const { | ||||||
|  |     writer.beginObject(); | ||||||
|  |  | ||||||
|  |     const node_type* node = _firstNode; | ||||||
|  |     while (node) { | ||||||
|  |       writer.writeString(node->content.key); | ||||||
|  |       writer.writeColon(); | ||||||
|  |       node->content.value.writeTo(writer); | ||||||
|  |  | ||||||
|  |       node = node->next; | ||||||
|  |       if (!node) break; | ||||||
|  |  | ||||||
|  |       writer.writeComma(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     writer.endObject(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   // Returns the list node that matches the specified key. |   // Returns the list node that matches the specified key. | ||||||
|   node_type* getNodeAt(const char* key) const; |   node_type* getNodeAt(const char* key) const { | ||||||
|  |     for (node_type* node = _firstNode; node; node = node->next) { | ||||||
|   node_type* getOrCreateNodeAt(const char* key); |       if (!strcmp(node->content.key, key)) return node; | ||||||
|  |     } | ||||||
|  |     return NULL; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool setNodeAt(JsonObjectKey key, T value); |   bool setNodeAt(JsonObjectKey key, T value) { | ||||||
|  |     node_type* node = getNodeAt(key.c_str()); | ||||||
|  |     if (!node) { | ||||||
|  |       node = addNewNode(); | ||||||
|  |       if (!node || !setNodeKey(node, key)) return false; | ||||||
|  |     } | ||||||
|  |     return setNodeValue<T>(node, value); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE bool setNodeKey(node_type*, JsonObjectKey key); |   bool setNodeKey(node_type* node, JsonObjectKey key) { | ||||||
|  |     if (key.needs_copy()) { | ||||||
|  |       node->content.key = _buffer->strdup(key.c_str()); | ||||||
|  |       if (node->content.key == NULL) return false; | ||||||
|  |     } else { | ||||||
|  |       node->content.key = key.c_str(); | ||||||
|  |     } | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool setNodeValue(node_type*, T value); |   bool setNodeValue(node_type* node, T value) { | ||||||
|  |     node->content.value = value; | ||||||
|   // The instance returned by JsonObject::invalid() |     return true; | ||||||
|   static JsonObject _invalid; |   } | ||||||
| }; | }; | ||||||
| } | } | ||||||
|  |  | ||||||
| #include "JsonObject.ipp" |  | ||||||
|   | |||||||
| @@ -13,71 +13,6 @@ | |||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| inline JsonVariant JsonObject::get(JsonObjectKey key) const { |  | ||||||
|   node_type *node = getNodeAt(key.c_str()); |  | ||||||
|   return node ? node->content.value : JsonVariant(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline T JsonObject::get(JsonObjectKey key) const { |  | ||||||
|   node_type *node = getNodeAt(key.c_str()); |  | ||||||
|   return node ? node->content.value.as<T>() : JsonVariant::defaultValue<T>(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline bool JsonObject::is(JsonObjectKey key) const { |  | ||||||
|   node_type *node = getNodeAt(key.c_str()); |  | ||||||
|   return node ? node->content.value.is<T>() : false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonObjectSubscript<const char *> JsonObject::operator[]( |  | ||||||
|     const char *key) { |  | ||||||
|   return JsonObjectSubscript<const char *>(*this, key); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonObjectSubscript<const String &> JsonObject::operator[]( |  | ||||||
|     const String &key) { |  | ||||||
|   return JsonObjectSubscript<const String &>(*this, key); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant JsonObject::operator[](JsonObjectKey key) const { |  | ||||||
|   return get(key); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonObject::containsKey(JsonObjectKey key) const { |  | ||||||
|   return getNodeAt(key.c_str()) != NULL; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonObject::remove(JsonObjectKey key) { |  | ||||||
|   removeNode(getNodeAt(key.c_str())); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline bool JsonObject::setNodeAt(JsonObjectKey key, T value) { |  | ||||||
|   node_type *node = getNodeAt(key.c_str()); |  | ||||||
|   if (!node) { |  | ||||||
|     node = addNewNode(); |  | ||||||
|     if (!node || !setNodeKey(node, key)) return false; |  | ||||||
|   } |  | ||||||
|   return setNodeValue<T>(node, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonObject::setNodeKey(node_type *node, JsonObjectKey key) { |  | ||||||
|   if (key.needs_copy()) { |  | ||||||
|     node->content.key = _buffer->strdup(key.c_str()); |  | ||||||
|     if (node->content.key == NULL) return false; |  | ||||||
|   } else { |  | ||||||
|     node->content.key = key.c_str(); |  | ||||||
|   } |  | ||||||
|   return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename TValue> |  | ||||||
| inline bool JsonObject::setNodeValue(node_type *node, TValue value) { |  | ||||||
|   node->content.value = value; |  | ||||||
|   return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> | template <> | ||||||
| inline bool JsonObject::setNodeValue(node_type *node, String &value) { | inline bool JsonObject::setNodeValue(node_type *node, String &value) { | ||||||
|   node->content.value = _buffer->strdup(value); |   node->content.value = _buffer->strdup(value); | ||||||
| @@ -90,18 +25,6 @@ inline bool JsonObject::setNodeValue(node_type *node, const String &value) { | |||||||
|   return node->content.value; |   return node->content.value; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TImplem> |  | ||||||
| inline const JsonObjectSubscript<const char *> JsonVariantBase<TImplem>:: |  | ||||||
| operator[](const char *key) const { |  | ||||||
|   return asObject()[key]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename TImplem> |  | ||||||
| inline const JsonObjectSubscript<const String &> JsonVariantBase<TImplem>:: |  | ||||||
| operator[](const String &key) const { |  | ||||||
|   return asObject()[key]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> | template <> | ||||||
| inline JsonObject const &JsonVariant::defaultValue<JsonObject const &>() { | inline JsonObject const &JsonVariant::defaultValue<JsonObject const &>() { | ||||||
|   return JsonObject::invalid(); |   return JsonObject::invalid(); | ||||||
|   | |||||||
| @@ -45,9 +45,13 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > { | |||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE bool success() const { return _object.containsKey(_key); } |   FORCE_INLINE bool success() const { | ||||||
|  |     return _object.containsKey(_key); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE operator JsonVariant() const { return _object.get(_key); } |   FORCE_INLINE operator JsonVariant() const { | ||||||
|  |     return _object.get(_key); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE TValue as() const { |   FORCE_INLINE TValue as() const { | ||||||
| @@ -69,7 +73,9 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > { | |||||||
|     return _object.set(_key, value, decimals); |     return _object.set(_key, value, decimals); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE JsonVariant get() { return _object.get(_key); } |   FORCE_INLINE JsonVariant get() { | ||||||
|  |     return _object.get(_key); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   void writeTo(Internals::JsonWriter& writer) const { |   void writeTo(Internals::JsonWriter& writer) const { | ||||||
|     _object.get(_key).writeTo(writer); |     _object.get(_key).writeTo(writer); | ||||||
| @@ -92,6 +98,28 @@ inline std::ostream& operator<<( | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | inline JsonObjectSubscript<const char*> JsonObject::operator[]( | ||||||
|  |     const char* key) { | ||||||
|  |   return JsonObjectSubscript<const char*>(*this, key); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline JsonObjectSubscript<const String&> JsonObject::operator[]( | ||||||
|  |     const String& key) { | ||||||
|  |   return JsonObjectSubscript<const String&>(*this, key); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TImplem> | ||||||
|  | inline const JsonObjectSubscript<const char*> JsonVariantBase<TImplem>:: | ||||||
|  | operator[](const char* key) const { | ||||||
|  |   return asObject()[key]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename TImplem> | ||||||
|  | inline const JsonObjectSubscript<const String&> JsonVariantBase<TImplem>:: | ||||||
|  | operator[](const String& key) const { | ||||||
|  |   return asObject()[key]; | ||||||
|  | } | ||||||
|  |  | ||||||
| }  // namespace ArduinoJson | }  // namespace ArduinoJson | ||||||
|  |  | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
|   | |||||||
| @@ -41,11 +41,15 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   struct IsConstructibleFrom; |   struct IsConstructibleFrom; | ||||||
|  |  | ||||||
|   // Creates an uninitialized JsonVariant |   // Creates an uninitialized JsonVariant | ||||||
|   FORCE_INLINE JsonVariant() : _type(Internals::JSON_UNDEFINED) {} |   JsonVariant() : _type(Internals::JSON_UNDEFINED) {} | ||||||
|  |  | ||||||
|   // Create a JsonVariant containing a boolean value. |   // Create a JsonVariant containing a boolean value. | ||||||
|   // It will be serialized as "true" or "false" in JSON. |   // It will be serialized as "true" or "false" in JSON. | ||||||
|   FORCE_INLINE JsonVariant(bool value); |   JsonVariant(bool value) { | ||||||
|  |     using namespace Internals; | ||||||
|  |     _type = JSON_BOOLEAN; | ||||||
|  |     _content.asInteger = static_cast<JsonInteger>(value); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Create a JsonVariant containing a floating point value. |   // Create a JsonVariant containing a floating point value. | ||||||
|   // The second argument specifies the number of decimal digits to write in |   // The second argument specifies the number of decimal digits to write in | ||||||
| @@ -53,10 +57,9 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   // JsonVariant(double value, uint8_t decimals); |   // JsonVariant(double value, uint8_t decimals); | ||||||
|   // JsonVariant(float value, uint8_t decimals); |   // JsonVariant(float value, uint8_t decimals); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE JsonVariant( |   JsonVariant(T value, uint8_t decimals = 2, | ||||||
|       T value, uint8_t decimals = 2, |               typename TypeTraits::EnableIf< | ||||||
|       typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value>::type |                   TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { | ||||||
|           * = 0) { |  | ||||||
|     using namespace Internals; |     using namespace Internals; | ||||||
|     _type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals); |     _type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals); | ||||||
|     _content.asFloat = static_cast<JsonFloat>(value); |     _content.asFloat = static_cast<JsonFloat>(value); | ||||||
| @@ -67,9 +70,9 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   // JsonVariant(signed int) |   // JsonVariant(signed int) | ||||||
|   // JsonVariant(signed long) |   // JsonVariant(signed long) | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE JsonVariant( |   JsonVariant(T value, | ||||||
|       T value, typename TypeTraits::EnableIf< |               typename TypeTraits::EnableIf< | ||||||
|                    TypeTraits::IsSignedIntegral<T>::value>::type * = 0) { |                   TypeTraits::IsSignedIntegral<T>::value>::type * = 0) { | ||||||
|     using namespace Internals; |     using namespace Internals; | ||||||
|     if (value >= 0) { |     if (value >= 0) { | ||||||
|       _type = JSON_POSITIVE_INTEGER; |       _type = JSON_POSITIVE_INTEGER; | ||||||
| @@ -83,25 +86,37 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   // JsonVariant(unsigned int) |   // JsonVariant(unsigned int) | ||||||
|   // JsonVariant(unsigned long) |   // JsonVariant(unsigned long) | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE JsonVariant( |   JsonVariant(T value, | ||||||
|       T value, typename TypeTraits::EnableIf< |               typename TypeTraits::EnableIf< | ||||||
|                    TypeTraits::IsUnsignedIntegral<T>::value>::type * = 0) { |                   TypeTraits::IsUnsignedIntegral<T>::value>::type * = 0) { | ||||||
|     using namespace Internals; |     using namespace Internals; | ||||||
|     _type = JSON_POSITIVE_INTEGER; |     _type = JSON_POSITIVE_INTEGER; | ||||||
|     _content.asInteger = static_cast<JsonUInt>(value); |     _content.asInteger = static_cast<JsonUInt>(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Create a JsonVariant containing a string. |   // Create a JsonVariant containing a string. | ||||||
|   FORCE_INLINE JsonVariant(const char *value); |   JsonVariant(const char *value) { | ||||||
|  |     _type = Internals::JSON_STRING; | ||||||
|  |     _content.asString = value; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Create a JsonVariant containing an unparsed string |   // Create a JsonVariant containing an unparsed string | ||||||
|   FORCE_INLINE JsonVariant(RawJson value); |   JsonVariant(RawJson value) { | ||||||
|  |     _type = Internals::JSON_UNPARSED; | ||||||
|  |     _content.asString = value; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Create a JsonVariant containing a reference to an array. |   // Create a JsonVariant containing a reference to an array. | ||||||
|   FORCE_INLINE JsonVariant(JsonArray &array); |   JsonVariant(JsonArray &array) { | ||||||
|  |     _type = Internals::JSON_ARRAY; | ||||||
|  |     _content.asArray = &array; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Create a JsonVariant containing a reference to an object. |   // Create a JsonVariant containing a reference to an object. | ||||||
|   FORCE_INLINE JsonVariant(JsonObject &object); |   JsonVariant(JsonObject &object) { | ||||||
|  |     _type = Internals::JSON_OBJECT; | ||||||
|  |     _content.asObject = &object; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Get the variant as the specified type. |   // Get the variant as the specified type. | ||||||
|   // |   // | ||||||
| @@ -257,7 +272,9 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Returns true if the variant has a value |   // Returns true if the variant has a value | ||||||
|   bool success() const { return _type != Internals::JSON_UNDEFINED; } |   bool success() const { | ||||||
|  |     return _type != Internals::JSON_UNDEFINED; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Serialize the variant to a JsonWriter |   // Serialize the variant to a JsonWriter | ||||||
|   void writeTo(Internals::JsonWriter &writer) const; |   void writeTo(Internals::JsonWriter &writer) const; | ||||||
| @@ -275,9 +292,8 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|  private: |  private: | ||||||
|   // It's not allowed to store a char |   // It's not allowed to store a char | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE JsonVariant(T value, |   JsonVariant(T value, typename TypeTraits::EnableIf< | ||||||
|                            typename TypeTraits::EnableIf< |                            TypeTraits::IsSame<T, char>::value>::type * = 0); | ||||||
|                                TypeTraits::IsSame<T, char>::value>::type * = 0); |  | ||||||
|  |  | ||||||
|   String toString() const; |   String toString() const; | ||||||
|   Internals::JsonFloat asFloat() const; |   Internals::JsonFloat asFloat() const; | ||||||
| @@ -286,9 +302,15 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   bool isBoolean() const; |   bool isBoolean() const; | ||||||
|   bool isFloat() const; |   bool isFloat() const; | ||||||
|   bool isInteger() const; |   bool isInteger() const; | ||||||
|   bool isArray() const { return _type == Internals::JSON_ARRAY; } |   bool isArray() const { | ||||||
|   bool isObject() const { return _type == Internals::JSON_OBJECT; } |     return _type == Internals::JSON_ARRAY; | ||||||
|   bool isString() const { return _type == Internals::JSON_STRING; } |   } | ||||||
|  |   bool isObject() const { | ||||||
|  |     return _type == Internals::JSON_OBJECT; | ||||||
|  |   } | ||||||
|  |   bool isString() const { | ||||||
|  |     return _type == Internals::JSON_STRING; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // The current type of the variant |   // The current type of the variant | ||||||
|   Internals::JsonVariantType _type; |   Internals::JsonVariantType _type; | ||||||
| @@ -328,6 +350,3 @@ struct JsonVariant::IsConstructibleFrom { | |||||||
|       TypeTraits::IsSame<T, const JsonVariant &>::value; |       TypeTraits::IsSame<T, const JsonVariant &>::value; | ||||||
| }; | }; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Include inline implementations |  | ||||||
| #include "JsonVariant.ipp" |  | ||||||
|   | |||||||
| @@ -10,37 +10,15 @@ | |||||||
| #include "Configuration.hpp" | #include "Configuration.hpp" | ||||||
| #include "JsonVariant.hpp" | #include "JsonVariant.hpp" | ||||||
| #include "Internals/Parse.hpp" | #include "Internals/Parse.hpp" | ||||||
|  | #include "JsonArray.hpp" | ||||||
|  | #include "JsonObject.hpp" | ||||||
|  |  | ||||||
| #include <string.h> | #include <string.h>  // for strcmp | ||||||
|  | #include <errno.h>   // for errno | ||||||
|  | #include <stdlib.h>  // for strtol, strtod | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(bool value) { |  | ||||||
|   using namespace Internals; |  | ||||||
|   _type = JSON_BOOLEAN; |  | ||||||
|   _content.asInteger = static_cast<JsonInteger>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(const char *value) { |  | ||||||
|   _type = Internals::JSON_STRING; |  | ||||||
|   _content.asString = value; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(RawJson value) { |  | ||||||
|   _type = Internals::JSON_UNPARSED; |  | ||||||
|   _content.asString = value; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(JsonArray &array) { |  | ||||||
|   _type = Internals::JSON_ARRAY; |  | ||||||
|   _content.asArray = &array; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(JsonObject &object) { |  | ||||||
|   _type = Internals::JSON_OBJECT; |  | ||||||
|   _content.asObject = &object; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline Internals::JsonInteger JsonVariant::asInteger() const { | inline Internals::JsonInteger JsonVariant::asInteger() const { | ||||||
|   using namespace Internals; |   using namespace Internals; | ||||||
|   switch (_type) { |   switch (_type) { | ||||||
| @@ -80,6 +58,119 @@ inline Internals::JsonUInt JsonVariant::asUnsignedInteger() const { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline const char *JsonVariant::asString() const { | ||||||
|  |   using namespace Internals; | ||||||
|  |   if (_type == JSON_UNPARSED && _content.asString && | ||||||
|  |       !strcmp("null", _content.asString)) | ||||||
|  |     return NULL; | ||||||
|  |   if (_type == JSON_STRING || _type == JSON_UNPARSED) return _content.asString; | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline Internals::JsonFloat JsonVariant::asFloat() const { | ||||||
|  |   using namespace Internals; | ||||||
|  |   switch (_type) { | ||||||
|  |     case JSON_UNDEFINED: | ||||||
|  |       return 0; | ||||||
|  |     case JSON_POSITIVE_INTEGER: | ||||||
|  |     case JSON_BOOLEAN: | ||||||
|  |       return static_cast<JsonFloat>(_content.asInteger); | ||||||
|  |     case JSON_NEGATIVE_INTEGER: | ||||||
|  |       return -static_cast<JsonFloat>(_content.asInteger); | ||||||
|  |     case JSON_STRING: | ||||||
|  |     case JSON_UNPARSED: | ||||||
|  |       return _content.asString ? parse<JsonFloat>(_content.asString) : 0; | ||||||
|  |     default: | ||||||
|  |       return _content.asFloat; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline String JsonVariant::toString() const { | ||||||
|  |   using namespace Internals; | ||||||
|  |   String s; | ||||||
|  |   if ((_type == JSON_STRING || _type == JSON_UNPARSED) && | ||||||
|  |       _content.asString != NULL) | ||||||
|  |     s = _content.asString; | ||||||
|  |   else | ||||||
|  |     printTo(s); | ||||||
|  |   return s; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline bool JsonVariant::isBoolean() const { | ||||||
|  |   using namespace Internals; | ||||||
|  |   if (_type == JSON_BOOLEAN) return true; | ||||||
|  |  | ||||||
|  |   if (_type != JSON_UNPARSED || _content.asString == NULL) return false; | ||||||
|  |  | ||||||
|  |   return !strcmp(_content.asString, "true") || | ||||||
|  |          !strcmp(_content.asString, "false"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline bool JsonVariant::isInteger() const { | ||||||
|  |   using namespace Internals; | ||||||
|  |   if (_type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER) | ||||||
|  |     return true; | ||||||
|  |  | ||||||
|  |   if (_type != JSON_UNPARSED || _content.asString == NULL) return false; | ||||||
|  |  | ||||||
|  |   char *end; | ||||||
|  |   errno = 0; | ||||||
|  |   strtol(_content.asString, &end, 10); | ||||||
|  |  | ||||||
|  |   return *end == '\0' && errno == 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline bool JsonVariant::isFloat() const { | ||||||
|  |   using namespace Internals; | ||||||
|  |   if (_type >= JSON_FLOAT_0_DECIMALS) return true; | ||||||
|  |  | ||||||
|  |   if (_type != JSON_UNPARSED || _content.asString == NULL) return false; | ||||||
|  |  | ||||||
|  |   char *end; | ||||||
|  |   errno = 0; | ||||||
|  |   strtod(_content.asString, &end); | ||||||
|  |  | ||||||
|  |   return *end == '\0' && errno == 0 && !is<long>(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void JsonVariant::writeTo(Internals::JsonWriter &writer) const { | ||||||
|  |   using namespace Internals; | ||||||
|  |   switch (_type) { | ||||||
|  |     case JSON_UNDEFINED: | ||||||
|  |       return; | ||||||
|  |  | ||||||
|  |     case JSON_ARRAY: | ||||||
|  |       _content.asArray->writeTo(writer); | ||||||
|  |       return; | ||||||
|  |  | ||||||
|  |     case JSON_OBJECT: | ||||||
|  |       _content.asObject->writeTo(writer); | ||||||
|  |       return; | ||||||
|  |  | ||||||
|  |     case JSON_STRING: | ||||||
|  |       writer.writeString(_content.asString); | ||||||
|  |       return; | ||||||
|  |  | ||||||
|  |     case JSON_UNPARSED: | ||||||
|  |       writer.writeRaw(_content.asString); | ||||||
|  |       return; | ||||||
|  |  | ||||||
|  |     case JSON_NEGATIVE_INTEGER: | ||||||
|  |       writer.writeRaw('-'); | ||||||
|  |     case JSON_POSITIVE_INTEGER: | ||||||
|  |       writer.writeInteger(_content.asInteger); | ||||||
|  |       return; | ||||||
|  |  | ||||||
|  |     case JSON_BOOLEAN: | ||||||
|  |       writer.writeBoolean(_content.asInteger != 0); | ||||||
|  |       return; | ||||||
|  |  | ||||||
|  |     default: | ||||||
|  |       uint8_t decimals = static_cast<uint8_t>(_type - JSON_FLOAT_0_DECIMALS); | ||||||
|  |       writer.writeFloat(_content.asFloat, decimals); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_STD_STREAM | #if ARDUINOJSON_ENABLE_STD_STREAM | ||||||
| inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) { | inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) { | ||||||
|   return source.printTo(os); |   return source.printTo(os); | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "Internals/ForceInline.hpp" | #include "Polyfills/attributes.hpp" | ||||||
| #include "JsonObjectKey.hpp" | #include "JsonObjectKey.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|   | |||||||
| @@ -9,6 +9,8 @@ | |||||||
| 
 | 
 | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
| #define FORCE_INLINE __forceinline | #define FORCE_INLINE __forceinline | ||||||
|  | #define NO_INLINE __declspec(noinline) | ||||||
| #else | #else | ||||||
| #define FORCE_INLINE __attribute__((always_inline)) | #define FORCE_INLINE __attribute__((always_inline)) | ||||||
|  | #define NO_INLINE __attribute__((noinline)) | ||||||
| #endif | #endif | ||||||
| @@ -9,6 +9,16 @@ | |||||||
|  |  | ||||||
| #include "JsonBuffer.hpp" | #include "JsonBuffer.hpp" | ||||||
|  |  | ||||||
|  | #if defined(__clang__) | ||||||
|  | #pragma clang diagnostic push | ||||||
|  | #pragma clang diagnostic ignored "-Wnon-virtual-dtor" | ||||||
|  | #elif defined(__GNUC__) | ||||||
|  | #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) | ||||||
|  | #pragma GCC diagnostic push | ||||||
|  | #endif | ||||||
|  | #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| // Implements a JsonBuffer with fixed memory allocation. | // Implements a JsonBuffer with fixed memory allocation. | ||||||
| @@ -19,8 +29,12 @@ class StaticJsonBuffer : public JsonBuffer { | |||||||
|  public: |  public: | ||||||
|   explicit StaticJsonBuffer() : _size(0) {} |   explicit StaticJsonBuffer() : _size(0) {} | ||||||
|  |  | ||||||
|   size_t capacity() const { return CAPACITY; } |   size_t capacity() const { | ||||||
|   size_t size() const { return _size; } |     return CAPACITY; | ||||||
|  |   } | ||||||
|  |   size_t size() const { | ||||||
|  |     return _size; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   virtual void* alloc(size_t bytes) { |   virtual void* alloc(size_t bytes) { | ||||||
|     if (_size + bytes > CAPACITY) return NULL; |     if (_size + bytes > CAPACITY) return NULL; | ||||||
| @@ -34,3 +48,11 @@ class StaticJsonBuffer : public JsonBuffer { | |||||||
|   size_t _size; |   size_t _size; | ||||||
| }; | }; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #if defined(__clang__) | ||||||
|  | #pragma clang diagnostic pop | ||||||
|  | #elif defined(__GNUC__) | ||||||
|  | #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) | ||||||
|  | #pragma GCC diagnostic pop | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|   | |||||||
| @@ -1,14 +0,0 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2016 |  | ||||||
| // MIT License |  | ||||||
| // |  | ||||||
| // Arduino JSON library |  | ||||||
| // https://github.com/bblanchon/ArduinoJson |  | ||||||
| // If you like this project, please add a star! |  | ||||||
|  |  | ||||||
| // About this file |  | ||||||
| // --------------- |  | ||||||
| // This file is here to please the Arduino IDE. It must be present in the src/ |  | ||||||
| // for the IDE to find it. Feel free to ignore this file if your working in |  | ||||||
| // another environment |  | ||||||
|  |  | ||||||
| #include "../include/ArduinoJson.h" |  | ||||||
| @@ -1,71 +0,0 @@ | |||||||
| # Copyright Benoit Blanchon 2014-2016 |  | ||||||
| # MIT License |  | ||||||
| #  |  | ||||||
| # Arduino JSON library |  | ||||||
| # https://github.com/bblanchon/ArduinoJson |  | ||||||
| # If you like this project, please add a star! |  | ||||||
|  |  | ||||||
| file(GLOB_RECURSE HPP_FILES ../include/*.hpp) |  | ||||||
| file(GLOB_RECURSE IPP_FILES ../include/*.ipp) |  | ||||||
| file(GLOB_RECURSE CPP_FILES *.cpp) |  | ||||||
|  |  | ||||||
| if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") |  | ||||||
| 	add_compile_options( |  | ||||||
| 		-fno-exceptions |  | ||||||
| 		-fno-rtti |  | ||||||
| 		-pedantic |  | ||||||
| 		-Wall |  | ||||||
| 		-Wcast-align |  | ||||||
| 		-Wcast-qual |  | ||||||
| 		-Wconversion |  | ||||||
| 		-Wctor-dtor-privacy |  | ||||||
| 		-Wdisabled-optimization |  | ||||||
| 		-Werror |  | ||||||
| 		-Wextra |  | ||||||
| 		-Wformat=2 |  | ||||||
| 		-Winit-self |  | ||||||
| 		-Wmissing-include-dirs |  | ||||||
| 		-Wno-parentheses |  | ||||||
| 		-Wno-sign-conversion |  | ||||||
| 		-Wno-unused |  | ||||||
| 		-Wno-variadic-macros |  | ||||||
| 		-Wnon-virtual-dtor |  | ||||||
| 		-Wold-style-cast |  | ||||||
| 		-Woverloaded-virtual |  | ||||||
| 		-Wredundant-decls |  | ||||||
| 		-Wshadow |  | ||||||
| 		-Wsign-promo |  | ||||||
| 		-Wstrict-overflow=5 |  | ||||||
| 		-Wundef |  | ||||||
| 	) |  | ||||||
| endif() |  | ||||||
|  |  | ||||||
| if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") |  | ||||||
| 	add_compile_options( |  | ||||||
| 		-Wstrict-null-sentinel |  | ||||||
| 	) |  | ||||||
|  |  | ||||||
| 	if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.5) |  | ||||||
| 		add_compile_options(-Wlogical-op) # the flag exists in 4.4 but is buggy |  | ||||||
| 	endif() |  | ||||||
|  |  | ||||||
| 	if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.6) |  | ||||||
| 		add_compile_options(-Wnoexcept) |  | ||||||
| 	endif() |  | ||||||
| endif() |  | ||||||
|  |  | ||||||
| if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") |  | ||||||
| 	add_compile_options( |  | ||||||
| 		-Wc++11-compat |  | ||||||
| 		-Wdeprecated-register |  | ||||||
| 	) |  | ||||||
| endif() |  | ||||||
|  |  | ||||||
| if(MSVC) |  | ||||||
| 	add_definitions(-D_CRT_SECURE_NO_WARNINGS) |  | ||||||
| 	add_compile_options(-W4) |  | ||||||
| endif() |  | ||||||
|  |  | ||||||
| add_library(ArduinoJson ${CPP_FILES} ${HPP_FILES} ${IPP_FILES}) |  | ||||||
|  |  | ||||||
| target_include_directories(ArduinoJson INTERFACE ${CMAKE_CURRENT_LIST_DIR}/../include) |  | ||||||
| @@ -1,52 +0,0 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2016 |  | ||||||
| // MIT License |  | ||||||
| // |  | ||||||
| // Arduino JSON library |  | ||||||
| // https://github.com/bblanchon/ArduinoJson |  | ||||||
| // If you like this project, please add a star! |  | ||||||
|  |  | ||||||
| #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; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -1,14 +0,0 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2016 |  | ||||||
| // MIT License |  | ||||||
| // |  | ||||||
| // Arduino JSON library |  | ||||||
| // https://github.com/bblanchon/ArduinoJson |  | ||||||
| // If you like this project, please add a star! |  | ||||||
|  |  | ||||||
| #include "../../include/ArduinoJson/Internals/Encoding.hpp" |  | ||||||
|  |  | ||||||
| // How to escape special chars: |  | ||||||
| // _escapeTable[2*i+1] => the special char |  | ||||||
| // _escapeTable[2*i] => the char to use instead |  | ||||||
| const char ArduinoJson::Internals::Encoding::_escapeTable[] = |  | ||||||
|     "\"\"\\\\b\bf\fn\nr\rt\t"; |  | ||||||
| @@ -1,30 +0,0 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2016 |  | ||||||
| // MIT License |  | ||||||
| // |  | ||||||
| // Arduino JSON library |  | ||||||
| // https://github.com/bblanchon/ArduinoJson |  | ||||||
| // If you like this project, please add a star! |  | ||||||
|  |  | ||||||
| #include "../../include/ArduinoJson/Internals/IndentedPrint.hpp" |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson::Internals; |  | ||||||
|  |  | ||||||
| size_t IndentedPrint::write(uint8_t c) { |  | ||||||
|   size_t n = 0; |  | ||||||
|  |  | ||||||
|   if (isNewLine) n += writeTabs(); |  | ||||||
|  |  | ||||||
|   n += sink->write(c); |  | ||||||
|  |  | ||||||
|   isNewLine = c == '\n'; |  | ||||||
|  |  | ||||||
|   return n; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t IndentedPrint::writeTabs() { |  | ||||||
|   size_t n = 0; |  | ||||||
|  |  | ||||||
|   for (int i = 0; i < level * tabSize; i++) n += sink->write(' '); |  | ||||||
|  |  | ||||||
|   return n; |  | ||||||
| } |  | ||||||
| @@ -1,50 +0,0 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2016 |  | ||||||
| // MIT License |  | ||||||
| // |  | ||||||
| // Arduino JSON library |  | ||||||
| // https://github.com/bblanchon/ArduinoJson |  | ||||||
| // If you like this project, please add a star! |  | ||||||
|  |  | ||||||
| #include "../../include/ArduinoJson/Internals/List.hpp" |  | ||||||
|  |  | ||||||
| #include "../../include/ArduinoJson/JsonPair.hpp" |  | ||||||
| #include "../../include/ArduinoJson/JsonVariant.hpp" |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson; |  | ||||||
| using namespace ArduinoJson::Internals; |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| size_t List<T>::size() const { |  | ||||||
|   size_t nodeCount = 0; |  | ||||||
|   for (node_type *node = _firstNode; node; node = node->next) nodeCount++; |  | ||||||
|   return nodeCount; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| typename List<T>::node_type *List<T>::addNewNode() { |  | ||||||
|   node_type *newNode = new (_buffer) node_type(); |  | ||||||
|  |  | ||||||
|   if (_firstNode) { |  | ||||||
|     node_type *lastNode = _firstNode; |  | ||||||
|     while (lastNode->next) lastNode = lastNode->next; |  | ||||||
|     lastNode->next = newNode; |  | ||||||
|   } else { |  | ||||||
|     _firstNode = newNode; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return newNode; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| void List<T>::removeNode(node_type *nodeToRemove) { |  | ||||||
|   if (!nodeToRemove) return; |  | ||||||
|   if (nodeToRemove == _firstNode) { |  | ||||||
|     _firstNode = nodeToRemove->next; |  | ||||||
|   } else { |  | ||||||
|     for (node_type *node = _firstNode; node; node = node->next) |  | ||||||
|       if (node->next == nodeToRemove) node->next = nodeToRemove->next; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template class ArduinoJson::Internals::List<JsonPair>; |  | ||||||
| template class ArduinoJson::Internals::List<JsonVariant>; |  | ||||||
| @@ -1,87 +0,0 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2016 |  | ||||||
| // MIT License |  | ||||||
| // |  | ||||||
| // Arduino JSON library |  | ||||||
| // https://github.com/bblanchon/ArduinoJson |  | ||||||
| // If you like this project, please add a star! |  | ||||||
|  |  | ||||||
| #include "../../include/ArduinoJson/Internals/Prettyfier.hpp" |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson::Internals; |  | ||||||
|  |  | ||||||
| size_t Prettyfier::write(uint8_t c) { |  | ||||||
|   size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c); |  | ||||||
|   _previousChar = c; |  | ||||||
|   return n; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t Prettyfier::handleStringChar(uint8_t c) { |  | ||||||
|   bool isQuote = c == '"' && _previousChar != '\\'; |  | ||||||
|  |  | ||||||
|   if (isQuote) _inString = false; |  | ||||||
|  |  | ||||||
|   return _sink.write(c); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t Prettyfier::handleMarkupChar(uint8_t c) { |  | ||||||
|   switch (c) { |  | ||||||
|     case '{': |  | ||||||
|     case '[': |  | ||||||
|       return handleBlockOpen(c); |  | ||||||
|  |  | ||||||
|     case '}': |  | ||||||
|     case ']': |  | ||||||
|       return handleBlockClose(c); |  | ||||||
|  |  | ||||||
|     case ':': |  | ||||||
|       return handleColon(); |  | ||||||
|  |  | ||||||
|     case ',': |  | ||||||
|       return handleComma(); |  | ||||||
|  |  | ||||||
|     case '"': |  | ||||||
|       return handleQuoteOpen(); |  | ||||||
|  |  | ||||||
|     default: |  | ||||||
|       return handleNormalChar(c); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t Prettyfier::handleBlockOpen(uint8_t c) { |  | ||||||
|   return indentIfNeeded() + _sink.write(c); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t Prettyfier::handleBlockClose(uint8_t c) { |  | ||||||
|   return unindentIfNeeded() + _sink.write(c); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t Prettyfier::handleColon() { |  | ||||||
|   return _sink.write(':') + _sink.write(' '); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t Prettyfier::handleComma() { |  | ||||||
|   return _sink.write(',') + _sink.println(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t Prettyfier::handleQuoteOpen() { |  | ||||||
|   _inString = true; |  | ||||||
|   return indentIfNeeded() + _sink.write('"'); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t Prettyfier::handleNormalChar(uint8_t c) { |  | ||||||
|   return indentIfNeeded() + _sink.write(c); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| size_t Prettyfier::indentIfNeeded() { |  | ||||||
|   if (!inEmptyBlock()) return 0; |  | ||||||
|  |  | ||||||
|   _sink.indent(); |  | ||||||
|   return _sink.println(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| size_t Prettyfier::unindentIfNeeded() { |  | ||||||
|   if (inEmptyBlock()) return 0; |  | ||||||
|  |  | ||||||
|   _sink.unindent(); |  | ||||||
|   return _sink.println(); |  | ||||||
| } |  | ||||||
| @@ -1,18 +0,0 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2016 |  | ||||||
| // MIT License |  | ||||||
| // |  | ||||||
| // Arduino JSON library |  | ||||||
| // https://github.com/bblanchon/ArduinoJson |  | ||||||
| // If you like this project, please add a star! |  | ||||||
|  |  | ||||||
| #include "../../include/ArduinoJson/Internals/StaticStringBuilder.hpp" |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson::Internals; |  | ||||||
|  |  | ||||||
| size_t StaticStringBuilder::write(uint8_t c) { |  | ||||||
|   if (length >= capacity) return 0; |  | ||||||
|  |  | ||||||
|   buffer[length++] = c; |  | ||||||
|   buffer[length] = '\0'; |  | ||||||
|   return 1; |  | ||||||
| } |  | ||||||
| @@ -1,40 +0,0 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2016 |  | ||||||
| // MIT License |  | ||||||
| // |  | ||||||
| // Arduino JSON library |  | ||||||
| // https://github.com/bblanchon/ArduinoJson |  | ||||||
| // If you like this project, please add a star! |  | ||||||
|  |  | ||||||
| #include "../include/ArduinoJson/JsonArray.hpp" |  | ||||||
|  |  | ||||||
| #include "../include/ArduinoJson/JsonBuffer.hpp" |  | ||||||
| #include "../include/ArduinoJson/JsonObject.hpp" |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson; |  | ||||||
| using namespace ArduinoJson::Internals; |  | ||||||
|  |  | ||||||
| JsonArray JsonArray::_invalid(NULL); |  | ||||||
|  |  | ||||||
| JsonArray::node_type *JsonArray::getNodeAt(size_t index) const { |  | ||||||
|   node_type *node = _firstNode; |  | ||||||
|   while (node && index--) node = node->next; |  | ||||||
|   return node; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void JsonArray::removeAt(size_t index) { removeNode(getNodeAt(index)); } |  | ||||||
|  |  | ||||||
| void JsonArray::writeTo(JsonWriter &writer) const { |  | ||||||
|   writer.beginArray(); |  | ||||||
|  |  | ||||||
|   const node_type *child = _firstNode; |  | ||||||
|   while (child) { |  | ||||||
|     child->content.writeTo(writer); |  | ||||||
|  |  | ||||||
|     child = child->next; |  | ||||||
|     if (!child) break; |  | ||||||
|  |  | ||||||
|     writer.writeComma(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   writer.endArray(); |  | ||||||
| } |  | ||||||
| @@ -1,47 +0,0 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2016 |  | ||||||
| // MIT License |  | ||||||
| // |  | ||||||
| // Arduino JSON library |  | ||||||
| // https://github.com/bblanchon/ArduinoJson |  | ||||||
| // If you like this project, please add a star! |  | ||||||
|  |  | ||||||
| #include "../include/ArduinoJson/JsonBuffer.hpp" |  | ||||||
|  |  | ||||||
| #include "../include/ArduinoJson/Internals/JsonParser.hpp" |  | ||||||
| #include "../include/ArduinoJson/JsonArray.hpp" |  | ||||||
| #include "../include/ArduinoJson/JsonObject.hpp" |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson; |  | ||||||
| using namespace ArduinoJson::Internals; |  | ||||||
|  |  | ||||||
| JsonArray &JsonBuffer::createArray() { |  | ||||||
|   JsonArray *ptr = new (this) JsonArray(this); |  | ||||||
|   return ptr ? *ptr : JsonArray::invalid(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| JsonObject &JsonBuffer::createObject() { |  | ||||||
|   JsonObject *ptr = new (this) JsonObject(this); |  | ||||||
|   return ptr ? *ptr : JsonObject::invalid(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| JsonArray &JsonBuffer::parseArray(char *json, uint8_t nestingLimit) { |  | ||||||
|   JsonParser parser(this, json, nestingLimit); |  | ||||||
|   return parser.parseArray(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| JsonObject &JsonBuffer::parseObject(char *json, uint8_t nestingLimit) { |  | ||||||
|   JsonParser parser(this, json, nestingLimit); |  | ||||||
|   return parser.parseObject(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| JsonVariant JsonBuffer::parse(char *json, uint8_t nestingLimit) { |  | ||||||
|   JsonParser parser(this, json, nestingLimit); |  | ||||||
|   return parser.parseVariant(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| char *JsonBuffer::strdup(const char *source, size_t length) { |  | ||||||
|   size_t size = length + 1; |  | ||||||
|   char *dest = static_cast<char *>(alloc(size)); |  | ||||||
|   if (dest != NULL) memcpy(dest, source, size); |  | ||||||
|   return dest; |  | ||||||
| } |  | ||||||
| @@ -1,44 +0,0 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2016 |  | ||||||
| // MIT License |  | ||||||
| // |  | ||||||
| // Arduino JSON library |  | ||||||
| // https://github.com/bblanchon/ArduinoJson |  | ||||||
| // If you like this project, please add a star! |  | ||||||
|  |  | ||||||
| #include "../include/ArduinoJson/JsonObject.hpp" |  | ||||||
|  |  | ||||||
| #include <string.h>  // for strcmp |  | ||||||
|  |  | ||||||
| #include "../include/ArduinoJson/Internals/StaticStringBuilder.hpp" |  | ||||||
| #include "../include/ArduinoJson/JsonArray.hpp" |  | ||||||
| #include "../include/ArduinoJson/JsonBuffer.hpp" |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson; |  | ||||||
| using namespace ArduinoJson::Internals; |  | ||||||
|  |  | ||||||
| JsonObject JsonObject::_invalid(NULL); |  | ||||||
|  |  | ||||||
| JsonObject::node_type *JsonObject::getNodeAt(const char *key) const { |  | ||||||
|   for (node_type *node = _firstNode; node; node = node->next) { |  | ||||||
|     if (!strcmp(node->content.key, key)) return node; |  | ||||||
|   } |  | ||||||
|   return NULL; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void JsonObject::writeTo(JsonWriter &writer) const { |  | ||||||
|   writer.beginObject(); |  | ||||||
|  |  | ||||||
|   const node_type *node = _firstNode; |  | ||||||
|   while (node) { |  | ||||||
|     writer.writeString(node->content.key); |  | ||||||
|     writer.writeColon(); |  | ||||||
|     node->content.value.writeTo(writer); |  | ||||||
|  |  | ||||||
|     node = node->next; |  | ||||||
|     if (!node) break; |  | ||||||
|  |  | ||||||
|     writer.writeComma(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   writer.endObject(); |  | ||||||
| } |  | ||||||
| @@ -1,125 +0,0 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2016 |  | ||||||
| // MIT License |  | ||||||
| // |  | ||||||
| // Arduino JSON library |  | ||||||
| // https://github.com/bblanchon/ArduinoJson |  | ||||||
| // If you like this project, please add a star! |  | ||||||
|  |  | ||||||
| #include "../include/ArduinoJson/JsonVariant.hpp" |  | ||||||
|  |  | ||||||
| #include "../include/ArduinoJson/JsonArray.hpp" |  | ||||||
| #include "../include/ArduinoJson/JsonObject.hpp" |  | ||||||
|  |  | ||||||
| #include <errno.h>   // for errno |  | ||||||
| #include <stdlib.h>  // for strtol, strtod |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson::Internals; |  | ||||||
|  |  | ||||||
| namespace ArduinoJson { |  | ||||||
|  |  | ||||||
| const char *JsonVariant::asString() const { |  | ||||||
|   if (_type == JSON_UNPARSED && _content.asString && |  | ||||||
|       !strcmp("null", _content.asString)) |  | ||||||
|     return NULL; |  | ||||||
|   if (_type == JSON_STRING || _type == JSON_UNPARSED) return _content.asString; |  | ||||||
|   return NULL; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| JsonFloat JsonVariant::asFloat() const { |  | ||||||
|   switch (_type) { |  | ||||||
|     case JSON_UNDEFINED: |  | ||||||
|       return 0; |  | ||||||
|     case JSON_POSITIVE_INTEGER: |  | ||||||
|     case JSON_BOOLEAN: |  | ||||||
|       return static_cast<JsonFloat>(_content.asInteger); |  | ||||||
|     case JSON_NEGATIVE_INTEGER: |  | ||||||
|       return -static_cast<JsonFloat>(_content.asInteger); |  | ||||||
|     case JSON_STRING: |  | ||||||
|     case JSON_UNPARSED: |  | ||||||
|       return _content.asString ? parse<JsonFloat>(_content.asString) : 0; |  | ||||||
|     default: |  | ||||||
|       return _content.asFloat; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| String JsonVariant::toString() const { |  | ||||||
|   String s; |  | ||||||
|   if ((_type == JSON_STRING || _type == JSON_UNPARSED) && |  | ||||||
|       _content.asString != NULL) |  | ||||||
|     s = _content.asString; |  | ||||||
|   else |  | ||||||
|     printTo(s); |  | ||||||
|   return s; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool JsonVariant::isBoolean() const { |  | ||||||
|   if (_type == JSON_BOOLEAN) return true; |  | ||||||
|  |  | ||||||
|   if (_type != JSON_UNPARSED || _content.asString == NULL) return false; |  | ||||||
|  |  | ||||||
|   return !strcmp(_content.asString, "true") || |  | ||||||
|          !strcmp(_content.asString, "false"); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool JsonVariant::isInteger() const { |  | ||||||
|   if (_type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER) |  | ||||||
|     return true; |  | ||||||
|  |  | ||||||
|   if (_type != JSON_UNPARSED || _content.asString == NULL) return false; |  | ||||||
|  |  | ||||||
|   char *end; |  | ||||||
|   errno = 0; |  | ||||||
|   strtol(_content.asString, &end, 10); |  | ||||||
|  |  | ||||||
|   return *end == '\0' && errno == 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool JsonVariant::isFloat() const { |  | ||||||
|   if (_type >= JSON_FLOAT_0_DECIMALS) return true; |  | ||||||
|  |  | ||||||
|   if (_type != JSON_UNPARSED || _content.asString == NULL) return false; |  | ||||||
|  |  | ||||||
|   char *end; |  | ||||||
|   errno = 0; |  | ||||||
|   strtod(_content.asString, &end); |  | ||||||
|  |  | ||||||
|   return *end == '\0' && errno == 0 && !is<long>(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void JsonVariant::writeTo(JsonWriter &writer) const { |  | ||||||
|   switch (_type) { |  | ||||||
|     case JSON_UNDEFINED: |  | ||||||
|       return; |  | ||||||
|  |  | ||||||
|     case JSON_ARRAY: |  | ||||||
|       _content.asArray->writeTo(writer); |  | ||||||
|       return; |  | ||||||
|  |  | ||||||
|     case JSON_OBJECT: |  | ||||||
|       _content.asObject->writeTo(writer); |  | ||||||
|       return; |  | ||||||
|  |  | ||||||
|     case JSON_STRING: |  | ||||||
|       writer.writeString(_content.asString); |  | ||||||
|       return; |  | ||||||
|  |  | ||||||
|     case JSON_UNPARSED: |  | ||||||
|       writer.writeRaw(_content.asString); |  | ||||||
|       return; |  | ||||||
|  |  | ||||||
|     case JSON_NEGATIVE_INTEGER: |  | ||||||
|       writer.writeRaw('-'); |  | ||||||
|     case JSON_POSITIVE_INTEGER: |  | ||||||
|       writer.writeInteger(_content.asInteger); |  | ||||||
|       return; |  | ||||||
|  |  | ||||||
|     case JSON_BOOLEAN: |  | ||||||
|       writer.writeBoolean(_content.asInteger != 0); |  | ||||||
|       return; |  | ||||||
|  |  | ||||||
|     default: |  | ||||||
|       uint8_t decimals = static_cast<uint8_t>(_type - JSON_FLOAT_0_DECIMALS); |  | ||||||
|       writer.writeFloat(_content.asFloat, decimals); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| } |  | ||||||
| @@ -5,31 +5,69 @@ | |||||||
| # https://github.com/bblanchon/ArduinoJson | # https://github.com/bblanchon/ArduinoJson | ||||||
| # If you like this project, please add a star! | # If you like this project, please add a star! | ||||||
|  |  | ||||||
| set(GTEST_DIR ../third-party/gtest-1.7.0) | include(gtest.cmake) | ||||||
|  |  | ||||||
| file(GLOB TESTS_FILES *.hpp *.cpp) | file(GLOB TESTS_FILES *.hpp *.cpp) | ||||||
|  |  | ||||||
| include_directories( | if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") | ||||||
|     ${GTEST_DIR} | 	add_compile_options( | ||||||
|     ${GTEST_DIR}/include) | 		-fno-exceptions | ||||||
|  | 		-fno-rtti | ||||||
| add_definitions(-DGTEST_HAS_PTHREAD=0) | 		-pedantic | ||||||
|  | 		-Wall | ||||||
| # Workaround for Visual Studio 2012 | 		-Wcast-align | ||||||
| if (MSVC AND MSVC_VERSION EQUAL 1700) | 		-Wcast-qual | ||||||
|     add_definitions(-D_VARIADIC_MAX=10) | 		-Wconversion | ||||||
|  | 		-Wctor-dtor-privacy | ||||||
|  | 		-Wdisabled-optimization | ||||||
|  | 		-Werror | ||||||
|  | 		-Wextra | ||||||
|  | 		-Wformat=2 | ||||||
|  | 		-Winit-self | ||||||
|  | 		-Wmissing-include-dirs | ||||||
|  | 		-Wno-parentheses | ||||||
|  | 		-Wno-sign-conversion | ||||||
|  | 		-Wno-unused | ||||||
|  | 		-Wno-variadic-macros | ||||||
|  | 		-Wnon-virtual-dtor | ||||||
|  | 		-Wold-style-cast | ||||||
|  | 		-Woverloaded-virtual | ||||||
|  | 		-Wredundant-decls | ||||||
|  | 		-Wshadow | ||||||
|  | 		-Wsign-promo | ||||||
|  | 		-Wstrict-overflow=5 | ||||||
|  | 		-Wundef | ||||||
|  | 	) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
| if (MSVC) | if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") | ||||||
|  | 	add_compile_options( | ||||||
|  | 		-Wstrict-null-sentinel | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.5) | ||||||
|  | 		add_compile_options(-Wlogical-op) # the flag exists in 4.4 but is buggy | ||||||
|  | 	endif() | ||||||
|  |  | ||||||
|  | 	if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.6) | ||||||
|  | 		add_compile_options(-Wnoexcept) | ||||||
|  | 	endif() | ||||||
|  | endif() | ||||||
|  |  | ||||||
|  | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") | ||||||
|  | 	add_compile_options( | ||||||
|  | 		-Wc++11-compat | ||||||
|  | 		-Wdeprecated-register | ||||||
|  | 	) | ||||||
|  | endif() | ||||||
|  |  | ||||||
|  | if(MSVC) | ||||||
| 	add_definitions(-D_CRT_SECURE_NO_WARNINGS) | 	add_definitions(-D_CRT_SECURE_NO_WARNINGS) | ||||||
|  | 	add_compile_options(-W4) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
| add_executable(ArduinoJsonTests  | add_executable(ArduinoJsonTests ${TESTS_FILES}) | ||||||
|     ${TESTS_FILES} | target_include_directories(ArduinoJsonTests PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../include) | ||||||
|     ${GTEST_DIR}/src/gtest-all.cc | target_link_libraries(ArduinoJsonTests gtest) | ||||||
|     ${GTEST_DIR}/src/gtest_main.cc) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| target_link_libraries(ArduinoJsonTests ArduinoJson) |  | ||||||
|  |  | ||||||
| add_test(ArduinoJsonTests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ArduinoJsonTests) | add_test(ArduinoJsonTests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ArduinoJsonTests) | ||||||
|   | |||||||
| @@ -6,11 +6,7 @@ | |||||||
| // If you like this project, please add a star! | // If you like this project, please add a star! | ||||||
|  |  | ||||||
| #include <gtest/gtest.h> | #include <gtest/gtest.h> | ||||||
|  | #include <ArduinoJson.h> | ||||||
| #define protected public |  | ||||||
| #include <ArduinoJson/DynamicJsonBuffer.hpp> |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson; |  | ||||||
|  |  | ||||||
| class DynamicJsonBuffer_Basic_Tests : public testing::Test { | class DynamicJsonBuffer_Basic_Tests : public testing::Test { | ||||||
|  protected: |  protected: | ||||||
|   | |||||||
| @@ -44,7 +44,7 @@ TEST(JsonArray_CopyTo_Tests, TwoOneDimensionIntegerArray) { | |||||||
|   DynamicJsonBuffer jsonBuffer; |   DynamicJsonBuffer jsonBuffer; | ||||||
|   JsonArray& array = jsonBuffer.parseArray(json); |   JsonArray& array = jsonBuffer.parseArray(json); | ||||||
|  |  | ||||||
|   int destination[3][2] = {0}; |   int destination[3][2] = {{0}}; | ||||||
|   array.copyTo(destination); |   array.copyTo(destination); | ||||||
|  |  | ||||||
|   ASSERT_EQ(1, destination[0][0]); |   ASSERT_EQ(1, destination[0][0]); | ||||||
|   | |||||||
| @@ -6,9 +6,7 @@ | |||||||
| // If you like this project, please add a star! | // If you like this project, please add a star! | ||||||
|  |  | ||||||
| #include <gtest/gtest.h> | #include <gtest/gtest.h> | ||||||
| #include <ArduinoJson/JsonVariant.hpp> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| using namespace ArduinoJson; |  | ||||||
|  |  | ||||||
| class JsonVariant_Comparison_Tests : public ::testing::Test { | class JsonVariant_Comparison_Tests : public ::testing::Test { | ||||||
|  protected: |  protected: | ||||||
|   | |||||||
| @@ -6,11 +6,7 @@ | |||||||
| // If you like this project, please add a star! | // If you like this project, please add a star! | ||||||
|  |  | ||||||
| #include <gtest/gtest.h> | #include <gtest/gtest.h> | ||||||
|  | #include <ArduinoJson.h> | ||||||
| #define protected public |  | ||||||
| #include <ArduinoJson/StaticJsonBuffer.hpp> |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson; |  | ||||||
|  |  | ||||||
| class StaticJsonBuffer_Basic_Tests : public testing::Test { | class StaticJsonBuffer_Basic_Tests : public testing::Test { | ||||||
|  protected: |  protected: | ||||||
|   | |||||||
| @@ -10,9 +10,13 @@ | |||||||
|  |  | ||||||
| class StaticJsonBuffer_ParseArray_Tests : public testing::Test { | class StaticJsonBuffer_ParseArray_Tests : public testing::Test { | ||||||
|  protected: |  protected: | ||||||
|   void with(JsonBuffer& jsonBuffer) { _jsonBuffer = &jsonBuffer; } |   void with(JsonBuffer& jsonBuffer) { | ||||||
|  |     _jsonBuffer = &jsonBuffer; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   void whenInputIs(const char* json) { strcpy(_jsonString, json); } |   void whenInputIs(const char* json) { | ||||||
|  |     strcpy(_jsonString, json); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   void parseMustSucceed() { |   void parseMustSucceed() { | ||||||
|     EXPECT_TRUE(_jsonBuffer->parseArray(_jsonString).success()); |     EXPECT_TRUE(_jsonBuffer->parseArray(_jsonString).success()); | ||||||
| @@ -73,9 +77,12 @@ TEST_F(StaticJsonBuffer_ParseArray_Tests, | |||||||
| } | } | ||||||
|  |  | ||||||
| TEST_F(StaticJsonBuffer_ParseArray_Tests, CharPtrNull) { | TEST_F(StaticJsonBuffer_ParseArray_Tests, CharPtrNull) { | ||||||
|   ASSERT_FALSE(StaticJsonBuffer<100>().parseArray((char*)0).success()); |   ASSERT_FALSE( | ||||||
|  |       StaticJsonBuffer<100>().parseArray(static_cast<char*>(0)).success()); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_F(StaticJsonBuffer_ParseArray_Tests, ConstCharPtrNull) { | TEST_F(StaticJsonBuffer_ParseArray_Tests, ConstCharPtrNull) { | ||||||
|   ASSERT_FALSE(StaticJsonBuffer<100>().parseArray((const char*)0).success()); |   ASSERT_FALSE(StaticJsonBuffer<100>() | ||||||
|  |                    .parseArray(static_cast<const char*>(0)) | ||||||
|  |                    .success()); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -10,9 +10,13 @@ | |||||||
|  |  | ||||||
| class StaticJsonBuffer_ParseObject_Tests : public testing::Test { | class StaticJsonBuffer_ParseObject_Tests : public testing::Test { | ||||||
|  protected: |  protected: | ||||||
|   void with(JsonBuffer& jsonBuffer) { _jsonBuffer = &jsonBuffer; } |   void with(JsonBuffer& jsonBuffer) { | ||||||
|  |     _jsonBuffer = &jsonBuffer; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   void whenInputIs(const char* json) { strcpy(_jsonString, json); } |   void whenInputIs(const char* json) { | ||||||
|  |     strcpy(_jsonString, json); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   void parseMustSucceed() { |   void parseMustSucceed() { | ||||||
|     EXPECT_TRUE(_jsonBuffer->parseObject(_jsonString).success()); |     EXPECT_TRUE(_jsonBuffer->parseObject(_jsonString).success()); | ||||||
| @@ -74,9 +78,12 @@ TEST_F(StaticJsonBuffer_ParseObject_Tests, | |||||||
| } | } | ||||||
|  |  | ||||||
| TEST_F(StaticJsonBuffer_ParseObject_Tests, CharPtrNull) { | TEST_F(StaticJsonBuffer_ParseObject_Tests, CharPtrNull) { | ||||||
|   ASSERT_FALSE(StaticJsonBuffer<100>().parseObject((char*)0).success()); |   ASSERT_FALSE( | ||||||
|  |       StaticJsonBuffer<100>().parseObject(static_cast<char*>(0)).success()); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_F(StaticJsonBuffer_ParseObject_Tests, ConstCharPtrNull) { | TEST_F(StaticJsonBuffer_ParseObject_Tests, ConstCharPtrNull) { | ||||||
|   ASSERT_FALSE(StaticJsonBuffer<100>().parseObject((const char*)0).success()); |   ASSERT_FALSE(StaticJsonBuffer<100>() | ||||||
|  |                    .parseObject(static_cast<const char*>(0)) | ||||||
|  |                    .success()); | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								test/gtest.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								test/gtest.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | set(GTEST_DIR ../third-party/gtest-1.7.0) | ||||||
|  |  | ||||||
|  | add_library(gtest | ||||||
|  | 	${GTEST_DIR}/src/gtest-all.cc | ||||||
|  |     ${GTEST_DIR}/src/gtest_main.cc | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | target_include_directories(gtest | ||||||
|  | 	PUBLIC | ||||||
|  |     ${GTEST_DIR} | ||||||
|  |     ${GTEST_DIR}/include | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | target_compile_definitions(gtest PUBLIC -DGTEST_HAS_PTHREAD=0) | ||||||
|  |  | ||||||
|  | if (MSVC) | ||||||
|  | 	if (MSVC_VERSION EQUAL 1700) | ||||||
|  | 		# Workaround for Visual Studio 2012 | ||||||
|  | 	    target_compile_definitions(gtest PUBLIC -D_VARIADIC_MAX=10) | ||||||
|  | 	endif() | ||||||
|  |  | ||||||
|  | 	target_compile_definitions(gtest PUBLIC -D_CRT_SECURE_NO_WARNINGS) | ||||||
|  | endif() | ||||||
| @@ -1,3 +1,8 @@ | |||||||
|  | // clang-format off | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | #pragma GCC system_header | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // This file was GENERATED by command: | // This file was GENERATED by command: | ||||||
| //     pump.py gtest-param-test.h.pump | //     pump.py gtest-param-test.h.pump | ||||||
| // DO NOT EDIT BY HAND!!! | // DO NOT EDIT BY HAND!!! | ||||||
|   | |||||||
| @@ -1,3 +1,8 @@ | |||||||
|  | // clang-format off | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | #pragma GCC system_header | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // Copyright 2005, Google Inc. | // Copyright 2005, Google Inc. | ||||||
| // All rights reserved. | // All rights reserved. | ||||||
| // | // | ||||||
|   | |||||||
| @@ -1,3 +1,8 @@ | |||||||
|  | // clang-format off | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | #pragma GCC system_header | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // Copyright 2005, Google Inc. | // Copyright 2005, Google Inc. | ||||||
| // All rights reserved. | // All rights reserved. | ||||||
| // | // | ||||||
|   | |||||||
| @@ -1,3 +1,8 @@ | |||||||
|  | // clang-format off | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | #pragma GCC system_header | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // Copyright 2005, Google Inc. | // Copyright 2005, Google Inc. | ||||||
| // All rights reserved. | // All rights reserved. | ||||||
| // | // | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user