mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Added support of long long (issue #171)
				
					
				
			Moved all build settings to `ArduinoJson/Configuration.hpp` Added AppVeyor settings in source tree
This commit is contained in:
		| @@ -1,3 +1,4 @@ | |||||||
| # http://clang.llvm.org/docs/ClangFormatStyleOptions.html | # http://clang.llvm.org/docs/ClangFormatStyleOptions.html | ||||||
|  |  | ||||||
| BasedOnStyle: Google | BasedOnStyle: Google | ||||||
|  | Standard: Cpp03 | ||||||
| @@ -1,6 +1,15 @@ | |||||||
| ArduinoJson: change log | ArduinoJson: change log | ||||||
| ======================= | ======================= | ||||||
|  |  | ||||||
|  | v5.1.0 | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | * Added support of `long long` (issue #171) | ||||||
|  | * Moved all build settings to `ArduinoJson/Configuration.hpp` | ||||||
|  |  | ||||||
|  | **BREAKING CHANGE**: | ||||||
|  | If you defined `ARDUINOJSON_ENABLE_STD_STREAM`, you now need to define it to `1`. | ||||||
|  |  | ||||||
| v5.0.8 | v5.0.8 | ||||||
| ------ | ------ | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								appveyor.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								appveyor.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | version: 5.1.0.{build} | ||||||
|  | environment: | ||||||
|  |   matrix: | ||||||
|  |   - CMAKE_GENERATOR: Visual Studio 14 2015 | ||||||
|  |   - CMAKE_GENERATOR: Visual Studio 12 2013 | ||||||
|  |   - CMAKE_GENERATOR: Visual Studio 11 2012 | ||||||
|  |   - CMAKE_GENERATOR: Visual Studio 10 2010 | ||||||
|  |   - CMAKE_GENERATOR: MinGW Makefiles | ||||||
|  | configuration: Debug | ||||||
|  | before_build: | ||||||
|  | - set PATH=C:\MinGW\bin;%PATH:C:\Program Files\Git\usr\bin;=% # Workaround for CMake not wanting sh.exe on PATH for MinGW | ||||||
|  | - cmake -DCMAKE_BUILD_TYPE=%CONFIGURATION% -G "%CMAKE_GENERATOR%" . | ||||||
|  | build_script: | ||||||
|  | - cmake --build . --config %CONFIGURATION% | ||||||
|  | test_script: | ||||||
|  | - ctest -V .  | ||||||
| @@ -9,8 +9,19 @@ | |||||||
|  |  | ||||||
| #ifndef ARDUINO | #ifndef ARDUINO | ||||||
|  |  | ||||||
|  | #include "../Internals/JsonFloat.hpp" | ||||||
|  | #include "../Internals/JsonInteger.hpp" | ||||||
|  |  | ||||||
| #include <stddef.h> | #include <stddef.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | #if defined(_MSC_VER) && _MSC_VER <= 1800 | ||||||
|  | // snprintf has been added in Visual Studio 2015 | ||||||
|  | #define ARDUINOJSON_SNPRINTF _snprintf | ||||||
|  | #else | ||||||
|  | #define ARDUINOJSON_SNPRINTF snprintf | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // This class reproduces Arduino's Print class | // This class reproduces Arduino's Print class | ||||||
| class Print { | class Print { | ||||||
| @@ -19,11 +30,56 @@ class Print { | |||||||
|  |  | ||||||
|   virtual size_t write(uint8_t) = 0; |   virtual size_t write(uint8_t) = 0; | ||||||
|  |  | ||||||
|   size_t print(const char[]); |   size_t print(const char* s) { | ||||||
|   size_t print(double, int = 2); |     size_t n = 0; | ||||||
|   size_t print(int); |     while (*s) { | ||||||
|   size_t print(long); |       n += write(*s++); | ||||||
|   size_t println(); |     } | ||||||
|  |     return n; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t print(ArduinoJson::Internals::JsonFloat value, int digits = 2) { | ||||||
|  |     char tmp[32]; | ||||||
|  |  | ||||||
|  |     // https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L220 | ||||||
|  |     bool isBigDouble = value > 4294967040.0 || value < -4294967040.0; | ||||||
|  |  | ||||||
|  |     if (isBigDouble) { | ||||||
|  |       // Arduino's implementation prints "ovf" | ||||||
|  |       // We prefer using the scientific notation, since we have sprintf | ||||||
|  |       ARDUINOJSON_SNPRINTF(tmp, sizeof(tmp), "%g", value); | ||||||
|  |     } else { | ||||||
|  |       // Here we have the exact same output as Arduino's implementation | ||||||
|  |       ARDUINOJSON_SNPRINTF(tmp, sizeof(tmp), "%.*f", digits, value); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return print(tmp); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t print(ArduinoJson::Internals::JsonInteger value) { | ||||||
|  |     // see http://clc-wiki.net/wiki/K%26R2_solutions:Chapter_3:Exercise_4 | ||||||
|  |     char buffer[22]; | ||||||
|  |  | ||||||
|  |     size_t n = 0; | ||||||
|  |     if (value < 0) { | ||||||
|  |       value = -value; | ||||||
|  |       n += write('-'); | ||||||
|  |     } | ||||||
|  |     uint8_t i = 0; | ||||||
|  |     do { | ||||||
|  |       ArduinoJson::Internals::JsonInteger digit = value % 10; | ||||||
|  |       value /= 10; | ||||||
|  |       buffer[i++] = static_cast<char>(digit >= 0 ? '0' + digit : '0' - digit); | ||||||
|  |     } while (value); | ||||||
|  |  | ||||||
|  |     while (i > 0) { | ||||||
|  |       n += write(buffer[--i]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return n; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   size_t println() { return write('\r') + write('\n'); } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #else | #else | ||||||
|   | |||||||
							
								
								
									
										79
									
								
								include/ArduinoJson/Configuration.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								include/ArduinoJson/Configuration.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #ifdef ARDUINO  // assume this is an embedded platform | ||||||
|  |  | ||||||
|  | // store using float instead of double to reduce the memory usage (issue #134) | ||||||
|  | #ifndef ARDUINOJSON_USE_DOUBLE | ||||||
|  | #define ARDUINOJSON_USE_DOUBLE 0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // store using a long because it usually match the size of a float. | ||||||
|  | #ifndef ARDUINOJSON_USE_LONG_LONG | ||||||
|  | #define ARDUINOJSON_USE_LONG_LONG 0 | ||||||
|  | #endif | ||||||
|  | #ifndef ARDUINOJSON_USE_INT64 | ||||||
|  | #define ARDUINOJSON_USE_INT64 0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // arduino doesn't support STL stream | ||||||
|  | #ifndef ARDUINOJSON_ENABLE_STD_STREAM | ||||||
|  | #define ARDUINOJSON_ENABLE_STD_STREAM 0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef ARDUINOJSON_ENABLE_ALIGNMENT | ||||||
|  | #ifdef ARDUINO_ARCH_AVR | ||||||
|  | // alignment isn't needed for 8-bit AVR | ||||||
|  | #define ARDUINOJSON_ENABLE_ALIGNMENT 0 | ||||||
|  | #else | ||||||
|  | // but must processor needs pointer to be align on word size | ||||||
|  | #define ARDUINOJSON_ENABLE_ALIGNMENT 1 | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #else  // assume this is a computer | ||||||
|  |  | ||||||
|  | // on a computer we have plenty of memory so we can use doubles | ||||||
|  | #ifndef ARDUINOJSON_USE_DOUBLE | ||||||
|  | #define ARDUINOJSON_USE_DOUBLE 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // use long long when available | ||||||
|  | #ifndef ARDUINOJSON_USE_LONG_LONG | ||||||
|  | #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) | ||||||
|  | #define ARDUINOJSON_USE_LONG_LONG 1 | ||||||
|  | #else | ||||||
|  | #define ARDUINOJSON_USE_LONG_LONG 0 | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // use _int64 on old versions of Visual Studio | ||||||
|  | #ifndef ARDUINOJSON_USE_INT64 | ||||||
|  | #if defined(_MSC_VER) && _MSC_VER <= 1700 | ||||||
|  | #define ARDUINOJSON_USE_INT64 1 | ||||||
|  | #else | ||||||
|  | #define ARDUINOJSON_USE_INT64 0 | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // on a computer, we can assume that the STL is there | ||||||
|  | #ifndef ARDUINOJSON_ENABLE_STD_STREAM | ||||||
|  | #define ARDUINOJSON_ENABLE_STD_STREAM 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef ARDUINOJSON_ENABLE_ALIGNMENT | ||||||
|  | // even if not required, most cpu's are faster with aligned pointers | ||||||
|  | #define ARDUINOJSON_ENABLE_ALIGNMENT 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64 | ||||||
|  | #error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together | ||||||
|  | #endif | ||||||
| @@ -7,15 +7,15 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include "../Configuration.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
|  |  | ||||||
| #ifdef ARDUINO | #if ARDUINOJSON_USE_DOUBLE | ||||||
| // On embedded platform, we with use float instead of double to keep JsonVariant |  | ||||||
| // small (issue #134) |  | ||||||
| typedef float JsonFloat; |  | ||||||
| #else |  | ||||||
| typedef double JsonFloat; | typedef double JsonFloat; | ||||||
|  | #else | ||||||
|  | typedef float JsonFloat; | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,8 +7,17 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include "../Configuration.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_USE_LONG_LONG | ||||||
|  | typedef long long JsonInteger; | ||||||
|  | #elif ARDUINOJSON_USE_INT64 | ||||||
|  | typedef __int64 JsonInteger; | ||||||
|  | #else | ||||||
| typedef long JsonInteger; | typedef long JsonInteger; | ||||||
|  | #endif | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include "../Configuration.hpp" | ||||||
| #include "DummyPrint.hpp" | #include "DummyPrint.hpp" | ||||||
| #include "IndentedPrint.hpp" | #include "IndentedPrint.hpp" | ||||||
| #include "JsonWriter.hpp" | #include "JsonWriter.hpp" | ||||||
| @@ -14,7 +15,7 @@ | |||||||
| #include "StaticStringBuilder.hpp" | #include "StaticStringBuilder.hpp" | ||||||
| #include "DynamicStringBuilder.hpp" | #include "DynamicStringBuilder.hpp" | ||||||
|  |  | ||||||
| #ifdef ARDUINOJSON_ENABLE_STD_STREAM | #if ARDUINOJSON_ENABLE_STD_STREAM | ||||||
| #include "StreamPrintAdapter.hpp" | #include "StreamPrintAdapter.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -34,7 +35,7 @@ class JsonPrintable { | |||||||
|     return writer.bytesWritten(); |     return writer.bytesWritten(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| #ifdef ARDUINOJSON_ENABLE_STD_STREAM | #if ARDUINOJSON_ENABLE_STD_STREAM | ||||||
|   std::ostream &printTo(std::ostream &os) const { |   std::ostream &printTo(std::ostream &os) const { | ||||||
|     StreamPrintAdapter adapter(os); |     StreamPrintAdapter adapter(os); | ||||||
|     printTo(adapter); |     printTo(adapter); | ||||||
| @@ -86,7 +87,7 @@ class JsonPrintable { | |||||||
|   const T &downcast() const { return *static_cast<const T *>(this); } |   const T &downcast() const { return *static_cast<const T *>(this); } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #ifdef ARDUINOJSON_ENABLE_STD_STREAM | #if ARDUINOJSON_ENABLE_STD_STREAM | ||||||
| template <typename T> | template <typename T> | ||||||
| inline std::ostream &operator<<(std::ostream &os, const JsonPrintable<T> &v) { | inline std::ostream &operator<<(std::ostream &os, const JsonPrintable<T> &v) { | ||||||
|   return v.printTo(os); |   return v.printTo(os); | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								include/ArduinoJson/Internals/Parse.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								include/ArduinoJson/Internals/Parse.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  | template <typename TFloat> | ||||||
|  | TFloat parse(const char *); | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | inline float parse<float>(const char *s) { | ||||||
|  |   return static_cast<float>(strtod(s, NULL)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | inline double parse<double>(const char *s) { | ||||||
|  |   return strtod(s, NULL); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | inline long parse<long>(const char *s) { | ||||||
|  |   return strtol(s, NULL, 10); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | inline int parse<int>(const char *s) { | ||||||
|  |   return atoi(s); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_USE_LONG_LONG | ||||||
|  | template <> | ||||||
|  | inline long long parse<long long>(const char *s) { | ||||||
|  |   return strtoll(s, NULL, 10); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_USE_INT64 | ||||||
|  | template <> | ||||||
|  | inline __int64 parse<__int64>(const char *s) { | ||||||
|  |   return _strtoi64(s, NULL, 10); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | } | ||||||
| @@ -7,10 +7,14 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #ifdef ARDUINOJSON_ENABLE_STD_STREAM | #include "../Configuration.hpp" | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_ENABLE_STD_STREAM | ||||||
|  |  | ||||||
| #include "../Arduino/Print.hpp" | #include "../Arduino/Print.hpp" | ||||||
|  |  | ||||||
|  | #include <ostream> | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,6 +12,10 @@ | |||||||
| #include "Internals/List.hpp" | #include "Internals/List.hpp" | ||||||
| #include "Internals/ReferenceType.hpp" | #include "Internals/ReferenceType.hpp" | ||||||
| #include "JsonVariant.hpp" | #include "JsonVariant.hpp" | ||||||
|  | #include "TypeTraits/EnableIf.hpp" | ||||||
|  | #include "TypeTraits/IsFloatingPoint.hpp" | ||||||
|  | #include "TypeTraits/IsReference.hpp" | ||||||
|  | #include "TypeTraits/IsSame.hpp" | ||||||
|  |  | ||||||
| // Returns the size (in bytes) of an array with n elements. | // Returns the size (in bytes) of an array with n elements. | ||||||
| // Can be very handy to determine the size of a StaticJsonBuffer. | // Can be very handy to determine the size of a StaticJsonBuffer. | ||||||
| @@ -36,6 +40,15 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|                   public Internals::List<JsonVariant>, |                   public Internals::List<JsonVariant>, | ||||||
|                   public Internals::JsonBufferAllocated { |                   public Internals::JsonBufferAllocated { | ||||||
|  public: |  public: | ||||||
|  |   // A meta-function that returns true if type T can be used in | ||||||
|  |   // JsonArray::set() | ||||||
|  |   template <typename T> | ||||||
|  |   struct CanSet { | ||||||
|  |     static const bool value = JsonVariant::IsConstructibleFrom<T>::value || | ||||||
|  |                               TypeTraits::IsSame<T, String &>::value || | ||||||
|  |                               TypeTraits::IsSame<T, const String &>::value; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   // Create an empty JsonArray attached to the specified JsonBuffer. |   // Create an empty JsonArray attached to the specified JsonBuffer. | ||||||
|   // You should not call this constructor directly. |   // You should not call this constructor directly. | ||||||
|   // Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray(). |   // Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray(). | ||||||
| @@ -49,42 +62,74 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   FORCE_INLINE JsonArraySubscript operator[](size_t index); |   FORCE_INLINE 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. | ||||||
|   FORCE_INLINE bool add(bool value); |   // | ||||||
|   FORCE_INLINE bool add(float value, uint8_t decimals = 2); |   // bool add(bool); | ||||||
|   FORCE_INLINE bool add(double value, uint8_t decimals = 2); |   // bool add(char); | ||||||
|   FORCE_INLINE bool add(signed char value); |   // bool add(long); | ||||||
|   FORCE_INLINE bool add(signed long value); |   // bool add(int); | ||||||
|   FORCE_INLINE bool add(signed int value); |   // bool add(short); | ||||||
|   FORCE_INLINE bool add(signed short value); |   // bool add(float value); | ||||||
|   FORCE_INLINE bool add(unsigned char value); |   // bool add(double value); | ||||||
|   FORCE_INLINE bool add(unsigned long value); |   // bool add(const char*); | ||||||
|   FORCE_INLINE bool add(unsigned int value); |  | ||||||
|   FORCE_INLINE bool add(unsigned short value); |  | ||||||
|   FORCE_INLINE bool add(const char *value); |  | ||||||
|   FORCE_INLINE bool add(const String &value); |  | ||||||
|   FORCE_INLINE bool add(JsonArray &array); |  | ||||||
|   FORCE_INLINE bool add(JsonObject &object); |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool add(const T &value); |   FORCE_INLINE bool add( | ||||||
|  |       T value, | ||||||
|  |       typename TypeTraits::EnableIf< | ||||||
|  |           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) { | ||||||
|  |     return addNode<T>(value); | ||||||
|  |   } | ||||||
|  |   // bool add(const String&) | ||||||
|  |   // bool add(const JsonVariant&); | ||||||
|  |   // bool add(JsonArray&); | ||||||
|  |   // bool add(JsonObject&); | ||||||
|  |   template <typename T> | ||||||
|  |   FORCE_INLINE 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) { | ||||||
|  |     return addNode<JsonVariant>(JsonVariant(value, decimals)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Sets the value at specified index. |   // Sets the value at specified index. | ||||||
|   FORCE_INLINE void set(size_t index, bool value); |   // | ||||||
|   FORCE_INLINE void set(size_t index, float value, uint8_t decimals = 2); |   // bool set(size_t index, bool value); | ||||||
|   FORCE_INLINE void set(size_t index, double value, uint8_t decimals = 2); |   // bool set(size_t index, long value); | ||||||
|   FORCE_INLINE void set(size_t index, signed char value); |   // bool set(size_t index, int value); | ||||||
|   FORCE_INLINE void set(size_t index, signed long value); |   // bool set(size_t index, short value); | ||||||
|   FORCE_INLINE void set(size_t index, signed int value); |  | ||||||
|   FORCE_INLINE void set(size_t index, signed short value); |  | ||||||
|   FORCE_INLINE void set(size_t index, unsigned char value); |  | ||||||
|   FORCE_INLINE void set(size_t index, unsigned long value); |  | ||||||
|   FORCE_INLINE void set(size_t index, unsigned int value); |  | ||||||
|   FORCE_INLINE void set(size_t index, unsigned short value); |  | ||||||
|   FORCE_INLINE void set(size_t index, const char *value); |  | ||||||
|   FORCE_INLINE void set(size_t index, const String &value); |  | ||||||
|   FORCE_INLINE void set(size_t index, JsonArray &array); |  | ||||||
|   FORCE_INLINE void set(size_t index, JsonObject &object); |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE void set(size_t index, const T &value); |   FORCE_INLINE bool set( | ||||||
|  |       size_t index, T value, | ||||||
|  |       typename TypeTraits::EnableIf< | ||||||
|  |           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) { | ||||||
|  |     return setNodeAt<T>(index, value); | ||||||
|  |   } | ||||||
|  |   // bool set(size_t index, const String&) | ||||||
|  |   // bool set(size_t index, const JsonVariant&); | ||||||
|  |   // 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) { | ||||||
|  |     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) { | ||||||
|  |     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; |   FORCE_INLINE JsonVariant get(size_t index) const; | ||||||
| @@ -120,13 +165,13 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   node_type *getNodeAt(size_t index) const; |   node_type *getNodeAt(size_t index) const; | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   void setNodeAt(size_t index, TValue value); |   bool setNodeAt(size_t index, TValue value); | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   bool addNode(TValue); |   bool addNode(TValue); | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE void setNodeValue(node_type *, T value); |   FORCE_INLINE bool setNodeValue(node_type *, T value); | ||||||
|  |  | ||||||
|   // The instance returned by JsonArray::invalid() |   // The instance returned by JsonArray::invalid() | ||||||
|   static JsonArray _invalid; |   static JsonArray _invalid; | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "JsonArray.hpp" | #include "JsonArray.hpp" | ||||||
|  | #include "JsonObject.hpp" | ||||||
| #include "JsonArraySubscript.hpp" | #include "JsonArraySubscript.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| @@ -20,157 +21,30 @@ inline JsonVariant JsonArray::operator[](size_t index) const { | |||||||
|   return get(index); |   return get(index); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool JsonArray::add(bool value) { return addNode<bool>(value); } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(float value, uint8_t decimals) { |  | ||||||
|   return addNode<const JsonVariant &>(JsonVariant(value, decimals)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(double value, uint8_t decimals) { |  | ||||||
|   return addNode<const JsonVariant &>(JsonVariant(value, decimals)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(signed char value) { |  | ||||||
|   return addNode<signed char>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(signed long value) { |  | ||||||
|   return addNode<signed long>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(signed int value) { |  | ||||||
|   return addNode<signed int>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(signed short value) { |  | ||||||
|   return addNode<signed short>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(unsigned char value) { |  | ||||||
|   return addNode<unsigned char>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(unsigned long value) { |  | ||||||
|   return addNode<unsigned long>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(unsigned int value) { |  | ||||||
|   return addNode<unsigned int>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(unsigned short value) { |  | ||||||
|   return addNode<unsigned short>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(const char *value) { |  | ||||||
|   return addNode<const char *>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(const String &value) { |  | ||||||
|   return addNode<const String &>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(JsonArray &array) { |  | ||||||
|   return addNode<JsonArray &>(array); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonArray::add(JsonObject &object) { |  | ||||||
|   return addNode<JsonObject &>(object); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline bool JsonArray::add(const T &variant) { |  | ||||||
|   return addNode<const JsonVariant &>(variant); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename TValue> | template <typename TValue> | ||||||
| inline bool JsonArray::addNode(TValue value) { | inline bool JsonArray::addNode(TValue value) { | ||||||
|   node_type *node = addNewNode(); |   node_type *node = addNewNode(); | ||||||
|   if (node == NULL) return false; |   return node != NULL && setNodeValue<TValue>(node, value); | ||||||
|   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; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, bool value) { |  | ||||||
|   return setNodeAt<bool>(index, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, float value, uint8_t decimals) { |  | ||||||
|   return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, double value, uint8_t decimals) { |  | ||||||
|   return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, signed char value) { |  | ||||||
|   return setNodeAt<signed char>(index, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, signed long value) { |  | ||||||
|   return setNodeAt<signed long>(index, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, signed int value) { |  | ||||||
|   return setNodeAt<signed int>(index, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, signed short value) { |  | ||||||
|   return setNodeAt<signed short>(index, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, unsigned char value) { |  | ||||||
|   return setNodeAt<unsigned char>(index, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, unsigned long value) { |  | ||||||
|   return setNodeAt<unsigned long>(index, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, unsigned int value) { |  | ||||||
|   return setNodeAt<unsigned int>(index, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, unsigned short value) { |  | ||||||
|   return setNodeAt<unsigned short>(index, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, const char *value) { |  | ||||||
|   return setNodeAt<const char *>(index, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, const String &value) { |  | ||||||
|   return setNodeAt<const String &>(index, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, JsonArray &array) { |  | ||||||
|   return setNodeAt<JsonArray &>(index, array); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void JsonArray::set(size_t index, JsonObject &object) { |  | ||||||
|   return setNodeAt<JsonObject &>(index, object); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline void JsonArray::set(size_t index, const T &variant) { |  | ||||||
|   return setNodeAt<const JsonVariant &>(index, variant); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename TValue> |  | ||||||
| inline void JsonArray::setNodeAt(size_t index, TValue value) { |  | ||||||
|   node_type *node = getNodeAt(index); |  | ||||||
|   if (node == NULL) return; |  | ||||||
|   setNodeValue<TValue>(node, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename TValue> |  | ||||||
| inline void JsonArray::setNodeValue(node_type *node, TValue value) { |  | ||||||
|   node->content = value; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> | template <> | ||||||
| inline void JsonArray::setNodeValue(node_type *node, const String &value) { | inline bool JsonArray::setNodeValue(node_type *node, String &value) { | ||||||
|   node->content = _buffer->strdup(value); |   const char *copy = _buffer->strdup(value); | ||||||
|  |   if (!copy) return false; | ||||||
|  |   node->content = copy; | ||||||
|  |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonVariant JsonArray::get(size_t index) const { | inline JsonVariant JsonArray::get(size_t index) const { | ||||||
| @@ -206,15 +80,22 @@ inline JsonArray const &JsonVariant::invalid<JsonArray const &>() { | |||||||
|   return JsonArray::invalid(); |   return JsonArray::invalid(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <> | inline JsonArray &JsonVariant::asArray() const { | ||||||
| inline JsonArray &JsonVariant::as<JsonArray &>() const { |  | ||||||
|   if (_type == Internals::JSON_ARRAY) return *_content.asArray; |   if (_type == Internals::JSON_ARRAY) return *_content.asArray; | ||||||
|   return JsonArray::invalid(); |   return JsonArray::invalid(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <> | inline JsonArray &JsonArray::createNestedArray() { | ||||||
| inline const JsonArray &JsonVariant::as<const JsonArray &>() const { |   if (!_buffer) return JsonArray::invalid(); | ||||||
|   if (_type == Internals::JSON_ARRAY) return *_content.asArray; |   JsonArray &array = _buffer->createArray(); | ||||||
|   return JsonArray::invalid(); |   add(array); | ||||||
|  |   return array; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline JsonArray &JsonObject::createNestedArray(JsonObjectKey key) { | ||||||
|  |   if (!_buffer) return JsonArray::invalid(); | ||||||
|  |   JsonArray &array = _buffer->createArray(); | ||||||
|  |   setNodeAt<const JsonVariant &>(key, array); | ||||||
|  |   return array; | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,7 +7,8 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "JsonSubscriptBase.hpp" | #include "Configuration.hpp" | ||||||
|  | #include "JsonVariantBase.hpp" | ||||||
|  |  | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
| #pragma warning(push) | #pragma warning(push) | ||||||
| @@ -15,20 +16,30 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| class JsonArraySubscript : public JsonSubscriptBase<JsonArraySubscript> { | class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | ||||||
|  public: |  public: | ||||||
|   FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index) |   FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index) | ||||||
|       : _array(array), _index(index) {} |       : _array(array), _index(index) {} | ||||||
|  |  | ||||||
|   using JsonSubscriptBase<JsonArraySubscript>::operator=; |  | ||||||
|  |  | ||||||
|   JsonArraySubscript& operator=(const JsonArraySubscript& src) { |   JsonArraySubscript& operator=(const JsonArraySubscript& src) { | ||||||
|     return assign<const JsonVariant&>(src); |     _array.set<const JsonVariant&>(_index, src); | ||||||
|  |     return *this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   JsonArraySubscript& operator=(const T& src) { |   typename TypeTraits::EnableIf<JsonArray::CanSet<T&>::value, | ||||||
|     return assign<const JsonVariant&>(src); |                                 JsonArraySubscript>::type& | ||||||
|  |   operator=(const T& src) { | ||||||
|  |     _array.set<T&>(_index, const_cast<T&>(src)); | ||||||
|  |     return *this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename T> | ||||||
|  |   typename TypeTraits::EnableIf<JsonArray::CanSet<T>::value, | ||||||
|  |                                 JsonArraySubscript>::type& | ||||||
|  |   operator=(T src) { | ||||||
|  |     _array.set<T>(_index, src); | ||||||
|  |     return *this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE bool success() const { return _index < _array.size(); } |   FORCE_INLINE bool success() const { return _index < _array.size(); } | ||||||
| @@ -59,7 +70,7 @@ class JsonArraySubscript : public JsonSubscriptBase<JsonArraySubscript> { | |||||||
|   const size_t _index; |   const size_t _index; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #ifdef ARDUINOJSON_ENABLE_STD_STREAM | #if ARDUINOJSON_ENABLE_STD_STREAM | ||||||
| inline std::ostream& operator<<(std::ostream& os, | inline std::ostream& operator<<(std::ostream& os, | ||||||
|                                 const JsonArraySubscript& source) { |                                 const JsonArraySubscript& source) { | ||||||
|   return source.printTo(os); |   return source.printTo(os); | ||||||
|   | |||||||
| @@ -107,12 +107,11 @@ class JsonBuffer { | |||||||
|  protected: |  protected: | ||||||
|   // Preserve aligment if nessary |   // Preserve aligment if nessary | ||||||
|   static FORCE_INLINE size_t round_size_up(size_t bytes) { |   static FORCE_INLINE size_t round_size_up(size_t bytes) { | ||||||
| #if defined ARDUINO_ARCH_AVR | #if ARDUINOJSON_ENABLE_ALIGNMENT | ||||||
|     // alignment isn't needed for 8-bit AVR |  | ||||||
|     return bytes; |  | ||||||
| #else |  | ||||||
|     const size_t x = sizeof(void *) - 1; |     const size_t x = sizeof(void *) - 1; | ||||||
|     return (bytes + x) & ~x; |     return (bytes + x) & ~x; | ||||||
|  | #else | ||||||
|  |     return bytes; | ||||||
| #endif | #endif | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,6 +13,10 @@ | |||||||
| #include "Internals/List.hpp" | #include "Internals/List.hpp" | ||||||
| #include "Internals/ReferenceType.hpp" | #include "Internals/ReferenceType.hpp" | ||||||
| #include "JsonPair.hpp" | #include "JsonPair.hpp" | ||||||
|  | #include "TypeTraits/EnableIf.hpp" | ||||||
|  | #include "TypeTraits/IsFloatingPoint.hpp" | ||||||
|  | #include "TypeTraits/IsReference.hpp" | ||||||
|  | #include "TypeTraits/IsSame.hpp" | ||||||
|  |  | ||||||
| // Returns the size (in bytes) of an object with n elements. | // Returns the size (in bytes) of an object with n elements. | ||||||
| // Can be very handy to determine the size of a StaticJsonBuffer. | // Can be very handy to determine the size of a StaticJsonBuffer. | ||||||
| @@ -36,6 +40,15 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|                    public Internals::List<JsonPair>, |                    public Internals::List<JsonPair>, | ||||||
|                    public Internals::JsonBufferAllocated { |                    public Internals::JsonBufferAllocated { | ||||||
|  public: |  public: | ||||||
|  |   // A meta-function that returns true if type T can be used in | ||||||
|  |   // JsonObject::set() | ||||||
|  |   template <typename T> | ||||||
|  |   struct CanSet { | ||||||
|  |     static const bool value = JsonVariant::IsConstructibleFrom<T>::value || | ||||||
|  |                               TypeTraits::IsSame<T, String&>::value || | ||||||
|  |                               TypeTraits::IsSame<T, const String&>::value; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|   // 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(). | ||||||
| @@ -50,43 +63,40 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   FORCE_INLINE JsonVariant operator[](JsonObjectKey key) const; |   FORCE_INLINE JsonVariant operator[](JsonObjectKey key) const; | ||||||
|  |  | ||||||
|   // Sets the specified key with the specified value. |   // Sets the specified key with the specified value. | ||||||
|   FORCE_INLINE bool set(const char* key, bool value); |   // bool set(TKey key, bool value); | ||||||
|   FORCE_INLINE bool set(const char* key, float value, uint8_t decimals = 2); |   // bool set(TKey key, char value); | ||||||
|   FORCE_INLINE bool set(const char* key, double value, uint8_t decimals = 2); |   // bool set(TKey key, long value); | ||||||
|   FORCE_INLINE bool set(const char* key, signed char value); |   // bool set(TKey key, int value); | ||||||
|   FORCE_INLINE bool set(const char* key, signed long value); |   // bool set(TKey key, short value); | ||||||
|   FORCE_INLINE bool set(const char* key, signed int value); |   // bool set(TKey key, float value); | ||||||
|   FORCE_INLINE bool set(const char* key, signed short value); |   // bool set(TKey key, double value); | ||||||
|   FORCE_INLINE bool set(const char* key, unsigned char value); |   // bool set(TKey key, const char* value); | ||||||
|   FORCE_INLINE bool set(const char* key, unsigned long value); |  | ||||||
|   FORCE_INLINE bool set(const char* key, unsigned int value); |  | ||||||
|   FORCE_INLINE bool set(const char* key, unsigned short value); |  | ||||||
|   FORCE_INLINE bool set(const char* key, const char* value); |  | ||||||
|   FORCE_INLINE bool set(const char* key, const String& value); |  | ||||||
|   FORCE_INLINE bool set(const char* key, JsonArray& array); |  | ||||||
|   FORCE_INLINE bool set(const char* key, JsonObject& object); |  | ||||||
|   FORCE_INLINE bool set(const char* key, const JsonVariant& value); |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool set(const char* key, const T& value); |   FORCE_INLINE bool set( | ||||||
|  |       JsonObjectKey key, T value, | ||||||
|   FORCE_INLINE bool set(const String& key, bool value); |       typename TypeTraits::EnableIf< | ||||||
|   FORCE_INLINE bool set(const String& key, float value, uint8_t decimals = 2); |           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type* = 0) { | ||||||
|   FORCE_INLINE bool set(const String& key, double value, uint8_t decimals = 2); |     return setNodeAt<T>(key, value); | ||||||
|   FORCE_INLINE bool set(const String& key, signed char value); |   } | ||||||
|   FORCE_INLINE bool set(const String& key, signed long value); |   // bool set(Key, String&); | ||||||
|   FORCE_INLINE bool set(const String& key, signed int value); |   // bool set(Key, JsonArray&); | ||||||
|   FORCE_INLINE bool set(const String& key, signed short value); |   // bool set(Key, JsonObject&); | ||||||
|   FORCE_INLINE bool set(const String& key, unsigned char value); |   // bool set(Key, JsonVariant&); | ||||||
|   FORCE_INLINE bool set(const String& key, unsigned long value); |  | ||||||
|   FORCE_INLINE bool set(const String& key, unsigned int value); |  | ||||||
|   FORCE_INLINE bool set(const String& key, unsigned short value); |  | ||||||
|   FORCE_INLINE bool set(const String& key, const char* value); |  | ||||||
|   FORCE_INLINE bool set(const String& key, const String& value); |  | ||||||
|   FORCE_INLINE bool set(const String& key, JsonArray& array); |  | ||||||
|   FORCE_INLINE bool set(const String& key, JsonObject& object); |  | ||||||
|   FORCE_INLINE bool set(const String& key, const JsonVariant& value); |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool set(const String& key, const T& value); |   FORCE_INLINE 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) { | ||||||
|  |     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; |   FORCE_INLINE JsonVariant get(JsonObjectKey) const; | ||||||
| @@ -101,13 +111,11 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|  |  | ||||||
|   // 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(const char* key); |   FORCE_INLINE JsonArray& createNestedArray(JsonObjectKey key); | ||||||
|   FORCE_INLINE JsonArray& createNestedArray(const String& 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(const char* key); |   FORCE_INLINE JsonObject& createNestedObject(JsonObjectKey key); | ||||||
|   FORCE_INLINE JsonObject& createNestedObject(const String& 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; |   FORCE_INLINE bool containsKey(JsonObjectKey key) const; | ||||||
| @@ -125,24 +133,17 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   // Returns the list node that matches the specified key. |   // Returns the list node that matches the specified key. | ||||||
|   node_type* getNodeAt(JsonObjectKey key) const; |   node_type* getNodeAt(const char* key) const; | ||||||
|  |  | ||||||
|   node_type* getOrCreateNodeAt(JsonObjectKey key); |   node_type* getOrCreateNodeAt(const char* key); | ||||||
|  |  | ||||||
|   template <typename TKey, typename TValue> |  | ||||||
|   FORCE_INLINE bool setNodeAt(TKey key, TValue value); |  | ||||||
|  |  | ||||||
|   template <typename TKey> |  | ||||||
|   JsonArray& createArrayAt(TKey key); |  | ||||||
|  |  | ||||||
|   template <typename TKey> |  | ||||||
|   JsonObject& createObjectAt(TKey key); |  | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE void setNodeKey(node_type*, T key); |   FORCE_INLINE bool setNodeAt(JsonObjectKey key, T value); | ||||||
|  |  | ||||||
|  |   FORCE_INLINE bool setNodeKey(node_type*, JsonObjectKey key); | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE void setNodeValue(node_type*, T value); |   FORCE_INLINE bool setNodeValue(node_type*, T value); | ||||||
|  |  | ||||||
|   // The instance returned by JsonObject::invalid() |   // The instance returned by JsonObject::invalid() | ||||||
|   static JsonObject _invalid; |   static JsonObject _invalid; | ||||||
|   | |||||||
| @@ -7,25 +7,26 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include "JsonArray.hpp" | ||||||
| #include "JsonObject.hpp" | #include "JsonObject.hpp" | ||||||
| #include "JsonObjectSubscript.hpp" | #include "JsonObjectSubscript.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| inline JsonVariant JsonObject::get(JsonObjectKey key) const { | inline JsonVariant JsonObject::get(JsonObjectKey key) const { | ||||||
|   node_type *node = getNodeAt(key); |   node_type *node = getNodeAt(key.c_str()); | ||||||
|   return node ? node->content.value : JsonVariant(); |   return node ? node->content.value : JsonVariant(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| inline T JsonObject::get(JsonObjectKey key) const { | inline T JsonObject::get(JsonObjectKey key) const { | ||||||
|   node_type *node = getNodeAt(key); |   node_type *node = getNodeAt(key.c_str()); | ||||||
|   return node ? node->content.value.as<T>() : JsonVariant::invalid<T>(); |   return node ? node->content.value.as<T>() : JsonVariant::invalid<T>(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| inline bool JsonObject::is(JsonObjectKey key) const { | inline bool JsonObject::is(JsonObjectKey key) const { | ||||||
|   node_type *node = getNodeAt(key); |   node_type *node = getNodeAt(key.c_str()); | ||||||
|   return node ? node->content.value.is<T>() : false; |   return node ? node->content.value.is<T>() : false; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -44,165 +45,46 @@ inline JsonVariant JsonObject::operator[](JsonObjectKey key) const { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline bool JsonObject::containsKey(JsonObjectKey key) const { | inline bool JsonObject::containsKey(JsonObjectKey key) const { | ||||||
|   return getNodeAt(key) != NULL; |   return getNodeAt(key.c_str()) != NULL; | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonArray &JsonObject::createNestedArray(const char *key) { |  | ||||||
|   return createArrayAt<const char *>(key); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonArray &JsonObject::createNestedArray(const String &key) { |  | ||||||
|   return createArrayAt<const String &>(key); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonObject &JsonObject::createNestedObject(const char *key) { |  | ||||||
|   return createObjectAt<const char *>(key); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonObject &JsonObject::createNestedObject(const String &key) { |  | ||||||
|   return createObjectAt<const String &>(key); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| inline void JsonObject::remove(JsonObjectKey key) { | inline void JsonObject::remove(JsonObjectKey key) { | ||||||
|   removeNode(getNodeAt(key)); |   removeNode(getNodeAt(key.c_str())); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool JsonObject::set(const char *key, bool value) { |  | ||||||
|   return setNodeAt<const char *, bool>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, float value, uint8_t decimals) { |  | ||||||
|   return setNodeAt<const char *, const JsonVariant &>( |  | ||||||
|       key, JsonVariant(value, decimals)); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, double value, uint8_t decimals) { |  | ||||||
|   return setNodeAt<const char *, const JsonVariant &>( |  | ||||||
|       key, JsonVariant(value, decimals)); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, signed char value) { |  | ||||||
|   return setNodeAt<const char *, signed char>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, signed long value) { |  | ||||||
|   return setNodeAt<const char *, signed long>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, signed int value) { |  | ||||||
|   return setNodeAt<const char *, signed int>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, signed short value) { |  | ||||||
|   return setNodeAt<const char *, signed short>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, unsigned char value) { |  | ||||||
|   return setNodeAt<const char *, unsigned char>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, unsigned long value) { |  | ||||||
|   return setNodeAt<const char *, unsigned long>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, unsigned int value) { |  | ||||||
|   return setNodeAt<const char *, unsigned int>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, unsigned short value) { |  | ||||||
|   return setNodeAt<const char *, unsigned short>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, const char *value) { |  | ||||||
|   return setNodeAt<const char *, const char *>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, const String &value) { |  | ||||||
|   return setNodeAt<const char *, const String &>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, JsonArray &array) { |  | ||||||
|   return setNodeAt<const char *, JsonArray &>(key, array); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, JsonObject &object) { |  | ||||||
|   return setNodeAt<const char *, JsonObject &>(key, object); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const char *key, const JsonVariant &value) { |  | ||||||
|   return setNodeAt<const char *, const JsonVariant &>(key, value); |  | ||||||
| } |  | ||||||
| template <typename T> | template <typename T> | ||||||
| inline bool JsonObject::set(const char *key, const T &value) { | inline bool JsonObject::setNodeAt(JsonObjectKey key, T value) { | ||||||
|   return setNodeAt<const char *, JsonVariant>(key, value); |   node_type *node = getNodeAt(key.c_str()); | ||||||
| } |   if (!node) node = addNewNode(); | ||||||
| inline bool JsonObject::set(const String &key, bool value) { |   return node && setNodeKey(node, key) && setNodeValue<T>(node, value); | ||||||
|   return setNodeAt<const String &, bool>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, float value, uint8_t decimals) { |  | ||||||
|   return setNodeAt<const String &, const JsonVariant &>( |  | ||||||
|       key, JsonVariant(value, decimals)); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, double value, uint8_t decimals) { |  | ||||||
|   return setNodeAt<const String &, const JsonVariant &>( |  | ||||||
|       key, JsonVariant(value, decimals)); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, signed char value) { |  | ||||||
|   return setNodeAt<const String &, signed char>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, signed long value) { |  | ||||||
|   return setNodeAt<const String &, signed long>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, signed int value) { |  | ||||||
|   return setNodeAt<const String &, signed int>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, signed short value) { |  | ||||||
|   return setNodeAt<const String &, signed short>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, unsigned char value) { |  | ||||||
|   return setNodeAt<const String &, unsigned char>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, unsigned long value) { |  | ||||||
|   return setNodeAt<const String &, unsigned long>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, unsigned int value) { |  | ||||||
|   return setNodeAt<const String &, unsigned int>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, unsigned short value) { |  | ||||||
|   return setNodeAt<const String &, unsigned short>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, const char *value) { |  | ||||||
|   return setNodeAt<const String &, const char *>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, const String &value) { |  | ||||||
|   return setNodeAt<const String &, const String &>(key, value); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, JsonArray &array) { |  | ||||||
|   return setNodeAt<const String &, JsonArray &>(key, array); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, JsonObject &object) { |  | ||||||
|   return setNodeAt<const String &, JsonObject &>(key, object); |  | ||||||
| } |  | ||||||
| inline bool JsonObject::set(const String &key, const JsonVariant &value) { |  | ||||||
|   return setNodeAt<const String &, const JsonVariant &>(key, value); |  | ||||||
| } |  | ||||||
| template <typename T> |  | ||||||
| inline bool JsonObject::set(const String &key, const T &value) { |  | ||||||
|   return setNodeAt<const String &, JsonVariant>(key, value); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey, typename TValue> | inline bool JsonObject::setNodeKey(node_type *node, JsonObjectKey key) { | ||||||
| inline bool JsonObject::setNodeAt(TKey key, TValue value) { |   if (key.needs_copy()) { | ||||||
|   node_type *node = getOrCreateNodeAt(key); |     node->content.key = _buffer->strdup(key.c_str()); | ||||||
|   if (!node) return false; |     if (node->content.key == NULL) return false; | ||||||
|   setNodeKey<TKey>(node, key); |   } else { | ||||||
|   setNodeValue<TValue>(node, value); |     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; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <> | template <> | ||||||
| inline void JsonObject::setNodeKey(node_type *node, const char *key) { | inline bool JsonObject::setNodeValue(node_type *node, String &value) { | ||||||
|   node->content.key = key; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline void JsonObject::setNodeKey(node_type *node, const String &key) { |  | ||||||
|   node->content.key = _buffer->strdup(key); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename TValue> |  | ||||||
| inline void JsonObject::setNodeValue(node_type *node, TValue value) { |  | ||||||
|   node->content.value = value; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline void JsonObject::setNodeValue(node_type *node, const String &value) { |  | ||||||
|   node->content.value = _buffer->strdup(value); |   node->content.value = _buffer->strdup(value); | ||||||
|  |   return node->content.value; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | inline bool JsonObject::setNodeValue(node_type *node, const String &value) { | ||||||
|  |   node->content.value = _buffer->strdup(value); | ||||||
|  |   return node->content.value; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TImplem> | template <typename TImplem> | ||||||
| @@ -227,15 +109,22 @@ inline JsonObject &JsonVariant::invalid<JsonObject &>() { | |||||||
|   return JsonObject::invalid(); |   return JsonObject::invalid(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <> | inline JsonObject &JsonVariant::asObject() const { | ||||||
| inline JsonObject &JsonVariant::as<JsonObject &>() const { |  | ||||||
|   if (_type == Internals::JSON_OBJECT) return *_content.asObject; |   if (_type == Internals::JSON_OBJECT) return *_content.asObject; | ||||||
|   return JsonObject::invalid(); |   return JsonObject::invalid(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <> | inline JsonObject &JsonObject::createNestedObject(JsonObjectKey key) { | ||||||
| inline const JsonObject &JsonVariant::as<const JsonObject &>() const { |   if (!_buffer) return JsonObject::invalid(); | ||||||
|   if (_type == Internals::JSON_OBJECT) return *_content.asObject; |   JsonObject &array = _buffer->createObject(); | ||||||
|   return JsonObject::invalid(); |   setNodeAt<const JsonVariant &>(key, array); | ||||||
|  |   return array; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline JsonObject &JsonArray::createNestedObject() { | ||||||
|  |   if (!_buffer) return JsonObject::invalid(); | ||||||
|  |   JsonObject &object = _buffer->createObject(); | ||||||
|  |   add(object); | ||||||
|  |   return object; | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,15 +11,17 @@ | |||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
|  | // Represents a key in a JsonObject | ||||||
| class JsonObjectKey { | class JsonObjectKey { | ||||||
|  public: |  public: | ||||||
|   JsonObjectKey() {} |   JsonObjectKey(const char* key) : _value(key), _needs_copy(false) {} | ||||||
|   JsonObjectKey(const char* key) : _data(key) {} |   JsonObjectKey(const String& key) : _value(key.c_str()), _needs_copy(true) {} | ||||||
|   JsonObjectKey(const String& key) : _data(key.c_str()) {} |  | ||||||
|  |  | ||||||
|   operator const char*() const { return _data; } |   const char* c_str() const { return _value; } | ||||||
|  |   bool needs_copy() const { return _needs_copy; } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   const char* _data; |   const char* _value; | ||||||
|  |   bool _needs_copy; | ||||||
| }; | }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,7 +7,9 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "JsonSubscriptBase.hpp" | #include "Configuration.hpp" | ||||||
|  | #include "JsonVariantBase.hpp" | ||||||
|  | #include "TypeTraits/EnableIf.hpp" | ||||||
|  |  | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
| #pragma warning(push) | #pragma warning(push) | ||||||
| @@ -17,23 +19,30 @@ | |||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TKey> | ||||||
| class JsonObjectSubscript | class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > { | ||||||
|     : public JsonSubscriptBase<JsonObjectSubscript<TKey> > { |  | ||||||
|  public: |  public: | ||||||
|   FORCE_INLINE JsonObjectSubscript(JsonObject& object, TKey key) |   FORCE_INLINE JsonObjectSubscript(JsonObject& object, TKey key) | ||||||
|       : _object(object), _key(key) {} |       : _object(object), _key(key) {} | ||||||
|  |  | ||||||
|   using JsonSubscriptBase<JsonObjectSubscript<TKey> >::operator=; |  | ||||||
|  |  | ||||||
|   JsonObjectSubscript<TKey>& operator=(const JsonObjectSubscript<TKey>& src) { |   JsonObjectSubscript<TKey>& operator=(const JsonObjectSubscript<TKey>& src) { | ||||||
|     return JsonSubscriptBase<JsonObjectSubscript<TKey> >::template assign< |     _object.set<const JsonVariant&>(_key, src); | ||||||
|         JsonVariant>(src); |     return *this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   JsonObjectSubscript<TKey>& operator=(const T& src) { |   typename TypeTraits::EnableIf<JsonObject::CanSet<T&>::value, | ||||||
|     return JsonSubscriptBase<JsonObjectSubscript<TKey> >::template assign< |                                 JsonObjectSubscript<TKey> >::type& | ||||||
|         JsonVariant>(src); |   operator=(const T& src) { | ||||||
|  |     _object.set<T&>(_key, const_cast<T&>(src)); | ||||||
|  |     return *this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename T> | ||||||
|  |   typename TypeTraits::EnableIf<JsonObject::CanSet<T>::value, | ||||||
|  |                                 JsonObjectSubscript<TKey> >::type& | ||||||
|  |   operator=(T src) { | ||||||
|  |     _object.set<T>(_key, src); | ||||||
|  |     return *this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE bool success() const { return _object.containsKey(_key); } |   FORCE_INLINE bool success() const { return _object.containsKey(_key); } | ||||||
| @@ -52,7 +61,7 @@ class JsonObjectSubscript | |||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(TValue value) { |   FORCE_INLINE bool set(TValue value) { | ||||||
|     return _object.set(_key, value); |     return _object.set<TValue>(_key, value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
| @@ -71,7 +80,7 @@ class JsonObjectSubscript | |||||||
|   TKey _key; |   TKey _key; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #ifdef ARDUINOJSON_ENABLE_STD_STREAM | #if ARDUINOJSON_ENABLE_STD_STREAM | ||||||
| inline std::ostream& operator<<( | inline std::ostream& operator<<( | ||||||
|     std::ostream& os, const JsonObjectSubscript<const String&>& source) { |     std::ostream& os, const JsonObjectSubscript<const String&>& source) { | ||||||
|   return source.printTo(os); |   return source.printTo(os); | ||||||
| @@ -82,6 +91,7 @@ inline std::ostream& operator<<( | |||||||
|   return source.printTo(os); |   return source.printTo(os); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| }  // namespace ArduinoJson | }  // namespace ArduinoJson | ||||||
|  |  | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ namespace ArduinoJson { | |||||||
|  |  | ||||||
| // A key value pair for JsonObject. | // A key value pair for JsonObject. | ||||||
| struct JsonPair { | struct JsonPair { | ||||||
|   JsonObjectKey key; |   const char* key; | ||||||
|   JsonVariant value; |   JsonVariant value; | ||||||
| }; | }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,83 +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! |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include "JsonVariantBase.hpp" |  | ||||||
|  |  | ||||||
| namespace ArduinoJson { |  | ||||||
|  |  | ||||||
| template <typename TImpl> |  | ||||||
| class JsonSubscriptBase : public JsonVariantBase<TImpl> { |  | ||||||
|  public: |  | ||||||
|   FORCE_INLINE TImpl& operator=(bool value) { return assign<bool>(value); } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(float value) { return assign<float>(value); } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(double value) { return assign<double>(value); } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(signed char value) { |  | ||||||
|     return assign<signed char>(value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(signed long value) { |  | ||||||
|     return assign<signed long>(value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(signed int value) { |  | ||||||
|     return assign<signed int>(value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(signed short value) { |  | ||||||
|     return assign<signed short>(value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(unsigned char value) { |  | ||||||
|     return assign<unsigned char>(value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(unsigned long value) { |  | ||||||
|     return assign<unsigned long>(value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(unsigned int value) { |  | ||||||
|     return assign<unsigned int>(value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(unsigned short value) { |  | ||||||
|     return assign<unsigned short>(value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(const char* value) { |  | ||||||
|     return assign<const char*>(value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(const String& value) { |  | ||||||
|     return assign<const String&>(value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(JsonArray& array) { |  | ||||||
|     return assign<JsonArray&>(array); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(JsonObject& object) { |  | ||||||
|     return assign<JsonObject&>(object); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE TImpl& operator=(JsonVariant value) { |  | ||||||
|     return assign<const JsonVariant&>(value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  protected: |  | ||||||
|   template <typename TValue> |  | ||||||
|   FORCE_INLINE TImpl& assign(TValue value) { |  | ||||||
|     TImpl* that = static_cast<TImpl*>(this); |  | ||||||
|     that->template set<TValue>(value); |  | ||||||
|     return *that; |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| } |  | ||||||
| @@ -15,6 +15,12 @@ | |||||||
| #include "Internals/JsonVariantType.hpp" | #include "Internals/JsonVariantType.hpp" | ||||||
| #include "Internals/Unparsed.hpp" | #include "Internals/Unparsed.hpp" | ||||||
| #include "JsonVariantBase.hpp" | #include "JsonVariantBase.hpp" | ||||||
|  | #include "TypeTraits/EnableIf.hpp" | ||||||
|  | #include "TypeTraits/IsFloatingPoint.hpp" | ||||||
|  | #include "TypeTraits/IsIntegral.hpp" | ||||||
|  | #include "TypeTraits/IsSame.hpp" | ||||||
|  | #include "TypeTraits/RemoveConst.hpp" | ||||||
|  | #include "TypeTraits/RemoveReference.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| @@ -31,6 +37,9 @@ class JsonObject; | |||||||
| // - a reference to a JsonArray or JsonObject | // - a reference to a JsonArray or JsonObject | ||||||
| class JsonVariant : public JsonVariantBase<JsonVariant> { | class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||||
|  public: |  public: | ||||||
|  |   template <typename T> | ||||||
|  |   struct IsConstructibleFrom; | ||||||
|  |  | ||||||
|   // Creates an uninitialized JsonVariant |   // Creates an uninitialized JsonVariant | ||||||
|   FORCE_INLINE JsonVariant() : _type(Internals::JSON_UNDEFINED) {} |   FORCE_INLINE JsonVariant() : _type(Internals::JSON_UNDEFINED) {} | ||||||
|  |  | ||||||
| @@ -41,18 +50,31 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   // 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 | ||||||
|   // the JSON string. |   // the JSON string. | ||||||
|   FORCE_INLINE JsonVariant(float value, uint8_t decimals = 2); |   // JsonVariant(double value, uint8_t decimals); | ||||||
|   FORCE_INLINE JsonVariant(double value, uint8_t decimals = 2); |   // 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) { | ||||||
|  |     using namespace Internals; | ||||||
|  |     _type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals); | ||||||
|  |     _content.asFloat = static_cast<JsonFloat>(value); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Create a JsonVariant containing an integer value. |   // Create a JsonVariant containing an integer value. | ||||||
|   FORCE_INLINE JsonVariant(signed char value); |   // JsonVariant(short) | ||||||
|   FORCE_INLINE JsonVariant(signed long value); |   // JsonVariant(int) | ||||||
|   FORCE_INLINE JsonVariant(signed int value); |   // JsonVariant(long) | ||||||
|   FORCE_INLINE JsonVariant(signed short value); |   template <typename T> | ||||||
|   FORCE_INLINE JsonVariant(unsigned char value); |   FORCE_INLINE JsonVariant( | ||||||
|   FORCE_INLINE JsonVariant(unsigned long value); |       T value, | ||||||
|   FORCE_INLINE JsonVariant(unsigned int value); |       typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value>::type * = | ||||||
|   FORCE_INLINE JsonVariant(unsigned short value); |           0) { | ||||||
|  |     using namespace Internals; | ||||||
|  |     _type = JSON_INTEGER; | ||||||
|  |     _content.asInteger = static_cast<JsonInteger>(value); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Create a JsonVariant containing a string. |   // Create a JsonVariant containing a string. | ||||||
|   FORCE_INLINE JsonVariant(const char *value); |   FORCE_INLINE JsonVariant(const char *value); | ||||||
| @@ -67,9 +89,70 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   FORCE_INLINE JsonVariant(JsonObject &object); |   FORCE_INLINE JsonVariant(JsonObject &object); | ||||||
|  |  | ||||||
|   // Get the variant as the specified type. |   // Get the variant as the specified type. | ||||||
|   // See cast operators for details. |   // short as<short>() const; | ||||||
|  |   // int as<int>() const; | ||||||
|  |   // long as<long>() const; | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   T as() const; |   const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value, T>::type | ||||||
|  |   as() const { | ||||||
|  |     return static_cast<T>(asInteger()); | ||||||
|  |   } | ||||||
|  |   // double as<double>() const; | ||||||
|  |   // float as<float>() const; | ||||||
|  |   template <typename T> | ||||||
|  |   const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value, | ||||||
|  |                                       T>::type | ||||||
|  |   as() const { | ||||||
|  |     return static_cast<T>(asFloat()); | ||||||
|  |   } | ||||||
|  |   // const String as<String>() const; | ||||||
|  |   template <typename T> | ||||||
|  |   const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, String>::value, | ||||||
|  |                                       T>::type | ||||||
|  |   as() const { | ||||||
|  |     return toString(); | ||||||
|  |   } | ||||||
|  |   // const char* as<const char*>() const; | ||||||
|  |   // const char* as<char*>() const; | ||||||
|  |   template <typename T> | ||||||
|  |   typename TypeTraits::EnableIf<TypeTraits::IsSame<T, const char *>::value, | ||||||
|  |                                 const char *>::type | ||||||
|  |   as() const { | ||||||
|  |     return asString(); | ||||||
|  |   } | ||||||
|  |   // const bool as<bool>() const | ||||||
|  |   template <typename T> | ||||||
|  |   const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value, | ||||||
|  |                                       T>::type | ||||||
|  |   as() const { | ||||||
|  |     return asInteger() != 0; | ||||||
|  |   } | ||||||
|  |   // JsonArray& as<JsonArray> const; | ||||||
|  |   // JsonArray& as<JsonArray&> const; | ||||||
|  |   // JsonArray& as<const JsonArray&> const; | ||||||
|  |   template <typename T> | ||||||
|  |   typename TypeTraits::EnableIf< | ||||||
|  |       TypeTraits::IsSame< | ||||||
|  |           typename TypeTraits::RemoveConst< | ||||||
|  |               typename TypeTraits::RemoveReference<T>::type>::type, | ||||||
|  |           JsonArray>::value, | ||||||
|  |       JsonArray &>::type | ||||||
|  |   as() const { | ||||||
|  |     return asArray(); | ||||||
|  |   } | ||||||
|  |   // JsonObject& as<JsonObject> const; | ||||||
|  |   // JsonObject& as<JsonObject&> const; | ||||||
|  |   // JsonObject& as<const JsonObject&> const; | ||||||
|  |   template <typename T> | ||||||
|  |   typename TypeTraits::EnableIf< | ||||||
|  |       TypeTraits::IsSame< | ||||||
|  |           typename TypeTraits::RemoveConst< | ||||||
|  |               typename TypeTraits::RemoveReference<T>::type>::type, | ||||||
|  |           JsonObject>::value, | ||||||
|  |       JsonObject &>::type | ||||||
|  |   as() const { | ||||||
|  |     return asObject(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Tells weither the variant has the specified type. |   // Tells weither the variant has the specified type. | ||||||
|   // Returns true if the variant has type type T, false otherwise. |   // Returns true if the variant has type type T, false otherwise. | ||||||
| @@ -83,7 +166,12 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   template <typename T> |   template <typename T> | ||||||
|   static T invalid(); |   static T invalid(); | ||||||
|  |  | ||||||
|  |   const char *asString() const; | ||||||
|  |   JsonArray &asArray() const; | ||||||
|  |   JsonObject &asObject() const; | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|  |   String toString() const; | ||||||
|   Internals::JsonFloat asFloat() const; |   Internals::JsonFloat asFloat() const; | ||||||
|   Internals::JsonInteger asInteger() const; |   Internals::JsonInteger asInteger() const; | ||||||
|  |  | ||||||
| @@ -101,6 +189,28 @@ inline JsonVariant float_with_n_digits(float value, uint8_t digits) { | |||||||
| inline JsonVariant double_with_n_digits(double value, uint8_t digits) { | inline JsonVariant double_with_n_digits(double value, uint8_t digits) { | ||||||
|   return JsonVariant(value, digits); |   return JsonVariant(value, digits); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct JsonVariant::IsConstructibleFrom { | ||||||
|  |   static const bool value = | ||||||
|  |       TypeTraits::IsIntegral<T>::value || | ||||||
|  |       TypeTraits::IsFloatingPoint<T>::value || | ||||||
|  |       TypeTraits::IsSame<T, bool>::value || | ||||||
|  |       TypeTraits::IsSame<T, char *>::value || | ||||||
|  |       TypeTraits::IsSame<T, const char *>::value || | ||||||
|  |       TypeTraits::IsSame<T, JsonArray &>::value || | ||||||
|  |       TypeTraits::IsSame<T, const JsonArray &>::value || | ||||||
|  |       TypeTraits::IsSame<T, JsonArraySubscript &>::value || | ||||||
|  |       TypeTraits::IsSame<T, const JsonArraySubscript &>::value || | ||||||
|  |       TypeTraits::IsSame<T, JsonObject &>::value || | ||||||
|  |       TypeTraits::IsSame<T, const JsonObject &>::value || | ||||||
|  |       TypeTraits::IsSame<T, JsonObjectSubscript<const char *> &>::value || | ||||||
|  |       TypeTraits::IsSame<T, const JsonObjectSubscript<const char *> &>::value || | ||||||
|  |       TypeTraits::IsSame<T, JsonObjectSubscript<String> &>::value || | ||||||
|  |       TypeTraits::IsSame<T, const JsonObjectSubscript<String> &>::value || | ||||||
|  |       TypeTraits::IsSame<T, JsonVariant &>::value || | ||||||
|  |       TypeTraits::IsSame<T, const JsonVariant &>::value; | ||||||
|  | }; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Include inline implementations | // Include inline implementations | ||||||
|   | |||||||
| @@ -7,7 +7,11 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include "Configuration.hpp" | ||||||
| #include "JsonVariant.hpp" | #include "JsonVariant.hpp" | ||||||
|  | #include "Internals/Parse.hpp" | ||||||
|  |  | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| @@ -27,18 +31,6 @@ inline JsonVariant::JsonVariant(Internals::Unparsed value) { | |||||||
|   _content.asString = value; |   _content.asString = value; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(double value, uint8_t decimals) { |  | ||||||
|   using namespace Internals; |  | ||||||
|   _type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals); |  | ||||||
|   _content.asFloat = static_cast<JsonFloat>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(float value, uint8_t decimals) { |  | ||||||
|   using namespace Internals; |  | ||||||
|   _type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals); |  | ||||||
|   _content.asFloat = static_cast<JsonFloat>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(JsonArray &array) { | inline JsonVariant::JsonVariant(JsonArray &array) { | ||||||
|   _type = Internals::JSON_ARRAY; |   _type = Internals::JSON_ARRAY; | ||||||
|   _content.asArray = &array; |   _content.asArray = &array; | ||||||
| @@ -49,115 +41,6 @@ inline JsonVariant::JsonVariant(JsonObject &object) { | |||||||
|   _content.asObject = &object; |   _content.asObject = &object; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(signed char value) { |  | ||||||
|   using namespace Internals; |  | ||||||
|   _type = JSON_INTEGER; |  | ||||||
|   _content.asInteger = static_cast<JsonInteger>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(signed int value) { |  | ||||||
|   using namespace Internals; |  | ||||||
|   _type = JSON_INTEGER; |  | ||||||
|   _content.asInteger = static_cast<JsonInteger>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(signed long value) { |  | ||||||
|   using namespace Internals; |  | ||||||
|   _type = JSON_INTEGER; |  | ||||||
|   _content.asInteger = static_cast<JsonInteger>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(signed short value) { |  | ||||||
|   using namespace Internals; |  | ||||||
|   _type = JSON_INTEGER; |  | ||||||
|   _content.asInteger = static_cast<JsonInteger>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(unsigned char value) { |  | ||||||
|   using namespace Internals; |  | ||||||
|   _type = JSON_INTEGER; |  | ||||||
|   _content.asInteger = static_cast<JsonInteger>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(unsigned int value) { |  | ||||||
|   using namespace Internals; |  | ||||||
|   _type = JSON_INTEGER; |  | ||||||
|   _content.asInteger = static_cast<JsonInteger>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(unsigned long value) { |  | ||||||
|   using namespace Internals; |  | ||||||
|   _type = JSON_INTEGER; |  | ||||||
|   _content.asInteger = static_cast<JsonInteger>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(unsigned short value) { |  | ||||||
|   using namespace Internals; |  | ||||||
|   _type = JSON_INTEGER; |  | ||||||
|   _content.asInteger = static_cast<JsonInteger>(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| String JsonVariant::as<String>() const; |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| const char *JsonVariant::as<const char *>() const; |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline bool JsonVariant::as<bool>() const { |  | ||||||
|   return asInteger() != 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline signed char JsonVariant::as<signed char>() const { |  | ||||||
|   return static_cast<signed char>(asInteger()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline unsigned char JsonVariant::as<unsigned char>() const { |  | ||||||
|   return static_cast<unsigned char>(asInteger()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline signed short JsonVariant::as<signed short>() const { |  | ||||||
|   return static_cast<signed short>(asInteger()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline unsigned short JsonVariant::as<unsigned short>() const { |  | ||||||
|   return static_cast<unsigned short>(asInteger()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline signed int JsonVariant::as<signed int>() const { |  | ||||||
|   return static_cast<signed int>(asInteger()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline unsigned int JsonVariant::as<unsigned int>() const { |  | ||||||
|   return static_cast<unsigned int>(asInteger()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline unsigned long JsonVariant::as<unsigned long>() const { |  | ||||||
|   return static_cast<unsigned long>(asInteger()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline signed long JsonVariant::as<signed long>() const { |  | ||||||
|   return static_cast<unsigned long>(asInteger()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline double JsonVariant::as<double>() const { |  | ||||||
|   return static_cast<double>(asFloat()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline float JsonVariant::as<float>() const { |  | ||||||
|   return static_cast<float>(asFloat()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| inline T JsonVariant::invalid() { | inline T JsonVariant::invalid() { | ||||||
|   return T(); |   return T(); | ||||||
| @@ -242,7 +125,23 @@ inline bool JsonVariant::is<unsigned short>() const { | |||||||
|   return is<signed long>(); |   return is<signed long>(); | ||||||
| } | } | ||||||
|  |  | ||||||
| #ifdef ARDUINOJSON_ENABLE_STD_STREAM | inline Internals::JsonInteger JsonVariant::asInteger() const { | ||||||
|  |   if (_type == Internals::JSON_INTEGER || _type == Internals::JSON_BOOLEAN) | ||||||
|  |     return _content.asInteger; | ||||||
|  |  | ||||||
|  |   if (_type >= Internals::JSON_FLOAT_0_DECIMALS) | ||||||
|  |     return static_cast<Internals::JsonInteger>(_content.asFloat); | ||||||
|  |  | ||||||
|  |   if ((_type == Internals::JSON_STRING || _type == Internals::JSON_UNPARSED) && | ||||||
|  |       _content.asString) { | ||||||
|  |     if (!strcmp("true", _content.asString)) return 1; | ||||||
|  |     return Internals::parse<Internals::JsonInteger>(_content.asString); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return 0L; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #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); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,31 +20,7 @@ class JsonObjectSubscript; | |||||||
| template <typename TImpl> | template <typename TImpl> | ||||||
| class JsonVariantBase : public Internals::JsonPrintable<TImpl> { | class JsonVariantBase : public Internals::JsonPrintable<TImpl> { | ||||||
|  public: |  public: | ||||||
|   // Gets the variant as a boolean value. |  | ||||||
|   // Returns false if the variant is not a boolean value. |  | ||||||
|   FORCE_INLINE operator bool() const { return as<bool>(); } |  | ||||||
|  |  | ||||||
|   // Gets the variant as a floating-point value. |  | ||||||
|   // Returns 0.0 if the variant is not a floating-point value |  | ||||||
|   FORCE_INLINE operator double() const { return as<double>(); } |  | ||||||
|   FORCE_INLINE operator float() const { return as<float>(); } |  | ||||||
|  |  | ||||||
|   // Gets the variant as an integer value. |  | ||||||
|   // Returns 0 if the variant is not an integer value. |  | ||||||
|   FORCE_INLINE operator signed long() const { return as<signed long>(); } |  | ||||||
|   FORCE_INLINE operator signed char() const { return as<signed char>(); } |  | ||||||
|   FORCE_INLINE operator signed int() const { return as<signed int>(); } |  | ||||||
|   FORCE_INLINE operator signed short() const { return as<signed short>(); } |  | ||||||
|   FORCE_INLINE operator unsigned char() const { return as<unsigned char>(); } |  | ||||||
|   FORCE_INLINE operator unsigned int() const { return as<unsigned int>(); } |  | ||||||
|   FORCE_INLINE operator unsigned long() const { return as<unsigned long>(); } |  | ||||||
|   FORCE_INLINE operator unsigned short() const { return as<unsigned short>(); } |  | ||||||
|  |  | ||||||
|   // Gets the variant as a string. |  | ||||||
|   // Returns NULL if variant is not a string. |  | ||||||
|   FORCE_INLINE operator const char *() const { return as<const char *>(); } |  | ||||||
|   FORCE_INLINE const char *asString() const { return as<const char *>(); } |   FORCE_INLINE const char *asString() const { return as<const char *>(); } | ||||||
|   FORCE_INLINE operator String() const { return as<String>(); } |  | ||||||
|  |  | ||||||
|   // Gets the variant as an array. |   // Gets the variant as an array. | ||||||
|   // Returns a reference to the JsonArray or JsonArray::invalid() if the |   // Returns a reference to the JsonArray or JsonArray::invalid() if the | ||||||
| @@ -59,6 +35,11 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> { | |||||||
|   FORCE_INLINE operator JsonObject &() const { return as<JsonObject &>(); } |   FORCE_INLINE operator JsonObject &() const { return as<JsonObject &>(); } | ||||||
|   FORCE_INLINE JsonObject &asObject() const { return as<JsonObject &>(); } |   FORCE_INLINE JsonObject &asObject() const { return as<JsonObject &>(); } | ||||||
|  |  | ||||||
|  |   template <typename T> | ||||||
|  |   FORCE_INLINE operator T() const { | ||||||
|  |     return as<T>(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE const T as() const { |   FORCE_INLINE const T as() const { | ||||||
|     return impl()->template as<T>(); |     return impl()->template as<T>(); | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								include/ArduinoJson/TypeTraits/EnableIf.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								include/ArduinoJson/TypeTraits/EnableIf.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace TypeTraits { | ||||||
|  |  | ||||||
|  | // A meta-function that return the type T if Condition is true. | ||||||
|  | template <bool Condition, typename T = void> | ||||||
|  | struct EnableIf {}; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct EnableIf<true, T> { | ||||||
|  |   typedef T type; | ||||||
|  | }; | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								include/ArduinoJson/TypeTraits/IsFloatingPoint.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								include/ArduinoJson/TypeTraits/IsFloatingPoint.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "IsSame.hpp" | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace TypeTraits { | ||||||
|  |  | ||||||
|  | // A meta-function that returns true if T is a floating point type | ||||||
|  | template <typename T> | ||||||
|  | struct IsFloatingPoint { | ||||||
|  |   static const bool value = IsSame<T, float>::value || IsSame<T, double>::value; | ||||||
|  | }; | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										41
									
								
								include/ArduinoJson/TypeTraits/IsIntegral.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								include/ArduinoJson/TypeTraits/IsIntegral.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "../Configuration.hpp" | ||||||
|  | #include "IsSame.hpp" | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace TypeTraits { | ||||||
|  |  | ||||||
|  | // A meta-function that returns true if T is an integral type. | ||||||
|  | template <typename T> | ||||||
|  | struct IsIntegral { | ||||||
|  |   static const bool value = TypeTraits::IsSame<T, signed char>::value || | ||||||
|  |                             TypeTraits::IsSame<T, unsigned char>::value || | ||||||
|  |                             TypeTraits::IsSame<T, signed short>::value || | ||||||
|  |                             TypeTraits::IsSame<T, unsigned short>::value || | ||||||
|  |                             TypeTraits::IsSame<T, signed int>::value || | ||||||
|  |                             TypeTraits::IsSame<T, unsigned int>::value || | ||||||
|  |                             TypeTraits::IsSame<T, signed long>::value || | ||||||
|  |                             TypeTraits::IsSame<T, unsigned long>::value || | ||||||
|  | #if ARDUINOJSON_USE_LONG_LONG | ||||||
|  |                             TypeTraits::IsSame<T, long long>::value || | ||||||
|  |                             TypeTraits::IsSame<T, unsigned long long>::value || | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_USE_INT64 | ||||||
|  |                             TypeTraits::IsSame<T, __int64>::value || | ||||||
|  |                             TypeTraits::IsSame<T, unsigned __int64>::value || | ||||||
|  | #endif | ||||||
|  |                             TypeTraits::IsSame<T, char>::value; | ||||||
|  | }; | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								include/ArduinoJson/TypeTraits/IsReference.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								include/ArduinoJson/TypeTraits/IsReference.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace TypeTraits { | ||||||
|  |  | ||||||
|  | // A meta-function that returns true if T is a reference | ||||||
|  | template <typename T> | ||||||
|  | struct IsReference { | ||||||
|  |   static const bool value = false; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct IsReference<T&> { | ||||||
|  |   static const bool value = true; | ||||||
|  | }; | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								include/ArduinoJson/TypeTraits/IsSame.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								include/ArduinoJson/TypeTraits/IsSame.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace TypeTraits { | ||||||
|  |  | ||||||
|  | // A meta-function that returns true if types T and U are the same. | ||||||
|  | template <typename T, typename U> | ||||||
|  | struct IsSame { | ||||||
|  |   static const bool value = false; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct IsSame<T, T> { | ||||||
|  |   static const bool value = true; | ||||||
|  | }; | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								include/ArduinoJson/TypeTraits/RemoveConst.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								include/ArduinoJson/TypeTraits/RemoveConst.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace TypeTraits { | ||||||
|  |  | ||||||
|  | // A meta-function that return the type T without the const modifier | ||||||
|  | template <typename T> | ||||||
|  | struct RemoveConst { | ||||||
|  |   typedef T type; | ||||||
|  | }; | ||||||
|  | template <typename T> | ||||||
|  | struct RemoveConst<const T> { | ||||||
|  |   typedef T type; | ||||||
|  | }; | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								include/ArduinoJson/TypeTraits/RemoveReference.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								include/ArduinoJson/TypeTraits/RemoveReference.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace TypeTraits { | ||||||
|  |  | ||||||
|  | // A meta-function that return the type T without the reference modifier. | ||||||
|  | template <typename T> | ||||||
|  | struct RemoveReference { | ||||||
|  |   typedef T type; | ||||||
|  | }; | ||||||
|  | template <typename T> | ||||||
|  | struct RemoveReference<T&> { | ||||||
|  |   typedef T type; | ||||||
|  | }; | ||||||
|  | } | ||||||
|  | } | ||||||
| @@ -1,72 +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! |  | ||||||
|  |  | ||||||
| #ifndef ARDUINO |  | ||||||
|  |  | ||||||
| #include "../../include/ArduinoJson/Arduino/Print.hpp" |  | ||||||
|  |  | ||||||
| #include <math.h>   // for isnan() and isinf() |  | ||||||
| #include <stdio.h>  // for sprintf() |  | ||||||
|  |  | ||||||
| // only for GCC 4.9+ |  | ||||||
| #if defined(__GNUC__) && \ |  | ||||||
|     (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) |  | ||||||
| #pragma GCC diagnostic ignored "-Wfloat-conversion" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| // Visual Studo 2012 didn't have isnan, nor isinf |  | ||||||
| #if defined(_MSC_VER) && _MSC_VER <= 1700 |  | ||||||
| #include <float.h> |  | ||||||
| #define isnan(x) _isnan(x) |  | ||||||
| #define isinf(x) (!_finite(x)) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| size_t Print::print(const char s[]) { |  | ||||||
|   size_t n = 0; |  | ||||||
|   while (*s) { |  | ||||||
|     n += write(*s++); |  | ||||||
|   } |  | ||||||
|   return n; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| size_t Print::print(double value, int digits) { |  | ||||||
|   // https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L218 |  | ||||||
|   if (isnan(value)) return print("nan"); |  | ||||||
|   if (isinf(value)) return print("inf"); |  | ||||||
|  |  | ||||||
|   char tmp[32]; |  | ||||||
|  |  | ||||||
|   // https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L220 |  | ||||||
|   bool isBigDouble = value > 4294967040.0 || value < -4294967040.0; |  | ||||||
|  |  | ||||||
|   if (isBigDouble) { |  | ||||||
|     // Arduino's implementation prints "ovf" |  | ||||||
|     // We prefer trying to use scientific notation, since we have sprintf |  | ||||||
|     sprintf(tmp, "%g", value); |  | ||||||
|   } else { |  | ||||||
|     // Here we have the exact same output as Arduino's implementation |  | ||||||
|     sprintf(tmp, "%.*f", digits, value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return print(tmp); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| size_t Print::print(long value) { |  | ||||||
|   char tmp[32]; |  | ||||||
|   sprintf(tmp, "%ld", value); |  | ||||||
|   return print(tmp); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| size_t Print::print(int value) { |  | ||||||
|   char tmp[32]; |  | ||||||
|   sprintf(tmp, "%d", value); |  | ||||||
|   return print(tmp); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| size_t Print::println() { return write('\r') + write('\n'); } |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
| @@ -21,20 +21,6 @@ JsonArray::node_type *JsonArray::getNodeAt(size_t index) const { | |||||||
|   return node; |   return node; | ||||||
| } | } | ||||||
|  |  | ||||||
| JsonArray &JsonArray::createNestedArray() { |  | ||||||
|   if (!_buffer) return JsonArray::invalid(); |  | ||||||
|   JsonArray &array = _buffer->createArray(); |  | ||||||
|   add(array); |  | ||||||
|   return array; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| JsonObject &JsonArray::createNestedObject() { |  | ||||||
|   if (!_buffer) return JsonObject::invalid(); |  | ||||||
|   JsonObject &object = _buffer->createObject(); |  | ||||||
|   add(object); |  | ||||||
|   return object; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void JsonArray::removeAt(size_t index) { removeNode(getNodeAt(index)); } | void JsonArray::removeAt(size_t index) { removeNode(getNodeAt(index)); } | ||||||
|  |  | ||||||
| void JsonArray::writeTo(JsonWriter &writer) const { | void JsonArray::writeTo(JsonWriter &writer) const { | ||||||
|   | |||||||
| @@ -18,35 +18,7 @@ using namespace ArduinoJson::Internals; | |||||||
|  |  | ||||||
| JsonObject JsonObject::_invalid(NULL); | JsonObject JsonObject::_invalid(NULL); | ||||||
|  |  | ||||||
| JsonObject::node_type *JsonObject::getOrCreateNodeAt(JsonObjectKey key) { | JsonObject::node_type *JsonObject::getNodeAt(const char *key) const { | ||||||
|   node_type *existingNode = getNodeAt(key); |  | ||||||
|   if (existingNode) return existingNode; |  | ||||||
|  |  | ||||||
|   node_type *newNode = addNewNode(); |  | ||||||
|   return newNode; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename TKey> |  | ||||||
| JsonArray &JsonObject::createArrayAt(TKey key) { |  | ||||||
|   if (!_buffer) return JsonArray::invalid(); |  | ||||||
|   JsonArray &array = _buffer->createArray(); |  | ||||||
|   setNodeAt<TKey, const JsonVariant &>(key, array); |  | ||||||
|   return array; |  | ||||||
| } |  | ||||||
| template JsonArray &JsonObject::createArrayAt<const char *>(const char *); |  | ||||||
| template JsonArray &JsonObject::createArrayAt<const String &>(const String &); |  | ||||||
|  |  | ||||||
| template <typename TKey> |  | ||||||
| JsonObject &JsonObject::createObjectAt(TKey key) { |  | ||||||
|   if (!_buffer) return JsonObject::invalid(); |  | ||||||
|   JsonObject &array = _buffer->createObject(); |  | ||||||
|   setNodeAt<TKey, const JsonVariant &>(key, array); |  | ||||||
|   return array; |  | ||||||
| } |  | ||||||
| template JsonObject &JsonObject::createObjectAt<const char *>(const char *); |  | ||||||
| template JsonObject &JsonObject::createObjectAt<const String &>(const String &); |  | ||||||
|  |  | ||||||
| JsonObject::node_type *JsonObject::getNodeAt(JsonObjectKey key) const { |  | ||||||
|   for (node_type *node = _firstNode; node; node = node->next) { |   for (node_type *node = _firstNode; node; node = node->next) { | ||||||
|     if (!strcmp(node->content.key, key)) return node; |     if (!strcmp(node->content.key, key)) return node; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -17,31 +17,7 @@ using namespace ArduinoJson::Internals; | |||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| template <typename TFloat> | const char *JsonVariant::asString() const { | ||||||
| static TFloat parse(const char *); |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| float parse<float>(const char *s) { |  | ||||||
|   return static_cast<float>(strtod(s, NULL)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| double parse<double>(const char *s) { |  | ||||||
|   return strtod(s, NULL); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| long parse<long>(const char *s) { |  | ||||||
|   return strtol(s, NULL, 10); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| int parse<int>(const char *s) { |  | ||||||
|   return atoi(s); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| const char *JsonVariant::as<const char *>() const { |  | ||||||
|   if (_type == JSON_UNPARSED && _content.asString && |   if (_type == JSON_UNPARSED && _content.asString && | ||||||
|       !strcmp("null", _content.asString)) |       !strcmp("null", _content.asString)) | ||||||
|     return NULL; |     return NULL; | ||||||
| @@ -61,22 +37,7 @@ JsonFloat JsonVariant::asFloat() const { | |||||||
|   return 0.0; |   return 0.0; | ||||||
| } | } | ||||||
|  |  | ||||||
| JsonInteger JsonVariant::asInteger() const { | String JsonVariant::toString() const { | ||||||
|   if (_type == JSON_INTEGER || _type == JSON_BOOLEAN) return _content.asInteger; |  | ||||||
|  |  | ||||||
|   if (_type >= JSON_FLOAT_0_DECIMALS) |  | ||||||
|     return static_cast<JsonInteger>(_content.asFloat); |  | ||||||
|  |  | ||||||
|   if ((_type == JSON_STRING || _type == JSON_UNPARSED) && _content.asString) { |  | ||||||
|     if (!strcmp("true", _content.asString)) return 1; |  | ||||||
|     return parse<JsonInteger>(_content.asString); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return 0L; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| String JsonVariant::as<String>() const { |  | ||||||
|   String s; |   String s; | ||||||
|   if ((_type == JSON_STRING || _type == JSON_UNPARSED) && |   if ((_type == JSON_STRING || _type == JSON_UNPARSED) && | ||||||
|       _content.asString != NULL) |       _content.asString != NULL) | ||||||
|   | |||||||
| @@ -17,7 +17,11 @@ add_definitions(-DGTEST_HAS_PTHREAD=0) | |||||||
|  |  | ||||||
| # Workaround for Visual Studio 2012 | # Workaround for Visual Studio 2012 | ||||||
| if (MSVC AND MSVC_VERSION EQUAL 1700) | if (MSVC AND MSVC_VERSION EQUAL 1700) | ||||||
|   add_definitions(-D_VARIADIC_MAX=10) |     add_definitions(-D_VARIADIC_MAX=10) | ||||||
|  | endif() | ||||||
|  |  | ||||||
|  | if (MSVC) | ||||||
|  | 	add_definitions(-D_CRT_SECURE_NO_WARNINGS) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
| add_executable(ArduinoJsonTests  | add_executable(ArduinoJsonTests  | ||||||
| @@ -25,6 +29,7 @@ add_executable(ArduinoJsonTests | |||||||
|     ${GTEST_DIR}/src/gtest-all.cc |     ${GTEST_DIR}/src/gtest-all.cc | ||||||
|     ${GTEST_DIR}/src/gtest_main.cc) |     ${GTEST_DIR}/src/gtest_main.cc) | ||||||
|  |  | ||||||
|  |  | ||||||
| target_link_libraries(ArduinoJsonTests ArduinoJson) | target_link_libraries(ArduinoJsonTests ArduinoJson) | ||||||
|  |  | ||||||
| add_test(ArduinoJsonTests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ArduinoJsonTests) | add_test(ArduinoJsonTests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ArduinoJsonTests) | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ | |||||||
| // 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> | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| class GbathreeBug : public testing::Test { | class GbathreeBug : public testing::Test { | ||||||
|   | |||||||
| @@ -7,7 +7,9 @@ | |||||||
|  |  | ||||||
| #include <gtest/gtest.h> | #include <gtest/gtest.h> | ||||||
| #include <limits.h>  // for LONG_MAX | #include <limits.h>  // for LONG_MAX | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
|  | #define ARDUINOJSON_USE_LONG_LONG 0 | ||||||
|  | #define ARDUINOJSON_USE_INT64 0 | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| #define SUITE Issue90 | #define SUITE Issue90 | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ | |||||||
| // 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> | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| class JsonArray_Add_Tests : public ::testing::Test { | class JsonArray_Add_Tests : public ::testing::Test { | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ | |||||||
| // 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> | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| #define TEST_(name) TEST(JsonArray_Basic_Tests, name) | #define TEST_(name) TEST(JsonArray_Basic_Tests, name) | ||||||
|   | |||||||
| @@ -64,10 +64,25 @@ TEST_F(JsonArray_PrintTo_Tests, OneDoubleDefaultDigits) { | |||||||
| } | } | ||||||
|  |  | ||||||
| TEST_F(JsonArray_PrintTo_Tests, OneDoubleFourDigits) { | TEST_F(JsonArray_PrintTo_Tests, OneDoubleFourDigits) { | ||||||
|  |   array.add(3.14159265358979323846, 4); | ||||||
|  |   outputMustBe("[3.1416]"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonArray_PrintTo_Tests, OneDoubleFourDigits_AlternativeSyntax) { | ||||||
|   array.add(double_with_n_digits(3.14159265358979323846, 4)); |   array.add(double_with_n_digits(3.14159265358979323846, 4)); | ||||||
|   outputMustBe("[3.1416]"); |   outputMustBe("[3.1416]"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonArray_PrintTo_Tests, OneFloatDefaultDigits) { | ||||||
|  |   array.add(3.14159f); | ||||||
|  |   outputMustBe("[3.14]"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonArray_PrintTo_Tests, OneFloatFourDigits) { | ||||||
|  |   array.add(3.14159f, 4); | ||||||
|  |   outputMustBe("[3.1416]"); | ||||||
|  | } | ||||||
|  |  | ||||||
| TEST_F(JsonArray_PrintTo_Tests, OneInteger) { | TEST_F(JsonArray_PrintTo_Tests, OneInteger) { | ||||||
|   array.add(1); |   array.add(1); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ | |||||||
| // 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> | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| class JsonArray_Set_Tests : public ::testing::Test { | class JsonArray_Set_Tests : public ::testing::Test { | ||||||
|   | |||||||
| @@ -5,9 +5,9 @@ | |||||||
| // 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 <gtest/gtest.h> |  | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  | #include <gtest/gtest.h> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
| class JsonArray_Subscript_Tests : public ::testing::Test { | class JsonArray_Subscript_Tests : public ::testing::Test { | ||||||
|  protected: |  protected: | ||||||
| @@ -33,6 +33,15 @@ TEST_(StoreInteger) { | |||||||
|   EXPECT_FALSE(_array[0].is<double>()); |   EXPECT_FALSE(_array[0].is<double>()); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 | ||||||
|  | TEST_(StoreLongLong) { | ||||||
|  |   _array[0] = 9223372036854775807; | ||||||
|  |   EXPECT_EQ(9223372036854775807, _array[0].as<long long>()); | ||||||
|  |   EXPECT_TRUE(_array[0].is<int>()); | ||||||
|  |   EXPECT_FALSE(_array[0].is<double>()); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| TEST_(StoreDouble) { | TEST_(StoreDouble) { | ||||||
|   _array[0] = 123.45; |   _array[0] = 123.45; | ||||||
|   EXPECT_EQ(123.45, _array[0].as<double>()); |   EXPECT_EQ(123.45, _array[0].as<double>()); | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ | |||||||
| // 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> | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| class JsonObject_Iterator_Test : public testing::Test { | class JsonObject_Iterator_Test : public testing::Test { | ||||||
|   | |||||||
| @@ -5,8 +5,8 @@ | |||||||
| // 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 <gtest/gtest.h> |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  | #include <gtest/gtest.h> | ||||||
|  |  | ||||||
| using namespace ArduinoJson::Internals; | using namespace ArduinoJson::Internals; | ||||||
|  |  | ||||||
| @@ -78,7 +78,8 @@ TEST_F(JsonObject_PrintTo_Tests, TwoIntegers) { | |||||||
| TEST_F(JsonObject_PrintTo_Tests, TwoDoublesFourDigits) { | TEST_F(JsonObject_PrintTo_Tests, TwoDoublesFourDigits) { | ||||||
|   _object["a"] = double_with_n_digits(3.14159265358979323846, 4); |   _object["a"] = double_with_n_digits(3.14159265358979323846, 4); | ||||||
|   _object.set("b", 2.71828182845904523536, 4); |   _object.set("b", 2.71828182845904523536, 4); | ||||||
|   outputMustBe("{\"a\":3.1416,\"b\":2.7183}"); |   _object.set("c", double_with_n_digits(3.14159265358979323846, 3)); | ||||||
|  |   outputMustBe("{\"a\":3.1416,\"b\":2.7183,\"c\":3.142}"); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_F(JsonObject_PrintTo_Tests, TwoDoubleDefaultDigits) { | TEST_F(JsonObject_PrintTo_Tests, TwoDoubleDefaultDigits) { | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ | |||||||
| // 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> | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| class JsonObject_Set_Tests : public ::testing::Test { | class JsonObject_Set_Tests : public ::testing::Test { | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ | |||||||
| // 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> | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| class JsonObject_Subscript_Tests : public ::testing::Test { | class JsonObject_Subscript_Tests : public ::testing::Test { | ||||||
|   | |||||||
| @@ -5,10 +5,11 @@ | |||||||
| // 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 <gtest/gtest.h> |  | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
|  | #include <gtest/gtest.h> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
| static const char* null = 0; | static const char* null = 0; | ||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, DoubleAsBool) { | TEST(JsonVariant_As_Tests, DoubleAsBool) { | ||||||
| @@ -136,6 +137,18 @@ TEST(JsonVariant_As_Tests, NumberStringAsLong) { | |||||||
|   ASSERT_EQ(42L, variant.as<long>()); |   ASSERT_EQ(42L, variant.as<long>()); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 | ||||||
|  | TEST(JsonVariant_As_Tests, NumberStringAsInt64Negative) { | ||||||
|  |   JsonVariant variant = "-9223372036854775808"; | ||||||
|  |   ASSERT_EQ(-9223372036854775807 - 1, variant.as<long long>()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST(JsonVariant_As_Tests, NumberStringAsInt64Positive) { | ||||||
|  |   JsonVariant variant = "9223372036854775807"; | ||||||
|  |   ASSERT_EQ(9223372036854775807, variant.as<long long>()); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, RandomStringAsBool) { | TEST(JsonVariant_As_Tests, RandomStringAsBool) { | ||||||
|   JsonVariant variant = "hello"; |   JsonVariant variant = "hello"; | ||||||
|   ASSERT_FALSE(variant.as<bool>()); |   ASSERT_FALSE(variant.as<bool>()); | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ | |||||||
| // 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> | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson/JsonVariant.hpp> | #include <ArduinoJson/JsonVariant.hpp> | ||||||
|  |  | ||||||
| using namespace ArduinoJson; | using namespace ArduinoJson; | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ | |||||||
| // 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> | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| #define SUITE JsonVariant_Is_Tests | #define SUITE JsonVariant_Is_Tests | ||||||
|   | |||||||
| @@ -71,3 +71,15 @@ TEST_F(JsonVariant_PrintTo_Tests, OneFalse) { | |||||||
|   variant = false; |   variant = false; | ||||||
|   outputMustBe("false"); |   outputMustBe("false"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 | ||||||
|  | TEST_F(JsonVariant_PrintTo_Tests, NegativeInt64) { | ||||||
|  |   variant = -9223372036854775807 - 1; | ||||||
|  |   outputMustBe("-9223372036854775808"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(JsonVariant_PrintTo_Tests, PositiveInt64) { | ||||||
|  |   variant = 9223372036854775807; | ||||||
|  |   outputMustBe("9223372036854775807"); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|   | |||||||
| @@ -6,40 +6,74 @@ | |||||||
| // 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 <stdint.h> | ||||||
|  | #include <limits> | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| class JsonVariant_Storage_Tests : public ::testing::Test { | class JsonVariant_Storage_Tests : public ::testing::Test { | ||||||
|  protected: |  protected: | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   void testValue(T expected) { |   void testValue(T expected) { | ||||||
|     _actual = expected; |     JsonVariant variant = expected; | ||||||
|     EXPECT_EQ(expected, _actual.as<T>()); |     EXPECT_EQ(expected, variant.as<T>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   void testReference(T &expected) { |   void testReference(T &expected) { | ||||||
|     _actual = expected; |     JsonVariant variant = expected; | ||||||
|     EXPECT_EQ(expected, _actual.as<T &>()); |     EXPECT_EQ(expected, variant.as<T &>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |   template <typename T> | ||||||
|   JsonVariant _actual; |   void testNumericType() { | ||||||
|  |     T min = std::numeric_limits<T>::min(); | ||||||
|  |     T max = std::numeric_limits<T>::max(); | ||||||
|  |  | ||||||
|  |     JsonVariant variantMin(min); | ||||||
|  |     JsonVariant variantMax(max); | ||||||
|  |  | ||||||
|  |     EXPECT_EQ(min, variantMin.as<T>()); | ||||||
|  |     EXPECT_EQ(max, variantMax.as<T>()); | ||||||
|  |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| TEST_F(JsonVariant_Storage_Tests, Double) { testValue<double>(123.45); } | #if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 | ||||||
| TEST_F(JsonVariant_Storage_Tests, False) { testValue<bool>(false); } | TEST_F(JsonVariant_Storage_Tests, SizeOfJsonInteger) { | ||||||
| TEST_F(JsonVariant_Storage_Tests, Float) { testValue<float>(123.45f); } |   ASSERT_EQ(8, sizeof(Internals::JsonInteger)); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| TEST_F(JsonVariant_Storage_Tests, Null) { testValue<const char *>(NULL); } | TEST_F(JsonVariant_Storage_Tests, Null) { testValue<const char *>(NULL); } | ||||||
| TEST_F(JsonVariant_Storage_Tests, SChar) { testValue<signed char>(123); } |  | ||||||
| TEST_F(JsonVariant_Storage_Tests, SInt) { testValue<signed int>(123); } |  | ||||||
| TEST_F(JsonVariant_Storage_Tests, SLong) { testValue<signed long>(123L); } |  | ||||||
| TEST_F(JsonVariant_Storage_Tests, SShort) { testValue<signed short>(123); } |  | ||||||
| TEST_F(JsonVariant_Storage_Tests, String) { testValue<const char *>("hello"); } | TEST_F(JsonVariant_Storage_Tests, String) { testValue<const char *>("hello"); } | ||||||
|  |  | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, False) { testValue<bool>(false); } | ||||||
| TEST_F(JsonVariant_Storage_Tests, True) { testValue<bool>(true); } | TEST_F(JsonVariant_Storage_Tests, True) { testValue<bool>(true); } | ||||||
| TEST_F(JsonVariant_Storage_Tests, UChar) { testValue<unsigned char>(123); } |  | ||||||
| TEST_F(JsonVariant_Storage_Tests, UInt) { testValue<unsigned int>(123U); } | TEST_F(JsonVariant_Storage_Tests, Double) { testNumericType<double>(); } | ||||||
| TEST_F(JsonVariant_Storage_Tests, ULong) { testValue<unsigned long>(123UL); } | TEST_F(JsonVariant_Storage_Tests, Float) { testNumericType<float>(); } | ||||||
| TEST_F(JsonVariant_Storage_Tests, UShort) { testValue<unsigned short>(123); } | TEST_F(JsonVariant_Storage_Tests, SChar) { testNumericType<signed char>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, SInt) { testNumericType<signed int>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, SLong) { testNumericType<signed long>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, SShort) { testNumericType<signed short>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, UChar) { testNumericType<unsigned char>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, UInt) { testNumericType<unsigned int>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, ULong) { testNumericType<unsigned long>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, UShort) { testNumericType<unsigned short>(); } | ||||||
|  | #if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, LongLong) { testNumericType<unsigned long long>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, ULongLong) { testNumericType<unsigned long long>(); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, Int8) { testNumericType<int8_t>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, Uint8) { testNumericType<uint8_t>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, Int16) { testNumericType<int16_t>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, Uint16) { testNumericType<uint16_t>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, Int32) { testNumericType<int32_t>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, Uint32) { testNumericType<uint32_t>(); } | ||||||
|  | #if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, Int64) { testNumericType<int64_t>(); } | ||||||
|  | TEST_F(JsonVariant_Storage_Tests, Uint64) { testNumericType<uint64_t>(); } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| TEST_F(JsonVariant_Storage_Tests, CanStoreObject) { | TEST_F(JsonVariant_Storage_Tests, CanStoreObject) { | ||||||
|   DynamicJsonBuffer jsonBuffer; |   DynamicJsonBuffer jsonBuffer; | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ | |||||||
| // 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> | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| class JsonVariant_Undefined_Tests : public ::testing::Test { | class JsonVariant_Undefined_Tests : public ::testing::Test { | ||||||
|   | |||||||
| @@ -7,7 +7,6 @@ | |||||||
|  |  | ||||||
| #include <sstream> | #include <sstream> | ||||||
| #include <gtest/gtest.h> | #include <gtest/gtest.h> | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
| TEST(StdStream, JsonVariantFalse) { | TEST(StdStream, JsonVariantFalse) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user