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:
		| @@ -2,3 +2,4 @@ | ||||
|  | ||||
| BasedOnStyle: Google | ||||
| Standard: Cpp03 | ||||
| AllowShortFunctionsOnASingleLine: Empty | ||||
|   | ||||
| @@ -5,10 +5,4 @@ | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
| // 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" | ||||
|   | ||||
| @@ -1,6 +1,11 @@ | ||||
| ArduinoJson: change log | ||||
| ======================= | ||||
|  | ||||
| HEAD | ||||
| ---- | ||||
|  | ||||
| * ArduinoJson is now a header-only library (issue #199) | ||||
|  | ||||
| v5.5.1 | ||||
| ------ | ||||
|  | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| # https://github.com/bblanchon/ArduinoJson | ||||
| # If you like this project, please add a star! | ||||
|  | ||||
| cmake_minimum_required(VERSION 2.8.12) | ||||
| cmake_minimum_required(VERSION 3.0) | ||||
| project(ArduinoJson) | ||||
|  | ||||
| enable_testing() | ||||
| @@ -18,5 +18,4 @@ if(${COVERAGE}) | ||||
| 	set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") | ||||
| endif() | ||||
|  | ||||
| add_subdirectory(src) | ||||
| add_subdirectory(test) | ||||
|   | ||||
| @@ -5,9 +5,5 @@ | ||||
| // 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.hpp" | ||||
| 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> | ||||
|  | ||||
| #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 Internals { | ||||
| class DefaultAllocator { | ||||
|  public: | ||||
|   void* allocate(size_t size) { return malloc(size); } | ||||
|   void deallocate(void* pointer) { free(pointer); } | ||||
|   void* allocate(size_t size) { | ||||
|     return malloc(size); | ||||
|   } | ||||
|   void deallocate(void* pointer) { | ||||
|     free(pointer); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename TAllocator> | ||||
| @@ -51,7 +65,6 @@ class BlockJsonBuffer : public JsonBuffer { | ||||
|     return total; | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   virtual void* alloc(size_t 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 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: | ||||
|   // Optimized for code size on a 8-bit AVR | ||||
|   static char escapeChar(char c) { | ||||
|     const char *p = _escapeTable; | ||||
|     const char *p = escapeTable(false); | ||||
|     while (p[0] && p[1] != c) { | ||||
|       p += 2; | ||||
|     } | ||||
| @@ -25,7 +25,7 @@ class Encoding { | ||||
|  | ||||
|   // Optimized for code size on a 8-bit AVR | ||||
|   static char unescapeChar(char c) { | ||||
|     const char *p = _escapeTable + 4; | ||||
|     const char *p = escapeTable(true); | ||||
|     for (;;) { | ||||
|       if (p[0] == '\0') return c; | ||||
|       if (p[0] == c) return p[1]; | ||||
| @@ -34,7 +34,9 @@ class Encoding { | ||||
|   } | ||||
|  | ||||
|  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; | ||||
|   } | ||||
|  | ||||
|   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 | ||||
|   void indent() { | ||||
| @@ -46,7 +52,11 @@ class IndentedPrint : public Print { | ||||
|   uint8_t tabSize : 3; | ||||
|   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_TAB_SIZE = 7;  // because it's only 3 bits | ||||
|   | ||||
| @@ -44,6 +44,19 @@ class JsonParser { | ||||
|   inline bool parseObjectTo(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; | ||||
|   const char *_readPtr; | ||||
|   char *_writePtr; | ||||
|   | ||||
| @@ -5,18 +5,10 @@ | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
| // 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" | ||||
| #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) { | ||||
| inline bool ArduinoJson::Internals::JsonParser::skip(char charToSkip) { | ||||
|   const char *ptr = skipSpacesAndComments(_readPtr); | ||||
|   if (*ptr != charToSkip) return false; | ||||
|   ptr++; | ||||
| @@ -24,7 +16,8 @@ bool JsonParser::skip(char charToSkip) { | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool JsonParser::parseAnythingTo(JsonVariant *destination) { | ||||
| inline bool ArduinoJson::Internals::JsonParser::parseAnythingTo( | ||||
|     JsonVariant *destination) { | ||||
|   if (_nestingLimit == 0) return false; | ||||
|   _nestingLimit--; | ||||
|   bool success = parseAnythingToUnsafe(destination); | ||||
| @@ -32,7 +25,8 @@ bool JsonParser::parseAnythingTo(JsonVariant *destination) { | ||||
|   return success; | ||||
| } | ||||
| 
 | ||||
| inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) { | ||||
| inline bool ArduinoJson::Internals::JsonParser::parseAnythingToUnsafe( | ||||
|     JsonVariant *destination) { | ||||
|   _readPtr = skipSpacesAndComments(_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 | ||||
|   JsonArray &array = _buffer->createArray(); | ||||
| 
 | ||||
| @@ -78,7 +73,8 @@ ERROR_NO_MEMORY: | ||||
|   return JsonArray::invalid(); | ||||
| } | ||||
| 
 | ||||
| bool JsonParser::parseArrayTo(JsonVariant *destination) { | ||||
| inline bool ArduinoJson::Internals::JsonParser::parseArrayTo( | ||||
|     JsonVariant *destination) { | ||||
|   JsonArray &array = parseArray(); | ||||
|   if (!array.success()) return false; | ||||
| 
 | ||||
| @@ -86,7 +82,8 @@ bool JsonParser::parseArrayTo(JsonVariant *destination) { | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| JsonObject &JsonParser::parseObject() { | ||||
| inline ArduinoJson::JsonObject & | ||||
| ArduinoJson::Internals::JsonParser::parseObject() { | ||||
|   // Create an empty object | ||||
|   JsonObject &object = _buffer->createObject(); | ||||
| 
 | ||||
| @@ -124,7 +121,8 @@ ERROR_NO_MEMORY: | ||||
|   return JsonObject::invalid(); | ||||
| } | ||||
| 
 | ||||
| bool JsonParser::parseObjectTo(JsonVariant *destination) { | ||||
| inline bool ArduinoJson::Internals::JsonParser::parseObjectTo( | ||||
|     JsonVariant *destination) { | ||||
|   JsonObject &object = parseObject(); | ||||
|   if (!object.success()) return false; | ||||
| 
 | ||||
| @@ -132,18 +130,7 @@ bool JsonParser::parseObjectTo(JsonVariant *destination) { | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| 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 == '\"'; } | ||||
| 
 | ||||
| const char *JsonParser::parseString() { | ||||
| inline const char *ArduinoJson::Internals::JsonParser::parseString() { | ||||
|   const char *readPtr = _readPtr; | ||||
|   char *writePtr = _writePtr; | ||||
| 
 | ||||
| @@ -188,7 +175,8 @@ const char *JsonParser::parseString() { | ||||
|   return startPtr; | ||||
| } | ||||
| 
 | ||||
| bool JsonParser::parseStringTo(JsonVariant *destination) { | ||||
| inline bool ArduinoJson::Internals::JsonParser::parseStringTo( | ||||
|     JsonVariant *destination) { | ||||
|   bool hasQuotes = isQuote(_readPtr[0]); | ||||
|   const char *value = parseString(); | ||||
|   if (value == NULL) return false; | ||||
| @@ -7,12 +7,12 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "../Polyfills/attributes.hpp" | ||||
| #include "../Polyfills/isInfinity.hpp" | ||||
| #include "../Polyfills/isNaN.hpp" | ||||
| #include "../Polyfills/normalize.hpp" | ||||
| #include "../Print.hpp" | ||||
| #include "Encoding.hpp" | ||||
| #include "ForceInline.hpp" | ||||
| #include "JsonFloat.hpp" | ||||
| #include "JsonInteger.hpp" | ||||
|  | ||||
|   | ||||
| @@ -36,21 +36,56 @@ class List { | ||||
|   // Would return false in the following situation: | ||||
|   // - the memory allocation failed (StaticJsonBuffer was too small) | ||||
|   // - the JSON parsing failed | ||||
|   bool success() const { return _buffer != NULL; } | ||||
|   bool success() const { | ||||
|     return _buffer != NULL; | ||||
|   } | ||||
|  | ||||
|   // Returns the numbers of elements in the list. | ||||
|   // 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 end() { return iterator(NULL); } | ||||
|   iterator begin() { | ||||
|     return iterator(_firstNode); | ||||
|   } | ||||
|   iterator end() { | ||||
|     return iterator(NULL); | ||||
|   } | ||||
|  | ||||
|   const_iterator begin() const { return const_iterator(_firstNode); } | ||||
|   const_iterator end() const { return const_iterator(NULL); } | ||||
|   const_iterator begin() const { | ||||
|     return const_iterator(_firstNode); | ||||
|   } | ||||
|   const_iterator end() const { | ||||
|     return const_iterator(NULL); | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   node_type *addNewNode(); | ||||
|   void removeNode(node_type *nodeToRemove); | ||||
|   node_type *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; | ||||
|   } | ||||
|  | ||||
|   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; | ||||
|   node_type *_firstNode; | ||||
|   | ||||
| @@ -20,24 +20,89 @@ class Prettyfier : public Print { | ||||
|     _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: | ||||
|   Prettyfier& operator=(const Prettyfier&);  // cannot be assigned | ||||
|  | ||||
|   bool inEmptyBlock() { return _previousChar == '{' || _previousChar == '['; } | ||||
|   bool inEmptyBlock() { | ||||
|     return _previousChar == '{' || _previousChar == '['; | ||||
|   } | ||||
|  | ||||
|   size_t handleStringChar(uint8_t); | ||||
|   size_t handleMarkupChar(uint8_t); | ||||
|   size_t handleStringChar(uint8_t c) { | ||||
|     bool isQuote = c == '"' && _previousChar != '\\'; | ||||
|  | ||||
|   size_t handleBlockClose(uint8_t); | ||||
|   size_t handleBlockOpen(uint8_t); | ||||
|   size_t handleColon(); | ||||
|   size_t handleComma(); | ||||
|   size_t handleQuoteOpen(); | ||||
|   size_t handleNormalChar(uint8_t); | ||||
|   size_t indentIfNeeded(); | ||||
|   size_t unindentIfNeeded(); | ||||
|     if (isQuote) _inString = false; | ||||
|  | ||||
|     return _sink.write(c); | ||||
|   } | ||||
|  | ||||
|   size_t handleMarkupChar(uint8_t c) { | ||||
|     switch (c) { | ||||
|       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; | ||||
|   IndentedPrint& _sink; | ||||
|   | ||||
| @@ -20,7 +20,13 @@ class StaticStringBuilder : public Print { | ||||
|     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: | ||||
|   char *buffer; | ||||
|   | ||||
| @@ -56,10 +56,12 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|       : Internals::List<JsonVariant>(buffer) {} | ||||
|  | ||||
|   // 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 | ||||
|   FORCE_INLINE JsonArraySubscript operator[](size_t index); | ||||
|   JsonArraySubscript operator[](size_t index); | ||||
|  | ||||
|   // 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(const char*); | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool add( | ||||
|   bool add( | ||||
|       T value, | ||||
|       typename TypeTraits::EnableIf< | ||||
|           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) { | ||||
| @@ -83,18 +85,16 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|   // bool add(JsonArray&); | ||||
|   // bool add(JsonObject&); | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool add( | ||||
|       const T &value, | ||||
|       typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) { | ||||
|   bool add(const T &value, | ||||
|            typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) { | ||||
|     return addNode<T &>(const_cast<T &>(value)); | ||||
|   } | ||||
|   // bool add(float value, uint8_t decimals); | ||||
|   // bool add(double value, uint8_t decimals); | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool add( | ||||
|       T value, uint8_t decimals, | ||||
|       typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value>::type | ||||
|           * = 0) { | ||||
|   bool add(T value, uint8_t decimals, | ||||
|            typename TypeTraits::EnableIf< | ||||
|                TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { | ||||
|     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, short value); | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool set( | ||||
|   bool set( | ||||
|       size_t index, T value, | ||||
|       typename TypeTraits::EnableIf< | ||||
|           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, JsonObject&); | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool set( | ||||
|       size_t index, const T &value, | ||||
|       typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) { | ||||
|   bool set(size_t index, const T &value, | ||||
|            typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) { | ||||
|     return setNodeAt<T &>(index, const_cast<T &>(value)); | ||||
|   } | ||||
|   // bool set(size_t index, float value, uint8_t decimals = 2); | ||||
|   // bool set(size_t index, double value, uint8_t decimals = 2); | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool set( | ||||
|       size_t index, T value, uint8_t decimals, | ||||
|       typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value>::type | ||||
|           * = 0) { | ||||
|   bool set(size_t index, T value, uint8_t decimals, | ||||
|            typename TypeTraits::EnableIf< | ||||
|                TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { | ||||
|     return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals)); | ||||
|   } | ||||
|  | ||||
|   // 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. | ||||
|   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. | ||||
|   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. | ||||
|   // It's a shortcut for JsonBuffer::createArray() and JsonArray::add() | ||||
| @@ -151,15 +158,34 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|   JsonObject &createNestedObject(); | ||||
|  | ||||
|   // Removes element at specified index. | ||||
|   void removeAt(size_t index); | ||||
|   void removeAt(size_t index) { | ||||
|     removeNode(getNodeAt(index)); | ||||
|   } | ||||
|  | ||||
|   // Returns a reference an invalid JsonArray. | ||||
|   // This object is meant to replace a NULL pointer. | ||||
|   // 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. | ||||
|   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 | ||||
|   template <typename T, size_t N> | ||||
| @@ -215,20 +241,28 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|   } | ||||
|  | ||||
|  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> | ||||
|   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> | ||||
|   bool addNode(TValue); | ||||
|   bool addNode(TValue value) { | ||||
|     node_type *node = addNewNode(); | ||||
|     return node != NULL && setNodeValue<TValue>(node, value); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool setNodeValue(node_type *, T value); | ||||
|  | ||||
|   // The instance returned by JsonArray::invalid() | ||||
|   static JsonArray _invalid; | ||||
|   bool setNodeValue(node_type *node, T value) { | ||||
|     node->content = value; | ||||
|     return true; | ||||
|   } | ||||
| }; | ||||
| } | ||||
|  | ||||
| #include "JsonArray.ipp" | ||||
|   | ||||
| @@ -13,32 +13,6 @@ | ||||
|  | ||||
| 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 <> | ||||
| inline bool JsonArray::setNodeValue(node_type *node, String &value) { | ||||
|   const char *copy = _buffer->strdup(value); | ||||
| @@ -47,29 +21,6 @@ inline bool JsonArray::setNodeValue(node_type *node, String &value) { | ||||
|   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 <> | ||||
| inline JsonArray &JsonVariant::defaultValue<JsonArray &>() { | ||||
|   return JsonArray::invalid(); | ||||
|   | ||||
| @@ -77,6 +77,16 @@ inline std::ostream& operator<<(std::ostream& os, | ||||
| } | ||||
| #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 | ||||
|  | ||||
| #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. | ||||
|   // You should not use this constructor directly. | ||||
|   // Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject(). | ||||
|   FORCE_INLINE explicit JsonObject(JsonBuffer* buffer) | ||||
|       : Internals::List<JsonPair>(buffer) {} | ||||
|   explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {} | ||||
|  | ||||
|   // Gets or sets the value associated with the specified key. | ||||
|   FORCE_INLINE JsonObjectSubscript<const char*> operator[](const char* key); | ||||
|   FORCE_INLINE JsonObjectSubscript<const String&> operator[](const String& key); | ||||
|   JsonObjectSubscript<const char*> operator[](const char* key); | ||||
|   JsonObjectSubscript<const String&> operator[](const String& 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. | ||||
|   // 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, RawJson value); | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool set( | ||||
|   bool set( | ||||
|       JsonObjectKey key, T value, | ||||
|       typename TypeTraits::EnableIf< | ||||
|           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, JsonVariant&); | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool set( | ||||
|       JsonObjectKey key, const T& value, | ||||
|       typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) { | ||||
|   bool set(JsonObjectKey key, const T& value, | ||||
|            typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) { | ||||
|     return setNodeAt<T&>(key, const_cast<T&>(value)); | ||||
|   } | ||||
|   // bool set(Key, float value, uint8_t decimals); | ||||
|   // bool set(Key, double value, uint8_t decimals); | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE bool set( | ||||
|       JsonObjectKey key, TValue value, uint8_t decimals, | ||||
|       typename TypeTraits::EnableIf< | ||||
|           TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) { | ||||
|   bool set(JsonObjectKey key, TValue value, uint8_t decimals, | ||||
|            typename TypeTraits::EnableIf< | ||||
|                TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) { | ||||
|     return setNodeAt<const JsonVariant&>(key, JsonVariant(value, decimals)); | ||||
|   } | ||||
|  | ||||
|   // 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. | ||||
|   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. | ||||
|   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. | ||||
|   // 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. | ||||
|   // 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. | ||||
|   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. | ||||
|   void remove(JsonObjectKey key); | ||||
|   void remove(JsonObjectKey key) { | ||||
|     removeNode(getNodeAt(key.c_str())); | ||||
|   } | ||||
|  | ||||
|   // Returns a reference an invalid JsonObject. | ||||
|   // This object is meant to replace a NULL pointer. | ||||
|   // 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 | ||||
|   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: | ||||
|   // Returns the list node that matches the specified key. | ||||
|   node_type* getNodeAt(const char* key) const; | ||||
|  | ||||
|   node_type* getOrCreateNodeAt(const char* key); | ||||
|   node_type* getNodeAt(const char* key) const { | ||||
|     for (node_type* node = _firstNode; node; node = node->next) { | ||||
|       if (!strcmp(node->content.key, key)) return node; | ||||
|     } | ||||
|     return NULL; | ||||
|   } | ||||
|  | ||||
|   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> | ||||
|   FORCE_INLINE bool setNodeValue(node_type*, T value); | ||||
|  | ||||
|   // The instance returned by JsonObject::invalid() | ||||
|   static JsonObject _invalid; | ||||
|   bool setNodeValue(node_type* node, T value) { | ||||
|     node->content.value = value; | ||||
|     return true; | ||||
|   } | ||||
| }; | ||||
| } | ||||
|  | ||||
| #include "JsonObject.ipp" | ||||
|   | ||||
| @@ -13,71 +13,6 @@ | ||||
|  | ||||
| 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 <> | ||||
| inline bool JsonObject::setNodeValue(node_type *node, String &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; | ||||
| } | ||||
|  | ||||
| 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 <> | ||||
| inline JsonObject const &JsonVariant::defaultValue<JsonObject const &>() { | ||||
|   return JsonObject::invalid(); | ||||
|   | ||||
| @@ -45,9 +45,13 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > { | ||||
|     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> | ||||
|   FORCE_INLINE TValue as() const { | ||||
| @@ -69,7 +73,9 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > { | ||||
|     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 { | ||||
|     _object.get(_key).writeTo(writer); | ||||
| @@ -92,6 +98,28 @@ inline std::ostream& operator<<( | ||||
| } | ||||
| #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 | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
|   | ||||
| @@ -41,11 +41,15 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|   struct IsConstructibleFrom; | ||||
|  | ||||
|   // Creates an uninitialized JsonVariant | ||||
|   FORCE_INLINE JsonVariant() : _type(Internals::JSON_UNDEFINED) {} | ||||
|   JsonVariant() : _type(Internals::JSON_UNDEFINED) {} | ||||
|  | ||||
|   // Create a JsonVariant containing a boolean value. | ||||
|   // 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. | ||||
|   // 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(float value, uint8_t decimals); | ||||
|   template <typename T> | ||||
|   FORCE_INLINE JsonVariant( | ||||
|       T value, uint8_t decimals = 2, | ||||
|       typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value>::type | ||||
|           * = 0) { | ||||
|   JsonVariant(T value, uint8_t decimals = 2, | ||||
|               typename TypeTraits::EnableIf< | ||||
|                   TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { | ||||
|     using namespace Internals; | ||||
|     _type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals); | ||||
|     _content.asFloat = static_cast<JsonFloat>(value); | ||||
| @@ -67,9 +70,9 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|   // JsonVariant(signed int) | ||||
|   // JsonVariant(signed long) | ||||
|   template <typename T> | ||||
|   FORCE_INLINE JsonVariant( | ||||
|       T value, typename TypeTraits::EnableIf< | ||||
|                    TypeTraits::IsSignedIntegral<T>::value>::type * = 0) { | ||||
|   JsonVariant(T value, | ||||
|               typename TypeTraits::EnableIf< | ||||
|                   TypeTraits::IsSignedIntegral<T>::value>::type * = 0) { | ||||
|     using namespace Internals; | ||||
|     if (value >= 0) { | ||||
|       _type = JSON_POSITIVE_INTEGER; | ||||
| @@ -83,25 +86,37 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|   // JsonVariant(unsigned int) | ||||
|   // JsonVariant(unsigned long) | ||||
|   template <typename T> | ||||
|   FORCE_INLINE JsonVariant( | ||||
|       T value, typename TypeTraits::EnableIf< | ||||
|                    TypeTraits::IsUnsignedIntegral<T>::value>::type * = 0) { | ||||
|   JsonVariant(T value, | ||||
|               typename TypeTraits::EnableIf< | ||||
|                   TypeTraits::IsUnsignedIntegral<T>::value>::type * = 0) { | ||||
|     using namespace Internals; | ||||
|     _type = JSON_POSITIVE_INTEGER; | ||||
|     _content.asInteger = static_cast<JsonUInt>(value); | ||||
|   } | ||||
|  | ||||
|   // 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 | ||||
|   FORCE_INLINE JsonVariant(RawJson value); | ||||
|   JsonVariant(RawJson value) { | ||||
|     _type = Internals::JSON_UNPARSED; | ||||
|     _content.asString = value; | ||||
|   } | ||||
|  | ||||
|   // 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. | ||||
|   FORCE_INLINE JsonVariant(JsonObject &object); | ||||
|   JsonVariant(JsonObject &object) { | ||||
|     _type = Internals::JSON_OBJECT; | ||||
|     _content.asObject = &object; | ||||
|   } | ||||
|  | ||||
|   // Get the variant as the specified type. | ||||
|   // | ||||
| @@ -257,7 +272,9 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|   } | ||||
|  | ||||
|   // 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 | ||||
|   void writeTo(Internals::JsonWriter &writer) const; | ||||
| @@ -275,9 +292,8 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|  private: | ||||
|   // It's not allowed to store a char | ||||
|   template <typename T> | ||||
|   FORCE_INLINE JsonVariant(T value, | ||||
|                            typename TypeTraits::EnableIf< | ||||
|                                TypeTraits::IsSame<T, char>::value>::type * = 0); | ||||
|   JsonVariant(T value, typename TypeTraits::EnableIf< | ||||
|                            TypeTraits::IsSame<T, char>::value>::type * = 0); | ||||
|  | ||||
|   String toString() const; | ||||
|   Internals::JsonFloat asFloat() const; | ||||
| @@ -286,9 +302,15 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|   bool isBoolean() const; | ||||
|   bool isFloat() const; | ||||
|   bool isInteger() const; | ||||
|   bool isArray() const { return _type == Internals::JSON_ARRAY; } | ||||
|   bool isObject() const { return _type == Internals::JSON_OBJECT; } | ||||
|   bool isString() const { return _type == Internals::JSON_STRING; } | ||||
|   bool isArray() const { | ||||
|     return _type == Internals::JSON_ARRAY; | ||||
|   } | ||||
|   bool isObject() const { | ||||
|     return _type == Internals::JSON_OBJECT; | ||||
|   } | ||||
|   bool isString() const { | ||||
|     return _type == Internals::JSON_STRING; | ||||
|   } | ||||
|  | ||||
|   // The current type of the variant | ||||
|   Internals::JsonVariantType _type; | ||||
| @@ -328,6 +350,3 @@ struct JsonVariant::IsConstructibleFrom { | ||||
|       TypeTraits::IsSame<T, const JsonVariant &>::value; | ||||
| }; | ||||
| } | ||||
|  | ||||
| // Include inline implementations | ||||
| #include "JsonVariant.ipp" | ||||
|   | ||||
| @@ -10,37 +10,15 @@ | ||||
| #include "Configuration.hpp" | ||||
| #include "JsonVariant.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 { | ||||
|  | ||||
| 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 { | ||||
|   using namespace Internals; | ||||
|   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 | ||||
| inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) { | ||||
|   return source.printTo(os); | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Internals/ForceInline.hpp" | ||||
| #include "Polyfills/attributes.hpp" | ||||
| #include "JsonObjectKey.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|   | ||||
| @@ -9,6 +9,8 @@ | ||||
| 
 | ||||
| #ifdef _MSC_VER | ||||
| #define FORCE_INLINE __forceinline | ||||
| #define NO_INLINE __declspec(noinline) | ||||
| #else | ||||
| #define FORCE_INLINE __attribute__((always_inline)) | ||||
| #define NO_INLINE __attribute__((noinline)) | ||||
| #endif | ||||
| @@ -9,6 +9,16 @@ | ||||
|  | ||||
| #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 { | ||||
|  | ||||
| // Implements a JsonBuffer with fixed memory allocation. | ||||
| @@ -19,8 +29,12 @@ class StaticJsonBuffer : public JsonBuffer { | ||||
|  public: | ||||
|   explicit StaticJsonBuffer() : _size(0) {} | ||||
|  | ||||
|   size_t capacity() const { return CAPACITY; } | ||||
|   size_t size() const { return _size; } | ||||
|   size_t capacity() const { | ||||
|     return CAPACITY; | ||||
|   } | ||||
|   size_t size() const { | ||||
|     return _size; | ||||
|   } | ||||
|  | ||||
|   virtual void* alloc(size_t bytes) { | ||||
|     if (_size + bytes > CAPACITY) return NULL; | ||||
| @@ -34,3 +48,11 @@ class StaticJsonBuffer : public JsonBuffer { | ||||
|   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 | ||||
| # 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) | ||||
|  | ||||
| include_directories( | ||||
|     ${GTEST_DIR} | ||||
|     ${GTEST_DIR}/include) | ||||
|  | ||||
| add_definitions(-DGTEST_HAS_PTHREAD=0) | ||||
|  | ||||
| # Workaround for Visual Studio 2012 | ||||
| if (MSVC AND MSVC_VERSION EQUAL 1700) | ||||
|     add_definitions(-D_VARIADIC_MAX=10) | ||||
| 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 (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_compile_options(-W4) | ||||
| endif() | ||||
|  | ||||
| add_executable(ArduinoJsonTests  | ||||
|     ${TESTS_FILES} | ||||
|     ${GTEST_DIR}/src/gtest-all.cc | ||||
|     ${GTEST_DIR}/src/gtest_main.cc) | ||||
|  | ||||
|  | ||||
| target_link_libraries(ArduinoJsonTests ArduinoJson) | ||||
| add_executable(ArduinoJsonTests ${TESTS_FILES}) | ||||
| target_include_directories(ArduinoJsonTests PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../include) | ||||
| target_link_libraries(ArduinoJsonTests gtest) | ||||
|  | ||||
| add_test(ArduinoJsonTests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ArduinoJsonTests) | ||||
|   | ||||
| @@ -6,11 +6,7 @@ | ||||
| // If you like this project, please add a star! | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
|  | ||||
| #define protected public | ||||
| #include <ArduinoJson/DynamicJsonBuffer.hpp> | ||||
|  | ||||
| using namespace ArduinoJson; | ||||
| #include <ArduinoJson.h> | ||||
|  | ||||
| class DynamicJsonBuffer_Basic_Tests : public testing::Test { | ||||
|  protected: | ||||
|   | ||||
| @@ -44,7 +44,7 @@ TEST(JsonArray_CopyTo_Tests, TwoOneDimensionIntegerArray) { | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonArray& array = jsonBuffer.parseArray(json); | ||||
|  | ||||
|   int destination[3][2] = {0}; | ||||
|   int destination[3][2] = {{0}}; | ||||
|   array.copyTo(destination); | ||||
|  | ||||
|   ASSERT_EQ(1, destination[0][0]); | ||||
|   | ||||
| @@ -6,9 +6,7 @@ | ||||
| // If you like this project, please add a star! | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
| #include <ArduinoJson/JsonVariant.hpp> | ||||
|  | ||||
| using namespace ArduinoJson; | ||||
| #include <ArduinoJson.h> | ||||
|  | ||||
| class JsonVariant_Comparison_Tests : public ::testing::Test { | ||||
|  protected: | ||||
|   | ||||
| @@ -6,11 +6,7 @@ | ||||
| // If you like this project, please add a star! | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
|  | ||||
| #define protected public | ||||
| #include <ArduinoJson/StaticJsonBuffer.hpp> | ||||
|  | ||||
| using namespace ArduinoJson; | ||||
| #include <ArduinoJson.h> | ||||
|  | ||||
| class StaticJsonBuffer_Basic_Tests : public testing::Test { | ||||
|  protected: | ||||
|   | ||||
| @@ -10,9 +10,13 @@ | ||||
|  | ||||
| class StaticJsonBuffer_ParseArray_Tests : public testing::Test { | ||||
|  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() { | ||||
|     EXPECT_TRUE(_jsonBuffer->parseArray(_jsonString).success()); | ||||
| @@ -73,9 +77,12 @@ TEST_F(StaticJsonBuffer_ParseArray_Tests, | ||||
| } | ||||
|  | ||||
| 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) { | ||||
|   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 { | ||||
|  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() { | ||||
|     EXPECT_TRUE(_jsonBuffer->parseObject(_jsonString).success()); | ||||
| @@ -74,9 +78,12 @@ TEST_F(StaticJsonBuffer_ParseObject_Tests, | ||||
| } | ||||
|  | ||||
| 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) { | ||||
|   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: | ||||
| //     pump.py gtest-param-test.h.pump | ||||
| // DO NOT EDIT BY HAND!!! | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| // clang-format off | ||||
| #ifdef __GNUC__ | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
|  | ||||
| // Copyright 2005, Google Inc. | ||||
| // All rights reserved. | ||||
| // | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| // clang-format off | ||||
| #ifdef __GNUC__ | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
|  | ||||
| // Copyright 2005, Google Inc. | ||||
| // All rights reserved. | ||||
| // | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| // clang-format off | ||||
| #ifdef __GNUC__ | ||||
| #pragma GCC system_header | ||||
| #endif | ||||
|  | ||||
| // Copyright 2005, Google Inc. | ||||
| // All rights reserved. | ||||
| // | ||||
|   | ||||
		Reference in New Issue
	
	Block a user