mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Templatized all functions using String or std::string
				
					
				
			* Removed `ArduinoJson::String` * Removed `JsonVariant::defaultValue<T>()` * Removed non-template `JsonObject::get()` and `JsonArray.get()` * Fixed support for `StringSumHelper` (issue #184) * Replaced `ARDUINOJSON_USE_ARDUINO_STRING` by `ARDUINOJSON_ENABLE_STD_STRING` and `ARDUINOJSON_ENABLE_ARDUINO_STRING` (issue #378) * Added example `StringExample.ino` to show where `String` can be used
This commit is contained in:
		
							
								
								
									
										29
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -4,8 +4,37 @@ ArduinoJson: change log | |||||||
| HEAD | HEAD | ||||||
| ---- | ---- | ||||||
|  |  | ||||||
|  | * Templatized all functions using `String` or `std::string` | ||||||
|  | * Removed `ArduinoJson::String` | ||||||
|  | * Removed `JsonVariant::defaultValue<T>()` | ||||||
|  | * Removed non-template `JsonObject::get()` and `JsonArray.get()` | ||||||
|  | * Fixed support for `StringSumHelper` (issue #184) | ||||||
|  | * Replaced `ARDUINOJSON_USE_ARDUINO_STRING` by `ARDUINOJSON_ENABLE_STD_STRING` and `ARDUINOJSON_ENABLE_ARDUINO_STRING` (issue #378) | ||||||
|  | * Added example `StringExample.ino` to show where `String` can be used | ||||||
| * Increased default nesting limit to 50 when compiled for a computer (issue #349) | * Increased default nesting limit to 50 when compiled for a computer (issue #349) | ||||||
|  |  | ||||||
|  | **BREAKING CHANGES**: | ||||||
|  |  | ||||||
|  | The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return. | ||||||
|  |  | ||||||
|  | Old code: | ||||||
|  |  | ||||||
|  | ```c++ | ||||||
|  | #define ARDUINOJSON_USE_ARDUINO_STRING 0 | ||||||
|  | JsonVariant value1 = myObject.get("myKey"); | ||||||
|  | JsonVariant value2 = myArray.get(0); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | New code: | ||||||
|  |  | ||||||
|  | ```c++ | ||||||
|  | #define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 | ||||||
|  | #define ARDUINOJSON_ENABLE_STD_STRING 1 | ||||||
|  | JsonVariant value1 = myObject.get<JsonVariant>("myKey"); | ||||||
|  | JsonVariant value2 = myArray.get<JsonVariant>(0); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
| v5.6.7 | v5.6.7 | ||||||
| ------ | ------ | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										53
									
								
								examples/StringExample/StringExample.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								examples/StringExample/StringExample.ino
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  |  | ||||||
|  | // About | ||||||
|  | // ----- | ||||||
|  | // This example shows the different ways you can use String with ArduinoJson. | ||||||
|  | // Please don't see this as an invitation to use String. | ||||||
|  | // On the contrary, you should always use char[] when possible, it's much more | ||||||
|  | // efficient in term of code size, speed and memory usage. | ||||||
|  |  | ||||||
|  | void setup() { | ||||||
|  |   DynamicJsonBuffer jsonBuffer; | ||||||
|  |  | ||||||
|  |   // You can use a String as your JSON input. | ||||||
|  |   // WARNING: the content of the String will be duplicated in the JsonBuffer. | ||||||
|  |   String input = | ||||||
|  |       "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; | ||||||
|  |   JsonObject& root = jsonBuffer.parseObject(input); | ||||||
|  |  | ||||||
|  |   // You can use a String to get an element of a JsonObject | ||||||
|  |   // No duplication is done. | ||||||
|  |   long time = root[String("time")]; | ||||||
|  |  | ||||||
|  |   // You can use a String to set an element of a JsonObject | ||||||
|  |   // WARNING: the content of the String will be duplicated in the JsonBuffer. | ||||||
|  |   root[String("time")] = time; | ||||||
|  |  | ||||||
|  |   // You can get a String from a JsonObject or JsonArray: | ||||||
|  |   // No duplication is done, at least not in the JsonBuffer. | ||||||
|  |   String sensor = root[String("sensor")]; | ||||||
|  |  | ||||||
|  |   // You can set a String to a JsonObject or JsonArray: | ||||||
|  |   // WARNING: the content of the String will be duplicated in the JsonBuffer. | ||||||
|  |   root["sensor"] = sensor; | ||||||
|  |  | ||||||
|  |   // You can also concatenate strings | ||||||
|  |   // WARNING: the content of the String will be duplicated in the JsonBuffer. | ||||||
|  |   root[String("sen") + "sor"] = String("gp") + "s"; | ||||||
|  |  | ||||||
|  |   // Lastly, you can print the resulting JSON to a String | ||||||
|  |   String output; | ||||||
|  |   root.printTo(output); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void loop() { | ||||||
|  |   // not used in this example | ||||||
|  | } | ||||||
| @@ -22,12 +22,17 @@ | |||||||
| #define ARDUINOJSON_USE_INT64 0 | #define ARDUINOJSON_USE_INT64 0 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // arduino has its own implementation of String to replace std::string | // Arduino has its own implementation of String to replace std::string | ||||||
| #ifndef ARDUINOJSON_USE_ARDUINO_STRING | #ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING | ||||||
| #define ARDUINOJSON_USE_ARDUINO_STRING 1 | #define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // arduino doesn't support STL stream | // Arduino doesn't have std::string | ||||||
|  | #ifndef ARDUINOJSON_ENABLE_STD_STRING | ||||||
|  | #define ARDUINOJSON_ENABLE_STD_STRING 0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // Arduino doesn't support STL stream | ||||||
| #ifndef ARDUINOJSON_ENABLE_STD_STREAM | #ifndef ARDUINOJSON_ENABLE_STD_STREAM | ||||||
| #define ARDUINOJSON_ENABLE_STD_STREAM 0 | #define ARDUINOJSON_ENABLE_STD_STREAM 0 | ||||||
| #endif | #endif | ||||||
| @@ -73,8 +78,13 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // on a computer, we can use std::string | // on a computer, we can use std::string | ||||||
| #ifndef ARDUINOJSON_USE_ARDUINO_STRING | #ifndef ARDUINOJSON_ENABLE_STD_STRING | ||||||
| #define ARDUINOJSON_USE_ARDUINO_STRING 0 | #define ARDUINOJSON_ENABLE_STD_STRING 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // on a computer, there is no reason to beleive Arduino String is available | ||||||
|  | #ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING | ||||||
|  | #define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // on a computer, we can assume that the STL is there | // on a computer, we can assume that the STL is there | ||||||
|   | |||||||
| @@ -8,26 +8,26 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "../Print.hpp" | #include "../Print.hpp" | ||||||
| #include "../String.hpp" | #include "StringFuncs.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
|  |  | ||||||
| // A Print implementation that allows to write in a String | // A Print implementation that allows to write in a String | ||||||
|  | template <typename TString> | ||||||
| class DynamicStringBuilder : public Print { | class DynamicStringBuilder : public Print { | ||||||
|  public: |  public: | ||||||
|   DynamicStringBuilder(String &str) : _str(str) {} |   DynamicStringBuilder(TString &str) : _str(str) {} | ||||||
|  |  | ||||||
|   virtual size_t write(uint8_t c) { |   virtual size_t write(uint8_t c) { | ||||||
|     // Need to cast to char, otherwise String will print a number (issue #120) |     StringFuncs<TString>::append(_str, static_cast<char>(c)); | ||||||
|     _str += static_cast<char>(c); |  | ||||||
|     return 1; |     return 1; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   DynamicStringBuilder &operator=(const DynamicStringBuilder &); |   DynamicStringBuilder &operator=(const DynamicStringBuilder &); | ||||||
|  |  | ||||||
|   String &_str; |   TString &_str; | ||||||
| }; | }; | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "../Configuration.hpp" | #include "../Configuration.hpp" | ||||||
|  | #include "../TypeTraits/EnableIf.hpp" | ||||||
| #include "DummyPrint.hpp" | #include "DummyPrint.hpp" | ||||||
| #include "DynamicStringBuilder.hpp" | #include "DynamicStringBuilder.hpp" | ||||||
| #include "IndentedPrint.hpp" | #include "IndentedPrint.hpp" | ||||||
| @@ -49,8 +50,10 @@ class JsonPrintable { | |||||||
|     return printTo(sb); |     return printTo(sb); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t printTo(String &str) const { |   template <typename TString> | ||||||
|     DynamicStringBuilder sb(str); |   typename TypeTraits::EnableIf<StringFuncs<TString>::has_append, size_t>::type | ||||||
|  |   printTo(TString &str) const { | ||||||
|  |     DynamicStringBuilder<TString> sb(str); | ||||||
|     return printTo(sb); |     return printTo(sb); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -69,8 +72,10 @@ class JsonPrintable { | |||||||
|     return prettyPrintTo(indentedPrint); |     return prettyPrintTo(indentedPrint); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t prettyPrintTo(String &str) const { |   template <typename TString> | ||||||
|     DynamicStringBuilder sb(str); |   typename TypeTraits::EnableIf<StringFuncs<TString>::has_append, size_t>::type | ||||||
|  |   prettyPrintTo(TString &str) const { | ||||||
|  |     DynamicStringBuilder<TString> sb(str); | ||||||
|     return prettyPrintTo(sb); |     return prettyPrintTo(sb); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,17 +8,19 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace TypeTraits { | namespace Internals { | ||||||
| 
 | 
 | ||||||
| // A meta-function that returns true if T is a reference
 |  | ||||||
| template <typename T> | template <typename T> | ||||||
| struct IsReference { | struct JsonVariantDefault { | ||||||
|   static const bool value = false; |   static T get() { | ||||||
|  |     return T(); | ||||||
|  |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
| struct IsReference<T&> { | struct JsonVariantDefault<const T> : JsonVariantDefault<T> {}; | ||||||
|   static const bool value = true; | 
 | ||||||
| }; | template <typename T> | ||||||
|  | struct JsonVariantDefault<T&> : JsonVariantDefault<T> {}; | ||||||
| } | } | ||||||
| } | } | ||||||
							
								
								
									
										94
									
								
								include/ArduinoJson/Internals/StringFuncs.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								include/ArduinoJson/Internals/StringFuncs.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | |||||||
|  | // 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" | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_ENABLE_ARDUINO_STRING | ||||||
|  | #include <WString.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_ENABLE_STD_STRING | ||||||
|  | #include <string> | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  |  | ||||||
|  | template <typename TString> | ||||||
|  | struct StringFuncs {}; | ||||||
|  |  | ||||||
|  | template <typename TString> | ||||||
|  | struct StringFuncs<const TString> : StringFuncs<TString> {}; | ||||||
|  |  | ||||||
|  | template <typename TString> | ||||||
|  | struct StringFuncs<TString&> : StringFuncs<TString> {}; | ||||||
|  |  | ||||||
|  | struct CharPtrFuncs { | ||||||
|  |   static bool equals(const char* str, const char* expected) { | ||||||
|  |     return strcmp(str, expected) == 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename Buffer> | ||||||
|  |   static char* duplicate(const char* str, Buffer* buffer) { | ||||||
|  |     if (!str) return NULL; | ||||||
|  |     size_t size = strlen(str) + 1; | ||||||
|  |     void* dup = buffer->alloc(size); | ||||||
|  |     if (dup != NULL) memcpy(dup, str, size); | ||||||
|  |     return static_cast<char*>(dup); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static const bool has_append = false; | ||||||
|  |   static const bool should_duplicate = false; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct StringFuncs<const char*> : CharPtrFuncs {}; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct StringFuncs<char*> : CharPtrFuncs {}; | ||||||
|  |  | ||||||
|  | template <size_t N> | ||||||
|  | struct StringFuncs<char[N]> : CharPtrFuncs {}; | ||||||
|  |  | ||||||
|  | template <typename TString> | ||||||
|  | struct StdStringFuncs { | ||||||
|  |   template <typename Buffer> | ||||||
|  |   static char* duplicate(const TString& str, Buffer* buffer) { | ||||||
|  |     if (!str.c_str()) return NULL;  // <- Arduino string can return NULL | ||||||
|  |     size_t size = str.length() + 1; | ||||||
|  |     void* dup = buffer->alloc(size); | ||||||
|  |     if (dup != NULL) memcpy(dup, str.c_str(), size); | ||||||
|  |     return static_cast<char*>(dup); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool equals(const TString& str, const char* expected) { | ||||||
|  |     return str == expected; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static void append(TString& str, char c) { | ||||||
|  |     str += c; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static const bool has_append = true; | ||||||
|  |   static const bool should_duplicate = true; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_ENABLE_ARDUINO_STRING | ||||||
|  | template <> | ||||||
|  | struct StringFuncs<String> : StdStringFuncs<String> {}; | ||||||
|  | template <> | ||||||
|  | struct StringFuncs<StringSumHelper> : StdStringFuncs<StringSumHelper> {}; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_ENABLE_STD_STRING | ||||||
|  | template <> | ||||||
|  | struct StringFuncs<std::string> : StdStringFuncs<std::string> {}; | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										41
									
								
								include/ArduinoJson/Internals/ValueSetter.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								include/ArduinoJson/Internals/ValueSetter.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 "../JsonBuffer.hpp" | ||||||
|  | #include "../JsonVariant.hpp" | ||||||
|  | #include "../TypeTraits/EnableIf.hpp" | ||||||
|  | #include "StringFuncs.hpp" | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  |  | ||||||
|  | template <typename TSource, typename Enable = void> | ||||||
|  | struct ValueSetter { | ||||||
|  |   template <typename TDestination> | ||||||
|  |   static bool set(JsonBuffer*, TDestination& destination, | ||||||
|  |                   const TSource& source) { | ||||||
|  |     destination = source; | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename TSource> | ||||||
|  | struct ValueSetter<TSource, typename TypeTraits::EnableIf< | ||||||
|  |                                 StringFuncs<TSource>::should_duplicate>::type> { | ||||||
|  |   template <typename TDestination> | ||||||
|  |   static bool set(JsonBuffer* buffer, TDestination& destination, | ||||||
|  |                   const TSource& source) { | ||||||
|  |     const char* copy = buffer->strdup(source); | ||||||
|  |     if (!copy) return false; | ||||||
|  |     destination = copy; | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | } | ||||||
|  | } | ||||||
| @@ -11,10 +11,12 @@ | |||||||
| #include "Internals/JsonPrintable.hpp" | #include "Internals/JsonPrintable.hpp" | ||||||
| #include "Internals/List.hpp" | #include "Internals/List.hpp" | ||||||
| #include "Internals/ReferenceType.hpp" | #include "Internals/ReferenceType.hpp" | ||||||
|  | #include "Internals/StringFuncs.hpp" | ||||||
|  | #include "Internals/ValueSetter.hpp" | ||||||
| #include "JsonVariant.hpp" | #include "JsonVariant.hpp" | ||||||
|  | #include "TypeTraits/ConstRefOrConstPtr.hpp" | ||||||
| #include "TypeTraits/EnableIf.hpp" | #include "TypeTraits/EnableIf.hpp" | ||||||
| #include "TypeTraits/IsFloatingPoint.hpp" | #include "TypeTraits/IsFloatingPoint.hpp" | ||||||
| #include "TypeTraits/IsReference.hpp" |  | ||||||
| #include "TypeTraits/IsSame.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. | ||||||
| @@ -40,15 +42,6 @@ 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(). | ||||||
| @@ -57,7 +50,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|  |  | ||||||
|   // Gets the value at the specified index |   // Gets the value at the specified index | ||||||
|   JsonVariant operator[](size_t index) const { |   JsonVariant operator[](size_t index) const { | ||||||
|     return get(index); |     return get<JsonVariant>(index); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Gets or sets the value at specified index |   // Gets or sets the value at specified index | ||||||
| @@ -73,29 +66,24 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   // bool add(float value); |   // bool add(float value); | ||||||
|   // bool add(double value); |   // bool add(double value); | ||||||
|   // bool add(const char*); |   // bool add(const char*); | ||||||
|   template <typename T> |   // bool add(const char[]); | ||||||
|   bool add( |   // bool add(const char[N]); | ||||||
|       T value, |   // bool add(RawJson); | ||||||
|       typename TypeTraits::EnableIf< |   // bool add(const std::string&) | ||||||
|           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) { |  | ||||||
|     return addNode<T>(value); |  | ||||||
|   } |  | ||||||
|   // bool add(const String&) |   // bool add(const String&) | ||||||
|   // bool add(const JsonVariant&); |   // bool add(const JsonVariant&); | ||||||
|   // bool add(JsonArray&); |   // bool add(JsonArray&); | ||||||
|   // bool add(JsonObject&); |   // bool add(JsonObject&); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   bool add(const T &value, |   bool add(const T &value) { | ||||||
|            typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) { |     // reduce the number of template function instanciation to reduce code size | ||||||
|     return addNode<T &>(const_cast<T &>(value)); |     return addNodeImpl<typename TypeTraits::ConstRefOrConstPtr<T>::type>(value); | ||||||
|   } |   } | ||||||
|   // bool add(float value, uint8_t decimals); |   // bool add(float value, uint8_t decimals); | ||||||
|   // bool add(double value, uint8_t decimals); |   // bool add(double value, uint8_t decimals); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   bool add(T value, uint8_t decimals, |   bool add(T value, uint8_t decimals) { | ||||||
|            typename TypeTraits::EnableIf< |     return add(JsonVariant(value, decimals)); | ||||||
|                TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { |  | ||||||
|     return addNode<JsonVariant>(JsonVariant(value, decimals)); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Sets the value at specified index. |   // Sets the value at specified index. | ||||||
| @@ -104,42 +92,33 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   // bool set(size_t index, long value); |   // bool set(size_t index, long value); | ||||||
|   // bool set(size_t index, int value); |   // bool set(size_t index, int value); | ||||||
|   // bool set(size_t index, short value); |   // bool set(size_t index, short value); | ||||||
|   template <typename T> |   // bool set(size_t index, const std::string&) | ||||||
|   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 String&) | ||||||
|   // bool set(size_t index, const JsonVariant&); |   // bool set(size_t index, const JsonVariant&); | ||||||
|   // bool set(size_t index, JsonArray&); |   // bool set(size_t index, JsonArray&); | ||||||
|   // bool set(size_t index, JsonObject&); |   // bool set(size_t index, JsonObject&); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   bool set(size_t index, const T &value, |   bool set(size_t index, const T &value) { | ||||||
|            typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) { |     // reduce the number of template function instanciation to reduce code size | ||||||
|     return setNodeAt<T &>(index, const_cast<T &>(value)); |     return setNodeAt<typename TypeTraits::ConstRefOrConstPtr<T>::type>(index, | ||||||
|  |                                                                        value); | ||||||
|   } |   } | ||||||
|   // bool set(size_t index, float value, uint8_t decimals = 2); |   // bool set(size_t index, float value, uint8_t decimals = 2); | ||||||
|   // bool set(size_t index, double value, uint8_t decimals = 2); |   // bool set(size_t index, double value, uint8_t decimals = 2); | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   bool set(size_t index, T value, uint8_t decimals, |   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value, | ||||||
|            typename TypeTraits::EnableIf< |                                 bool>::type | ||||||
|                TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { |   set(size_t index, T value, uint8_t decimals) { | ||||||
|     return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals)); |     return set(index, JsonVariant(value, decimals)); | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Gets the value at the specified index. |  | ||||||
|   JsonVariant get(size_t index) const { |  | ||||||
|     node_type *node = getNodeAt(index); |  | ||||||
|     return node ? node->content : JsonVariant(); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Gets the value at the specified index. |   // Gets the value at the specified index. | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   typename Internals::JsonVariantAs<T>::type get(size_t index) const { |   typename Internals::JsonVariantAs<T>::type get(size_t index) const { | ||||||
|     node_type *node = getNodeAt(index); |     node_type *node = getNodeAt(index); | ||||||
|     return node ? node->content.as<T>() : JsonVariant::defaultValue<T>(); |     return node ? node->content.as<T>() | ||||||
|  |                 : Internals::JsonVariantDefault<T>::get(); | ||||||
|  |     ; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Check the type of the value at specified index. |   // Check the type of the value at specified index. | ||||||
| @@ -172,7 +151,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|  |  | ||||||
|   // Imports a 1D array |   // Imports a 1D array | ||||||
|   template <typename T, size_t N> |   template <typename T, size_t N> | ||||||
|   bool copyFrom(T(&array)[N]) { |   bool copyFrom(T (&array)[N]) { | ||||||
|     return copyFrom(array, N); |     return copyFrom(array, N); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -188,7 +167,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|  |  | ||||||
|   // Imports a 2D array |   // Imports a 2D array | ||||||
|   template <typename T, size_t N1, size_t N2> |   template <typename T, size_t N1, size_t N2> | ||||||
|   bool copyFrom(T(&array)[N1][N2]) { |   bool copyFrom(T (&array)[N1][N2]) { | ||||||
|     bool ok = true; |     bool ok = true; | ||||||
|     for (size_t i = 0; i < N1; i++) { |     for (size_t i = 0; i < N1; i++) { | ||||||
|       JsonArray &nestedArray = createNestedArray(); |       JsonArray &nestedArray = createNestedArray(); | ||||||
| @@ -201,7 +180,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|  |  | ||||||
|   // Exports a 1D array |   // Exports a 1D array | ||||||
|   template <typename T, size_t N> |   template <typename T, size_t N> | ||||||
|   size_t copyTo(T(&array)[N]) const { |   size_t copyTo(T (&array)[N]) const { | ||||||
|     return copyTo(array, N); |     return copyTo(array, N); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -216,7 +195,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|  |  | ||||||
|   // Exports a 2D array |   // Exports a 2D array | ||||||
|   template <typename T, size_t N1, size_t N2> |   template <typename T, size_t N1, size_t N2> | ||||||
|   void copyTo(T(&array)[N1][N2]) const { |   void copyTo(T (&array)[N1][N2]) const { | ||||||
|     size_t i = 0; |     size_t i = 0; | ||||||
|     for (const_iterator it = begin(); it != end() && i < N1; ++it) { |     for (const_iterator it = begin(); it != end() && i < N1; ++it) { | ||||||
|       it->asArray().copyTo(array[i++]); |       it->asArray().copyTo(array[i++]); | ||||||
| @@ -230,22 +209,22 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|     return node; |     return node; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValueRef> | ||||||
|   bool setNodeAt(size_t index, TValue value) { |   bool setNodeAt(size_t index, TValueRef value) { | ||||||
|     node_type *node = getNodeAt(index); |     node_type *node = getNodeAt(index); | ||||||
|     return node != NULL && setNodeValue<TValue>(node, value); |     if (!node) return false; | ||||||
|  |  | ||||||
|  |     return Internals::ValueSetter<TValueRef>::set(_buffer, node->content, | ||||||
|  |                                                   value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValueRef> | ||||||
|   bool addNode(TValue value) { |   bool addNodeImpl(TValueRef value) { | ||||||
|     node_type *node = addNewNode(); |     node_type *node = addNewNode(); | ||||||
|     return node != NULL && setNodeValue<TValue>(node, value); |     if (!node) return false; | ||||||
|   } |  | ||||||
|  |  | ||||||
|   template <typename T> |     return Internals::ValueSetter<TValueRef>::set(_buffer, node->content, | ||||||
|   bool setNodeValue(node_type *node, T value) { |                                                   value); | ||||||
|     node->content = value; |  | ||||||
|     return true; |  | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -13,50 +13,31 @@ | |||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(JsonArray &array) { | inline JsonVariant::JsonVariant(const JsonArray &array) { | ||||||
|   if (array.success()) { |   if (array.success()) { | ||||||
|     _type = Internals::JSON_ARRAY; |     _type = Internals::JSON_ARRAY; | ||||||
|     _content.asArray = &array; |     _content.asArray = const_cast<JsonArray *>(&array); | ||||||
|   } else { |   } else { | ||||||
|     _type = Internals::JSON_UNDEFINED; |     _type = Internals::JSON_UNDEFINED; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonVariant::JsonVariant(JsonObject &object) { | inline JsonVariant::JsonVariant(const JsonObject &object) { | ||||||
|   if (object.success()) { |   if (object.success()) { | ||||||
|     _type = Internals::JSON_OBJECT; |     _type = Internals::JSON_OBJECT; | ||||||
|     _content.asObject = &object; |     _content.asObject = const_cast<JsonObject *>(&object); | ||||||
|   } else { |   } else { | ||||||
|     _type = Internals::JSON_UNDEFINED; |     _type = Internals::JSON_UNDEFINED; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | namespace Internals { | ||||||
| template <> | template <> | ||||||
| inline bool JsonArray::setNodeValue(node_type *node, String &value) { | struct JsonVariantDefault<JsonArray> { | ||||||
|   const char *copy = _buffer->strdup(value); |   static JsonArray &get() { | ||||||
|   if (!copy) return false; |     return JsonArray::invalid(); | ||||||
|   node->content = copy; |   } | ||||||
|   return true; | }; | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline JsonArray &JsonVariant::defaultValue<JsonArray>() { |  | ||||||
|   return JsonArray::invalid(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline JsonArray &JsonVariant::defaultValue<JsonArray &>() { |  | ||||||
|   return JsonArray::invalid(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline const JsonArray &JsonVariant::defaultValue<const JsonArray>() { |  | ||||||
|   return JsonArray::invalid(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline const JsonArray &JsonVariant::defaultValue<const JsonArray &>() { |  | ||||||
|   return JsonArray::invalid(); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonArray &JsonVariant::asArray() const { | inline JsonArray &JsonVariant::asArray() const { | ||||||
| @@ -71,10 +52,11 @@ inline JsonArray &JsonArray::createNestedArray() { | |||||||
|   return array; |   return array; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonArray &JsonObject::createNestedArray(JsonObjectKey key) { | template <typename TString> | ||||||
|  | inline JsonArray &JsonObject::createNestedArray(const TString &key) { | ||||||
|   if (!_buffer) return JsonArray::invalid(); |   if (!_buffer) return JsonArray::invalid(); | ||||||
|   JsonArray &array = _buffer->createArray(); |   JsonArray &array = _buffer->createArray(); | ||||||
|   setNodeAt<const JsonVariant &>(key, array); |   set(key, array); | ||||||
|   return array; |   return array; | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,24 +21,14 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | |||||||
|   FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index) |   FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index) | ||||||
|       : _array(array), _index(index) {} |       : _array(array), _index(index) {} | ||||||
|  |  | ||||||
|   JsonArraySubscript& operator=(const JsonArraySubscript& src) { |   FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) { | ||||||
|     _array.set<const JsonVariant&>(_index, src); |     _array.set(_index, src); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   typename TypeTraits::EnableIf<JsonArray::CanSet<T&>::value, |   FORCE_INLINE JsonArraySubscript& operator=(const T& src) { | ||||||
|                                 JsonArraySubscript>::type& |     _array.set(_index, src); | ||||||
|   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; |     return *this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -46,10 +36,6 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | |||||||
|     return _index < _array.size(); |     return _index < _array.size(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE operator JsonVariant() const { |  | ||||||
|     return _array.get(_index); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE typename Internals::JsonVariantAs<T>::type as() const { |   FORCE_INLINE typename Internals::JsonVariantAs<T>::type as() const { | ||||||
|     return _array.get<T>(_index); |     return _array.get<T>(_index); | ||||||
| @@ -61,7 +47,7 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   void set(TValue value) { |   FORCE_INLINE void set(const TValue& value) { | ||||||
|     _array.set(_index, value); |     _array.set(_index, value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,7 +12,6 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
| #include "JsonVariant.hpp" | #include "JsonVariant.hpp" | ||||||
| #include "String.hpp" |  | ||||||
|  |  | ||||||
| #if defined(__clang__) | #if defined(__clang__) | ||||||
| #pragma clang diagnostic push | #pragma clang diagnostic push | ||||||
| @@ -58,67 +57,56 @@ class JsonBuffer { | |||||||
|   // writable |   // writable | ||||||
|   // because the parser will insert null-terminators and replace escaped chars. |   // because the parser will insert null-terminators and replace escaped chars. | ||||||
|   // |   // | ||||||
|   // The second argument set the nesting limit (see comment on DEFAULT_LIMIT) |   // The second argument set the nesting limit | ||||||
|   // |   // | ||||||
|   // Returns a reference to the new JsonObject or JsonObject::invalid() if the |   // Returns a reference to the new JsonObject or JsonObject::invalid() if the | ||||||
|   // allocation fails. |   // allocation fails. | ||||||
|   JsonArray &parseArray(char *json, uint8_t nestingLimit = DEFAULT_LIMIT); |   JsonArray &parseArray( | ||||||
|  |       char *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT); | ||||||
|  |  | ||||||
|   // Same with a const char*. |  | ||||||
|   // With this overload, the JsonBuffer will make a copy of the string |   // With this overload, the JsonBuffer will make a copy of the string | ||||||
|   JsonArray &parseArray(const char *json, uint8_t nesting = DEFAULT_LIMIT) { |   template <typename TString> | ||||||
|  |   JsonArray &parseArray(const TString &json, | ||||||
|  |                         uint8_t nesting = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||||
|     return parseArray(strdup(json), nesting); |     return parseArray(strdup(json), nesting); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Same as above with a String class |  | ||||||
|   JsonArray &parseArray(const String &json, uint8_t nesting = DEFAULT_LIMIT) { |  | ||||||
|     return parseArray(json.c_str(), nesting); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Allocates and populate a JsonObject from a JSON string. |   // Allocates and populate a JsonObject from a JSON string. | ||||||
|   // |   // | ||||||
|   // The First argument is a pointer to the JSON string, the memory must be |   // The First argument is a pointer to the JSON string, the memory must be | ||||||
|   // writable |   // writable | ||||||
|   // because the parser will insert null-terminators and replace escaped chars. |   // because the parser will insert null-terminators and replace escaped chars. | ||||||
|   // |   // | ||||||
|   // The second argument set the nesting limit (see comment on DEFAULT_LIMIT) |   // The second argument set the nesting limit | ||||||
|   // |   // | ||||||
|   // Returns a reference to the new JsonObject or JsonObject::invalid() if the |   // Returns a reference to the new JsonObject or JsonObject::invalid() if the | ||||||
|   // allocation fails. |   // allocation fails. | ||||||
|   JsonObject &parseObject(char *json, uint8_t nestingLimit = DEFAULT_LIMIT); |   JsonObject &parseObject( | ||||||
|  |       char *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT); | ||||||
|  |  | ||||||
|   // Same with a const char*. |  | ||||||
|   // With this overload, the JsonBuffer will make a copy of the string |   // With this overload, the JsonBuffer will make a copy of the string | ||||||
|   JsonObject &parseObject(const char *json, uint8_t nesting = DEFAULT_LIMIT) { |   template <typename TString> | ||||||
|  |   JsonObject &parseObject(const TString &json, | ||||||
|  |                           uint8_t nesting = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||||
|     return parseObject(strdup(json), nesting); |     return parseObject(strdup(json), nesting); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Same as above with a String class |  | ||||||
|   JsonObject &parseObject(const String &json, uint8_t nesting = DEFAULT_LIMIT) { |  | ||||||
|     return parseObject(json.c_str(), nesting); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Generalized version of parseArray() and parseObject(), also works for |   // Generalized version of parseArray() and parseObject(), also works for | ||||||
|   // integral types. |   // integral types. | ||||||
|   JsonVariant parse(char *json, uint8_t nestingLimit = DEFAULT_LIMIT); |   JsonVariant parse(char *json, | ||||||
|  |                     uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT); | ||||||
|  |  | ||||||
|   // Same with a const char*. |  | ||||||
|   // With this overload, the JsonBuffer will make a copy of the string |   // With this overload, the JsonBuffer will make a copy of the string | ||||||
|   JsonVariant parse(const char *json, uint8_t nesting = DEFAULT_LIMIT) { |   template <typename TString> | ||||||
|  |   JsonVariant parse(const TString &json, | ||||||
|  |                     uint8_t nesting = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { | ||||||
|     return parse(strdup(json), nesting); |     return parse(strdup(json), nesting); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Same as above with a String class |  | ||||||
|   JsonVariant parse(const String &json, uint8_t nesting = DEFAULT_LIMIT) { |  | ||||||
|     return parse(json.c_str(), nesting); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Duplicate a string |   // Duplicate a string | ||||||
|   char *strdup(const char *src) { |   template <typename TString> | ||||||
|     return src ? strdup(src, strlen(src)) : NULL; |   char *strdup(const TString &src) { | ||||||
|   } |     return Internals::StringFuncs<TString>::duplicate(src, this); | ||||||
|   char *strdup(const String &src) { |  | ||||||
|     return strdup(src.c_str(), src.length()); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Allocates n bytes in the JsonBuffer. |   // Allocates n bytes in the JsonBuffer. | ||||||
| @@ -135,23 +123,6 @@ class JsonBuffer { | |||||||
|     return bytes; |     return bytes; | ||||||
| #endif | #endif | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  | ||||||
|   char *strdup(const char *, size_t); |  | ||||||
|  |  | ||||||
|   // Default value of nesting limit of parseArray() and parseObject(). |  | ||||||
|   // |  | ||||||
|   // The nesting limit is a constrain on the level of nesting allowed in the |  | ||||||
|   // JSON string. |  | ||||||
|   // If set to 0, only a flat array or objects can be parsed. |  | ||||||
|   // If set to 1, the object can contain nested arrays or objects but only 1 |  | ||||||
|   // level deep. |  | ||||||
|   // And bigger values will allow more level of nesting. |  | ||||||
|   // |  | ||||||
|   // The purpose of this feature is to prevent stack overflow that could |  | ||||||
|   // lead to |  | ||||||
|   // a security risk. |  | ||||||
|   static const uint8_t DEFAULT_LIMIT = ARDUINOJSON_DEFAULT_NESTING_LIMIT; |  | ||||||
| }; | }; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -36,11 +36,3 @@ inline ArduinoJson::JsonVariant ArduinoJson::JsonBuffer::parse( | |||||||
|   Internals::JsonParser parser(this, json, nestingLimit); |   Internals::JsonParser parser(this, json, nestingLimit); | ||||||
|   return parser.parseVariant(); |   return parser.parseVariant(); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline char *ArduinoJson::JsonBuffer::strdup(const char *source, |  | ||||||
|                                              size_t length) { |  | ||||||
|   size_t size = length + 1; |  | ||||||
|   char *dest = static_cast<char *>(alloc(size)); |  | ||||||
|   if (dest != NULL) memcpy(dest, source, size); |  | ||||||
|   return dest; |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -7,15 +7,16 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "String.hpp" |  | ||||||
| #include "Internals/JsonBufferAllocated.hpp" | #include "Internals/JsonBufferAllocated.hpp" | ||||||
| #include "Internals/JsonPrintable.hpp" | #include "Internals/JsonPrintable.hpp" | ||||||
| #include "Internals/List.hpp" | #include "Internals/List.hpp" | ||||||
| #include "Internals/ReferenceType.hpp" | #include "Internals/ReferenceType.hpp" | ||||||
|  | #include "Internals/StringFuncs.hpp" | ||||||
|  | #include "Internals/ValueSetter.hpp" | ||||||
| #include "JsonPair.hpp" | #include "JsonPair.hpp" | ||||||
|  | #include "TypeTraits/ConstRefOrConstPtr.hpp" | ||||||
| #include "TypeTraits/EnableIf.hpp" | #include "TypeTraits/EnableIf.hpp" | ||||||
| #include "TypeTraits/IsFloatingPoint.hpp" | #include "TypeTraits/IsFloatingPoint.hpp" | ||||||
| #include "TypeTraits/IsReference.hpp" |  | ||||||
| #include "TypeTraits/IsSame.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. | ||||||
| @@ -40,27 +41,19 @@ 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(). | ||||||
|   explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {} |   explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {} | ||||||
|  |  | ||||||
|   // Gets or sets the value associated with the specified key. |   // Gets or sets the value associated with the specified key. | ||||||
|   JsonObjectSubscript<const char*> operator[](const char* key); |   template <typename TString> | ||||||
|   JsonObjectSubscript<const String&> operator[](const String& key); |   JsonObjectSubscript<TString> operator[](const TString& key); | ||||||
|  |  | ||||||
|   // Gets the value associated with the specified key. |   // Gets the value associated with the specified key. | ||||||
|   JsonVariant operator[](JsonObjectKey key) const { |   template <typename TString> | ||||||
|     return get(key); |   JsonVariant operator[](const TString& key) const { | ||||||
|  |     return get<JsonVariant>(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Sets the specified key with the specified value. |   // Sets the specified key with the specified value. | ||||||
| @@ -73,67 +66,62 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // bool set(TKey key, double value); |   // bool set(TKey key, double value); | ||||||
|   // bool set(TKey key, const char* value); |   // bool set(TKey key, const char* value); | ||||||
|   // bool set(TKey key, RawJson value); |   // bool set(TKey key, RawJson value); | ||||||
|   template <typename T> |  | ||||||
|   bool set( |  | ||||||
|       JsonObjectKey key, T value, |  | ||||||
|       typename TypeTraits::EnableIf< |  | ||||||
|           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type* = 0) { |  | ||||||
|     return setNodeAt<T>(key, value); |  | ||||||
|   } |  | ||||||
|   // bool set(Key, String&); |   // bool set(Key, String&); | ||||||
|   // bool set(Key, JsonArray&); |   // bool set(Key, JsonArray&); | ||||||
|   // bool set(Key, JsonObject&); |   // bool set(Key, JsonObject&); | ||||||
|   // bool set(Key, JsonVariant&); |   // bool set(Key, JsonVariant&); | ||||||
|   template <typename T> |   template <typename TValue, typename TString> | ||||||
|   bool set(JsonObjectKey key, const T& value, |   bool set(const TString& key, const TValue& value) { | ||||||
|            typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) { |     // reduce the number of template function instanciation to reduce code size | ||||||
|     return setNodeAt<T&>(key, const_cast<T&>(value)); |     return setNodeAt<typename TypeTraits::ConstRefOrConstPtr<TString>::type, | ||||||
|  |                      typename TypeTraits::ConstRefOrConstPtr<TValue>::type>( | ||||||
|  |         key, value); | ||||||
|   } |   } | ||||||
|   // bool set(Key, float value, uint8_t decimals); |   // bool set(Key, float value, uint8_t decimals); | ||||||
|   // bool set(Key, double value, uint8_t decimals); |   // bool set(Key, double value, uint8_t decimals); | ||||||
|   template <typename TValue> |   template <typename TValue, typename TString> | ||||||
|   bool set(JsonObjectKey key, TValue value, uint8_t decimals, |   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value, | ||||||
|            typename TypeTraits::EnableIf< |                                 bool>::type | ||||||
|                TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) { |   set(const TString& key, TValue value, uint8_t decimals) { | ||||||
|     return setNodeAt<const JsonVariant&>(key, JsonVariant(value, decimals)); |     return set(key, JsonVariant(value, decimals)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Gets the value associated with the specified key. |   // Gets the value associated with the specified key. | ||||||
|   JsonVariant get(JsonObjectKey key) const { |   template <typename TValue, typename TString> | ||||||
|     node_type* node = getNodeAt(key.c_str()); |   typename Internals::JsonVariantAs<TValue>::type get( | ||||||
|     return node ? node->content.value : JsonVariant(); |       const TString& key) const { | ||||||
|   } |     node_type* node = getNodeAt(key); | ||||||
|  |     return node ? node->content.value.as<TValue>() | ||||||
|   // Gets the value associated with the specified key. |                 : Internals::JsonVariantDefault<TValue>::get(); | ||||||
|   template <typename T> |  | ||||||
|   typename Internals::JsonVariantAs<T>::type get(JsonObjectKey key) const { |  | ||||||
|     node_type* node = getNodeAt(key.c_str()); |  | ||||||
|     return node ? node->content.value.as<T>() : JsonVariant::defaultValue<T>(); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Checks the type of the value associated with the specified key. |   // Checks the type of the value associated with the specified key. | ||||||
|   template <typename T> |   template <typename TValue, typename TString> | ||||||
|   bool is(JsonObjectKey key) const { |   bool is(const TString& key) const { | ||||||
|     node_type* node = getNodeAt(key.c_str()); |     node_type* node = getNodeAt(key); | ||||||
|     return node ? node->content.value.is<T>() : false; |     return node ? node->content.value.is<TValue>() : false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Creates and adds a JsonArray. |   // Creates and adds a JsonArray. | ||||||
|   // This is a shortcut for JsonBuffer::createArray() and JsonObject::add(). |   // This is a shortcut for JsonBuffer::createArray() and JsonObject::add(). | ||||||
|   JsonArray& createNestedArray(JsonObjectKey key); |   template <typename TString> | ||||||
|  |   JsonArray& createNestedArray(const TString& 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(). | ||||||
|   JsonObject& createNestedObject(JsonObjectKey key); |   template <typename TString> | ||||||
|  |   JsonObject& createNestedObject(const TString& 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. | ||||||
|   bool containsKey(JsonObjectKey key) const { |   template <typename TString> | ||||||
|     return getNodeAt(key.c_str()) != NULL; |   bool containsKey(const TString& key) const { | ||||||
|  |     return getNodeAt(key) != NULL; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Removes the specified key and the associated value. |   // Removes the specified key and the associated value. | ||||||
|   void remove(JsonObjectKey key) { |   template <typename TString> | ||||||
|     removeNode(getNodeAt(key.c_str())); |   void remove(const TString& key) { | ||||||
|  |     removeNode(getNodeAt(key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Returns a reference an invalid JsonObject. |   // Returns a reference an invalid JsonObject. | ||||||
| @@ -146,37 +134,35 @@ 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(const char* key) const { |   template <typename TString> | ||||||
|  |   node_type* getNodeAt(const TString& key) const { | ||||||
|  |     // reduce the number of template function instanciation to reduce code size | ||||||
|  |     return getNodeAtImpl< | ||||||
|  |         typename TypeTraits::ConstRefOrConstPtr<TString>::type>(key); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename TStringRef> | ||||||
|  |   node_type* getNodeAtImpl(TStringRef 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 (Internals::StringFuncs<TStringRef>::equals(key, node->content.key)) | ||||||
|  |         return node; | ||||||
|     } |     } | ||||||
|     return NULL; |     return NULL; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename TStringRef, typename TValueRef> | ||||||
|   bool setNodeAt(JsonObjectKey key, T value) { |   bool setNodeAt(TStringRef key, TValueRef value) { | ||||||
|     node_type* node = getNodeAt(key.c_str()); |     node_type* node = getNodeAtImpl<TStringRef>(key); | ||||||
|     if (!node) { |     if (!node) { | ||||||
|       node = addNewNode(); |       node = addNewNode(); | ||||||
|       if (!node || !setNodeKey(node, key)) return false; |       if (!node) return false; | ||||||
|     } |  | ||||||
|     return setNodeValue<T>(node, value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   bool setNodeKey(node_type* node, JsonObjectKey key) { |       bool key_ok = Internals::ValueSetter<TStringRef>::set( | ||||||
|     if (key.needs_copy()) { |           _buffer, node->content.key, key); | ||||||
|       node->content.key = _buffer->strdup(key.c_str()); |       if (!key_ok) return false; | ||||||
|       if (node->content.key == NULL) return false; |  | ||||||
|     } else { |  | ||||||
|       node->content.key = key.c_str(); |  | ||||||
|     } |     } | ||||||
|     return true; |     return Internals::ValueSetter<TValueRef>::set(_buffer, node->content.value, | ||||||
|   } |                                                   value); | ||||||
|  |  | ||||||
|   template <typename T> |  | ||||||
|   bool setNodeValue(node_type* node, T value) { |  | ||||||
|     node->content.value = value; |  | ||||||
|     return true; |  | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -13,38 +13,13 @@ | |||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
|  | namespace Internals { | ||||||
| template <> | template <> | ||||||
| inline bool JsonObject::setNodeValue(node_type *node, String &value) { | struct JsonVariantDefault<JsonObject> { | ||||||
|   const char *dup = _buffer->strdup(value); |   static JsonObject &get() { | ||||||
|   node->content.value = dup; |     return JsonObject::invalid(); | ||||||
|   return dup != NULL; |   } | ||||||
| } | }; | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline bool JsonObject::setNodeValue(node_type *node, const String &value) { |  | ||||||
|   const char *dup = _buffer->strdup(value); |  | ||||||
|   node->content.value = dup; |  | ||||||
|   return dup != NULL; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline const JsonObject &JsonVariant::defaultValue<const JsonObject &>() { |  | ||||||
|   return JsonObject::invalid(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline const JsonObject &JsonVariant::defaultValue<const JsonObject>() { |  | ||||||
|   return JsonObject::invalid(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline JsonObject &JsonVariant::defaultValue<JsonObject &>() { |  | ||||||
|   return JsonObject::invalid(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline JsonObject &JsonVariant::defaultValue<JsonObject>() { |  | ||||||
|   return JsonObject::invalid(); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonObject &JsonVariant::asObject() const { | inline JsonObject &JsonVariant::asObject() const { | ||||||
| @@ -52,11 +27,12 @@ inline JsonObject &JsonVariant::asObject() const { | |||||||
|   return JsonObject::invalid(); |   return JsonObject::invalid(); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonObject &JsonObject::createNestedObject(JsonObjectKey key) { | template <typename TString> | ||||||
|  | inline JsonObject &JsonObject::createNestedObject(const TString &key) { | ||||||
|   if (!_buffer) return JsonObject::invalid(); |   if (!_buffer) return JsonObject::invalid(); | ||||||
|   JsonObject &array = _buffer->createObject(); |   JsonObject &object = _buffer->createObject(); | ||||||
|   setNodeAt<const JsonVariant &>(key, array); |   set(key, object); | ||||||
|   return array; |   return object; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonObject &JsonArray::createNestedObject() { | inline JsonObject &JsonArray::createNestedObject() { | ||||||
|   | |||||||
| @@ -1,27 +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 "String.hpp" |  | ||||||
|  |  | ||||||
| namespace ArduinoJson { |  | ||||||
|  |  | ||||||
| // Represents a key in a JsonObject |  | ||||||
| class JsonObjectKey { |  | ||||||
|  public: |  | ||||||
|   JsonObjectKey(const char* key) : _value(key), _needs_copy(false) {} |  | ||||||
|   JsonObjectKey(const String& key) : _value(key.c_str()), _needs_copy(true) {} |  | ||||||
|  |  | ||||||
|   const char* c_str() const { return _value; } |  | ||||||
|   bool needs_copy() const { return _needs_copy; } |  | ||||||
|  |  | ||||||
|  private: |  | ||||||
|   const char* _value; |  | ||||||
|   bool _needs_copy; |  | ||||||
| }; |  | ||||||
| } |  | ||||||
| @@ -9,6 +9,7 @@ | |||||||
|  |  | ||||||
| #include "Configuration.hpp" | #include "Configuration.hpp" | ||||||
| #include "JsonVariantBase.hpp" | #include "JsonVariantBase.hpp" | ||||||
|  | #include "TypeTraits/ConstRefOrConstPtr.hpp" | ||||||
| #include "TypeTraits/EnableIf.hpp" | #include "TypeTraits/EnableIf.hpp" | ||||||
|  |  | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
| @@ -18,30 +19,27 @@ | |||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TString> | ||||||
| class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > { | class JsonObjectSubscript | ||||||
|  |     : public JsonVariantBase<JsonObjectSubscript<TString> > { | ||||||
|  |   // const String& | ||||||
|  |   // const std::string& | ||||||
|  |   // const char* | ||||||
|  |   typedef typename TypeTraits::ConstRefOrConstPtr<TString>::type TStringRef; | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   FORCE_INLINE JsonObjectSubscript(JsonObject& object, TKey key) |   FORCE_INLINE JsonObjectSubscript(JsonObject& object, TStringRef key) | ||||||
|       : _object(object), _key(key) {} |       : _object(object), _key(key) {} | ||||||
|  |  | ||||||
|   JsonObjectSubscript<TKey>& operator=(const JsonObjectSubscript<TKey>& src) { |   FORCE_INLINE JsonObjectSubscript<TString>& operator=( | ||||||
|     _object.set<const JsonVariant&>(_key, src); |       const JsonObjectSubscript<TString>& src) { | ||||||
|  |     _object.set(_key, src); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   typename TypeTraits::EnableIf<JsonObject::CanSet<T&>::value, |   FORCE_INLINE JsonObjectSubscript<TString>& operator=(const T& src) { | ||||||
|                                 JsonObjectSubscript<TKey> >::type& |     _object.set(_key, 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; |     return *this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -49,13 +47,9 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > { | |||||||
|     return _object.containsKey(_key); |     return _object.containsKey(_key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE operator JsonVariant() const { |  | ||||||
|     return _object.get(_key); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type as() const { |   FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type as() const { | ||||||
|     return _object.get<TValue>(_key); |     return _object.get<TValue, TStringRef>(_key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
| @@ -64,58 +58,39 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(TValue value) { |   FORCE_INLINE bool set(const TValue& value) { | ||||||
|     return _object.set<TValue>(_key, value); |     return _object.set(_key, value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(TValue value, uint8_t decimals) { |   FORCE_INLINE bool set(const TValue& value, uint8_t decimals) { | ||||||
|     return _object.set(_key, value, decimals); |     return _object.set(_key, value, decimals); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE JsonVariant get() { |  | ||||||
|     return _object.get(_key); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   JsonObject& _object; |   JsonObject& _object; | ||||||
|   TKey _key; |   TStringRef _key; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_STD_STREAM | #if ARDUINOJSON_ENABLE_STD_STREAM | ||||||
| inline std::ostream& operator<<( | template <typename TString> | ||||||
|     std::ostream& os, const JsonObjectSubscript<const String&>& source) { | inline std::ostream& operator<<(std::ostream& os, | ||||||
|   return source.printTo(os); |                                 const JsonObjectSubscript<TString>& source) { | ||||||
| } |  | ||||||
|  |  | ||||||
| inline std::ostream& operator<<( |  | ||||||
|     std::ostream& os, const JsonObjectSubscript<const char*>& source) { |  | ||||||
|   return source.printTo(os); |   return source.printTo(os); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| inline JsonObjectSubscript<const char*> JsonObject::operator[]( | template <typename TString> | ||||||
|     const char* key) { | inline JsonObjectSubscript<TString> JsonObject::operator[](const TString& key) { | ||||||
|   return JsonObjectSubscript<const char*>(*this, key); |   return JsonObjectSubscript<TString>(*this, key); | ||||||
| } |  | ||||||
|  |  | ||||||
| inline JsonObjectSubscript<const String&> JsonObject::operator[]( |  | ||||||
|     const String& key) { |  | ||||||
|   return JsonObjectSubscript<const String&>(*this, key); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TImplem> | template <typename TImplem> | ||||||
| inline const JsonObjectSubscript<const char*> JsonVariantBase<TImplem>:: | template <class TString> | ||||||
| operator[](const char* key) const { | inline const JsonObjectSubscript<TString> JsonVariantBase<TImplem>::operator[]( | ||||||
|  |     const TString& key) const { | ||||||
|   return asObject()[key]; |   return asObject()[key]; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TImplem> |  | ||||||
| inline const JsonObjectSubscript<const String&> JsonVariantBase<TImplem>:: |  | ||||||
| operator[](const String& key) const { |  | ||||||
|   return asObject()[key]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| }  // namespace ArduinoJson | }  // namespace ArduinoJson | ||||||
|  |  | ||||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||||
|   | |||||||
| @@ -7,7 +7,6 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "JsonObjectKey.hpp" |  | ||||||
| #include "JsonVariant.hpp" | #include "JsonVariant.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ | |||||||
|  |  | ||||||
| #include "Internals/JsonPrintable.hpp" | #include "Internals/JsonPrintable.hpp" | ||||||
| #include "Internals/JsonVariantContent.hpp" | #include "Internals/JsonVariantContent.hpp" | ||||||
|  | #include "Internals/JsonVariantDefault.hpp" | ||||||
| #include "Internals/JsonVariantType.hpp" | #include "Internals/JsonVariantType.hpp" | ||||||
| #include "JsonVariantBase.hpp" | #include "JsonVariantBase.hpp" | ||||||
| #include "RawJson.hpp" | #include "RawJson.hpp" | ||||||
| @@ -19,6 +20,8 @@ | |||||||
| #include "TypeTraits/IsFloatingPoint.hpp" | #include "TypeTraits/IsFloatingPoint.hpp" | ||||||
| #include "TypeTraits/IsIntegral.hpp" | #include "TypeTraits/IsIntegral.hpp" | ||||||
| #include "TypeTraits/IsSame.hpp" | #include "TypeTraits/IsSame.hpp" | ||||||
|  | #include "TypeTraits/IsSignedIntegral.hpp" | ||||||
|  | #include "TypeTraits/IsUnsignedIntegral.hpp" | ||||||
| #include "TypeTraits/RemoveConst.hpp" | #include "TypeTraits/RemoveConst.hpp" | ||||||
| #include "TypeTraits/RemoveReference.hpp" | #include "TypeTraits/RemoveReference.hpp" | ||||||
|  |  | ||||||
| @@ -40,9 +43,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|                                                    JsonWriter &); |                                                    JsonWriter &); | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   template <typename T> |  | ||||||
|   struct IsConstructibleFrom; |  | ||||||
|  |  | ||||||
|   // Creates an uninitialized JsonVariant |   // Creates an uninitialized JsonVariant | ||||||
|   JsonVariant() : _type(Internals::JSON_UNDEFINED) {} |   JsonVariant() : _type(Internals::JSON_UNDEFINED) {} | ||||||
|  |  | ||||||
| @@ -110,10 +110,14 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Create a JsonVariant containing a reference to an array. |   // Create a JsonVariant containing a reference to an array. | ||||||
|   JsonVariant(JsonArray &array); |   // CAUTION: we are lying about constness, because the array can be modified if | ||||||
|  |   // the variant is converted back to a JsonArray& | ||||||
|  |   JsonVariant(const JsonArray &array); | ||||||
|  |  | ||||||
|   // Create a JsonVariant containing a reference to an object. |   // Create a JsonVariant containing a reference to an object. | ||||||
|   JsonVariant(JsonObject &object); |   // CAUTION: we are lying about constness, because the object can be modified | ||||||
|  |   // if the variant is converted back to a JsonObject& | ||||||
|  |   JsonVariant(const JsonObject &object); | ||||||
|  |  | ||||||
|   // Get the variant as the specified type. |   // Get the variant as the specified type. | ||||||
|   // |   // | ||||||
| @@ -146,14 +150,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|     return static_cast<T>(asFloat()); |     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<const char*>() const; | ||||||
|   // const char* as<char*>() const; |   // const char* as<char*>() const; | ||||||
|   template <typename T> |   template <typename T> | ||||||
| @@ -164,6 +160,18 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|     return asString(); |     return asString(); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|  |   // std::string as<std::string>() const; | ||||||
|  |   // String as<String>() const; | ||||||
|  |   template <typename T> | ||||||
|  |   typename TypeTraits::EnableIf<Internals::StringFuncs<T>::has_append, T>::type | ||||||
|  |   as() const { | ||||||
|  |     const char *cstr = asString(); | ||||||
|  |     if (cstr) return T(cstr); | ||||||
|  |     T s; | ||||||
|  |     printTo(s); | ||||||
|  |     return s; | ||||||
|  |   } | ||||||
|  |   // | ||||||
|   // const bool as<bool>() const |   // const bool as<bool>() const | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value, |   const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value, | ||||||
| @@ -230,7 +238,8 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   // int as<int>() const; |   // int as<int>() const; | ||||||
|   // long as<long>() const; |   // long as<long>() const; | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value, |   const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value && | ||||||
|  |                                           !TypeTraits::IsSame<T, bool>::value, | ||||||
|                                       bool>::type |                                       bool>::type | ||||||
|   is() const { |   is() const { | ||||||
|     return isInteger(); |     return isInteger(); | ||||||
| @@ -296,12 +305,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|     return _type != Internals::JSON_UNDEFINED; |     return _type != Internals::JSON_UNDEFINED; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Value returned if the variant has an incompatible type |  | ||||||
|   template <typename T> |  | ||||||
|   static typename Internals::JsonVariantAs<T>::type defaultValue() { |  | ||||||
|     return T(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // DEPRECATED: use as<char*>() instead |   // DEPRECATED: use as<char*>() instead | ||||||
|   const char *asString() const; |   const char *asString() const; | ||||||
|  |  | ||||||
| @@ -317,7 +320,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   JsonVariant(T value, typename TypeTraits::EnableIf< |   JsonVariant(T value, typename TypeTraits::EnableIf< | ||||||
|                            TypeTraits::IsSame<T, char>::value>::type * = 0); |                            TypeTraits::IsSame<T, char>::value>::type * = 0); | ||||||
|  |  | ||||||
|   String toString() const; |  | ||||||
|   Internals::JsonFloat asFloat() const; |   Internals::JsonFloat asFloat() const; | ||||||
|   Internals::JsonInteger asInteger() const; |   Internals::JsonInteger asInteger() const; | ||||||
|   Internals::JsonUInt asUnsignedInteger() const; |   Internals::JsonUInt asUnsignedInteger() const; | ||||||
| @@ -350,27 +352,4 @@ 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, RawJson>::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; |  | ||||||
| }; |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -8,14 +8,14 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "Configuration.hpp" | #include "Configuration.hpp" | ||||||
| #include "JsonVariant.hpp" |  | ||||||
| #include "Internals/Parse.hpp" | #include "Internals/Parse.hpp" | ||||||
| #include "JsonArray.hpp" | #include "JsonArray.hpp" | ||||||
| #include "JsonObject.hpp" | #include "JsonObject.hpp" | ||||||
|  | #include "JsonVariant.hpp" | ||||||
|  |  | ||||||
| #include <string.h>  // for strcmp |  | ||||||
| #include <errno.h>   // for errno | #include <errno.h>   // for errno | ||||||
| #include <stdlib.h>  // for strtol, strtod | #include <stdlib.h>  // for strtol, strtod | ||||||
|  | #include <string.h>  // for strcmp | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|  |  | ||||||
| @@ -85,17 +85,6 @@ inline Internals::JsonFloat JsonVariant::asFloat() const { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| inline String JsonVariant::toString() const { |  | ||||||
|   using namespace Internals; |  | ||||||
|   String s; |  | ||||||
|   if ((_type == JSON_STRING || _type == JSON_UNPARSED) && |  | ||||||
|       _content.asString != NULL) |  | ||||||
|     s = _content.asString; |  | ||||||
|   else |  | ||||||
|     printTo(s); |  | ||||||
|   return s; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool JsonVariant::isBoolean() const { | inline bool JsonVariant::isBoolean() const { | ||||||
|   using namespace Internals; |   using namespace Internals; | ||||||
|   if (_type == JSON_BOOLEAN) return true; |   if (_type == JSON_BOOLEAN) return true; | ||||||
|   | |||||||
| @@ -8,7 +8,6 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "Internals/JsonVariantAs.hpp" | #include "Internals/JsonVariantAs.hpp" | ||||||
| #include "JsonObjectKey.hpp" |  | ||||||
| #include "Polyfills/attributes.hpp" | #include "Polyfills/attributes.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| @@ -77,10 +76,9 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> { | |||||||
|   // Returns the value associated with the specified key if the variant is |   // Returns the value associated with the specified key if the variant is | ||||||
|   // an object. |   // an object. | ||||||
|   // Return JsonVariant::invalid() if the variant is not an object. |   // Return JsonVariant::invalid() if the variant is not an object. | ||||||
|   FORCE_INLINE const JsonObjectSubscript<const char *> operator[]( |   template <typename TString> | ||||||
|       const char *key) const; |   FORCE_INLINE const JsonObjectSubscript<TString> operator[]( | ||||||
|   FORCE_INLINE const JsonObjectSubscript<const String &> operator[]( |       const TString &key) const; | ||||||
|       const String &key) const; |  | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   const TImpl *impl() const { |   const TImpl *impl() const { | ||||||
|   | |||||||
| @@ -13,7 +13,9 @@ namespace ArduinoJson { | |||||||
| class RawJson { | class RawJson { | ||||||
|  public: |  public: | ||||||
|   explicit RawJson(const char* str) : _str(str) {} |   explicit RawJson(const char* str) : _str(str) {} | ||||||
|   operator const char*() const { return _str; } |   operator const char*() const { | ||||||
|  |     return _str; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   const char* _str; |   const char* _str; | ||||||
|   | |||||||
| @@ -1,24 +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 "Configuration.hpp" |  | ||||||
|  |  | ||||||
| #if ARDUINOJSON_USE_ARDUINO_STRING |  | ||||||
|  |  | ||||||
| #include <WString.h> |  | ||||||
|  |  | ||||||
| #else |  | ||||||
|  |  | ||||||
| #include <string> |  | ||||||
|  |  | ||||||
| namespace ArduinoJson { |  | ||||||
| typedef std::string String; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
							
								
								
									
										31
									
								
								include/ArduinoJson/TypeTraits/ConstRefOrConstPtr.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								include/ArduinoJson/TypeTraits/ConstRefOrConstPtr.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | // 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 ConstRefOrConstPtr { | ||||||
|  |   typedef const T& type; | ||||||
|  | }; | ||||||
|  | template <typename T> | ||||||
|  | struct ConstRefOrConstPtr<T*> { | ||||||
|  |   typedef const T* type; | ||||||
|  | }; | ||||||
|  | template <typename T> | ||||||
|  | struct ConstRefOrConstPtr<T[]> { | ||||||
|  |   typedef const T* type; | ||||||
|  | }; | ||||||
|  | template <typename T, size_t N> | ||||||
|  | struct ConstRefOrConstPtr<T[N]> { | ||||||
|  |   typedef const T* type; | ||||||
|  | }; | ||||||
|  | } | ||||||
|  | } | ||||||
| @@ -7,7 +7,6 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "../Configuration.hpp" |  | ||||||
| #include "IsSame.hpp" | #include "IsSame.hpp" | ||||||
| #include "IsSignedIntegral.hpp" | #include "IsSignedIntegral.hpp" | ||||||
| #include "IsUnsignedIntegral.hpp" | #include "IsUnsignedIntegral.hpp" | ||||||
| @@ -20,7 +19,11 @@ template <typename T> | |||||||
| struct IsIntegral { | struct IsIntegral { | ||||||
|   static const bool value = TypeTraits::IsSignedIntegral<T>::value || |   static const bool value = TypeTraits::IsSignedIntegral<T>::value || | ||||||
|                             TypeTraits::IsUnsignedIntegral<T>::value || |                             TypeTraits::IsUnsignedIntegral<T>::value || | ||||||
|                             TypeTraits::IsSame<T, char>::value; |                             TypeTraits::IsSame<T, char>::value || | ||||||
|  |                             TypeTraits::IsSame<T, bool>::value; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct IsIntegral<const T> : IsIntegral<T> {}; | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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> | ||||||
|  |  | ||||||
| class DynamicJsonBuffer_Basic_Tests : public testing::Test { | class DynamicJsonBuffer_Basic_Tests : public testing::Test { | ||||||
|  protected: |  protected: | ||||||
| @@ -38,3 +38,16 @@ TEST_F(DynamicJsonBuffer_Basic_Tests, Alignment) { | |||||||
|     ASSERT_EQ(0, addr & mask); |     ASSERT_EQ(0, addr & mask); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | TEST_F(DynamicJsonBuffer_Basic_Tests, strdup) { | ||||||
|  |   char original[] = "hello"; | ||||||
|  |   char* copy = buffer.strdup(original); | ||||||
|  |   strcpy(original, "world"); | ||||||
|  |   ASSERT_STREQ("hello", copy); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_F(DynamicJsonBuffer_Basic_Tests, strdup_givenNull) { | ||||||
|  |   const char* original = NULL; | ||||||
|  |   char* copy = buffer.strdup(original); | ||||||
|  |   ASSERT_EQ(NULL, copy); | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								test/JsonObject_Get_Tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								test/JsonObject_Get_Tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | // Copyright Benoit Blanchon 2014-2016 | ||||||
|  | // MIT License | ||||||
|  | // | ||||||
|  | // Arduino JSON library | ||||||
|  | // https://github.com/bblanchon/ArduinoJson | ||||||
|  | // If you like this project, please add a star! | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <gtest/gtest.h> | ||||||
|  |  | ||||||
|  | class JsonObject_Get_Tests : public ::testing::Test { | ||||||
|  |  public: | ||||||
|  |   JsonObject_Get_Tests() : _object(_jsonBuffer.createObject()) {} | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   DynamicJsonBuffer _jsonBuffer; | ||||||
|  |   JsonObject& _object; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define TEST_(name) TEST_F(JsonObject_Get_Tests, name) | ||||||
|  |  | ||||||
|  | TEST_(GetConstCharPointer_GivenStringLiteral) { | ||||||
|  |   _object.set("hello", "world"); | ||||||
|  |   const char* value = _object.get<const char*>("hello"); | ||||||
|  |   EXPECT_STREQ("world", value); | ||||||
|  | } | ||||||
| @@ -5,11 +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> |  | ||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
|  | #include <gtest/gtest.h> | ||||||
|  |  | ||||||
| TEST(JsonObject_Invalid_Tests, SubscriptFails) { | TEST(JsonObject_Invalid_Tests, SubscriptFails) { | ||||||
|   ASSERT_FALSE(JsonObject::invalid()[0].success()); |   ASSERT_FALSE(JsonObject::invalid()["key"].success()); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(JsonObject_Invalid_Tests, AddFails) { | TEST(JsonObject_Invalid_Tests, AddFails) { | ||||||
|   | |||||||
| @@ -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> | ||||||
|  |  | ||||||
| class JsonObject_Set_Tests : public ::testing::Test { | class JsonObject_Set_Tests : public ::testing::Test { | ||||||
|  public: |  public: | ||||||
| @@ -112,7 +112,7 @@ TEST_(ShouldReturnTrue_WhenAllocationSucceeds) { | |||||||
|   StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 15> jsonBuffer; |   StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 15> jsonBuffer; | ||||||
|   JsonObject& obj = jsonBuffer.createObject(); |   JsonObject& obj = jsonBuffer.createObject(); | ||||||
|  |  | ||||||
|   bool result = obj.set(String("hello"), String("world")); |   bool result = obj.set(std::string("hello"), std::string("world")); | ||||||
|  |  | ||||||
|   ASSERT_TRUE(result); |   ASSERT_TRUE(result); | ||||||
| } | } | ||||||
| @@ -121,7 +121,7 @@ TEST_(ShouldReturnFalse_WhenAllocationFails) { | |||||||
|   StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 10> jsonBuffer; |   StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 10> jsonBuffer; | ||||||
|   JsonObject& obj = jsonBuffer.createObject(); |   JsonObject& obj = jsonBuffer.createObject(); | ||||||
|  |  | ||||||
|   bool result = obj.set(String("hello"), String("world")); |   bool result = obj.set(std::string("hello"), std::string("world")); | ||||||
|  |  | ||||||
|   ASSERT_FALSE(result); |   ASSERT_FALSE(result); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ TEST(JsonVariant_As_Tests, DoubleAsCstr) { | |||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, DoubleAsString) { | TEST(JsonVariant_As_Tests, DoubleAsString) { | ||||||
|   JsonVariant variant = 4.2; |   JsonVariant variant = 4.2; | ||||||
|   ASSERT_EQ(String("4.20"), variant.as<String>()); |   ASSERT_EQ(std::string("4.20"), variant.as<std::string>()); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, DoubleAsLong) { | TEST(JsonVariant_As_Tests, DoubleAsLong) { | ||||||
| @@ -64,7 +64,7 @@ TEST(JsonVariant_As_Tests, FalseAsLong) { | |||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, FalseAsString) { | TEST(JsonVariant_As_Tests, FalseAsString) { | ||||||
|   JsonVariant variant = false; |   JsonVariant variant = false; | ||||||
|   ASSERT_EQ(String("false"), variant.as<String>()); |   ASSERT_EQ(std::string("false"), variant.as<std::string>()); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, TrueAsBool) { | TEST(JsonVariant_As_Tests, TrueAsBool) { | ||||||
| @@ -84,7 +84,7 @@ TEST(JsonVariant_As_Tests, TrueAsLong) { | |||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, TrueAsString) { | TEST(JsonVariant_As_Tests, TrueAsString) { | ||||||
|   JsonVariant variant = true; |   JsonVariant variant = true; | ||||||
|   ASSERT_EQ(String("true"), variant.as<String>()); |   ASSERT_EQ(std::string("true"), variant.as<std::string>()); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, LongAsBool) { | TEST(JsonVariant_As_Tests, LongAsBool) { | ||||||
| @@ -109,7 +109,7 @@ TEST(JsonVariant_As_Tests, NegativeLongAsDouble) { | |||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, LongAsString) { | TEST(JsonVariant_As_Tests, LongAsString) { | ||||||
|   JsonVariant variant = 42L; |   JsonVariant variant = 42L; | ||||||
|   ASSERT_EQ(String("42"), variant.as<String>()); |   ASSERT_EQ(std::string("42"), variant.as<std::string>()); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, LongZeroAsDouble) { | TEST(JsonVariant_As_Tests, LongZeroAsDouble) { | ||||||
| @@ -134,7 +134,7 @@ TEST(JsonVariant_As_Tests, NullAsLong) { | |||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, NullAsString) { | TEST(JsonVariant_As_Tests, NullAsString) { | ||||||
|   JsonVariant variant = null; |   JsonVariant variant = null; | ||||||
|   ASSERT_EQ(String("null"), variant.as<String>()); |   ASSERT_EQ(std::string("null"), variant.as<std::string>()); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, NumberStringAsBool) { | TEST(JsonVariant_As_Tests, NumberStringAsBool) { | ||||||
| @@ -181,7 +181,7 @@ TEST(JsonVariant_As_Tests, RandomStringAsCharPtr) { | |||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, RandomStringAsString) { | TEST(JsonVariant_As_Tests, RandomStringAsString) { | ||||||
|   JsonVariant variant = "hello"; |   JsonVariant variant = "hello"; | ||||||
|   ASSERT_EQ(String("hello"), variant.as<String>()); |   ASSERT_EQ(std::string("hello"), variant.as<std::string>()); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, TrueStringAsBool) { | TEST(JsonVariant_As_Tests, TrueStringAsBool) { | ||||||
| @@ -201,7 +201,7 @@ TEST(JsonVariant_As_Tests, ObjectAsString) { | |||||||
|   obj["key"] = "value"; |   obj["key"] = "value"; | ||||||
|  |  | ||||||
|   JsonVariant variant = obj; |   JsonVariant variant = obj; | ||||||
|   ASSERT_EQ(String("{\"key\":\"value\"}"), variant.as<String>()); |   ASSERT_EQ(std::string("{\"key\":\"value\"}"), variant.as<std::string>()); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, ArrayAsString) { | TEST(JsonVariant_As_Tests, ArrayAsString) { | ||||||
| @@ -212,7 +212,7 @@ TEST(JsonVariant_As_Tests, ArrayAsString) { | |||||||
|   arr.add(2); |   arr.add(2); | ||||||
|  |  | ||||||
|   JsonVariant variant = arr; |   JsonVariant variant = arr; | ||||||
|   ASSERT_EQ(String("[4,2]"), variant.as<String>()); |   ASSERT_EQ(std::string("[4,2]"), variant.as<std::string>()); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(JsonVariant_As_Tests, ArrayAsJsonArray) { | TEST(JsonVariant_As_Tests, ArrayAsJsonArray) { | ||||||
|   | |||||||
| @@ -5,12 +5,12 @@ | |||||||
| // 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> | ||||||
| 
 | 
 | ||||||
| class ArduinoStringTests : public ::testing::Test { | class StringTests : public ::testing::Test { | ||||||
|  protected: |  protected: | ||||||
|   static void eraseString(String &str) { |   static void eraseString(std::string &str) { | ||||||
|     char *p = const_cast<char *>(str.c_str()); |     char *p = const_cast<char *>(str.c_str()); | ||||||
|     while (*p) *p++ = '*'; |     while (*p) *p++ = '*'; | ||||||
|   } |   } | ||||||
| @@ -18,100 +18,100 @@ class ArduinoStringTests : public ::testing::Test { | |||||||
|   DynamicJsonBuffer _jsonBuffer; |   DynamicJsonBuffer _jsonBuffer; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonBuffer_ParseArray) { | TEST_F(StringTests, JsonBuffer_ParseArray) { | ||||||
|   String json("[\"hello\"]"); |   std::string json("[\"hello\"]"); | ||||||
|   JsonArray &array = _jsonBuffer.parseArray(json); |   JsonArray &array = _jsonBuffer.parseArray(json); | ||||||
|   eraseString(json); |   eraseString(json); | ||||||
|   ASSERT_TRUE(array.success()); |   ASSERT_TRUE(array.success()); | ||||||
|   ASSERT_STREQ("hello", array[0]); |   ASSERT_STREQ("hello", array[0]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonBuffer_ParseObject) { | TEST_F(StringTests, JsonBuffer_ParseObject) { | ||||||
|   String json("{\"hello\":\"world\"}"); |   std::string json("{\"hello\":\"world\"}"); | ||||||
|   JsonObject &object = _jsonBuffer.parseObject(json); |   JsonObject &object = _jsonBuffer.parseObject(json); | ||||||
|   eraseString(json); |   eraseString(json); | ||||||
|   ASSERT_TRUE(object.success()); |   ASSERT_TRUE(object.success()); | ||||||
|   ASSERT_STREQ("world", object["hello"]); |   ASSERT_STREQ("world", object["hello"]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_Subscript) { | TEST_F(StringTests, JsonObject_Subscript) { | ||||||
|   char json[] = "{\"key\":\"value\"}"; |   char json[] = "{\"key\":\"value\"}"; | ||||||
|   JsonObject &object = _jsonBuffer.parseObject(json); |   JsonObject &object = _jsonBuffer.parseObject(json); | ||||||
|   ASSERT_STREQ("value", object[String("key")]); |   ASSERT_STREQ("value", object[std::string("key")]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_ConstSubscript) { | TEST_F(StringTests, JsonObject_ConstSubscript) { | ||||||
|   char json[] = "{\"key\":\"value\"}"; |   char json[] = "{\"key\":\"value\"}"; | ||||||
|   const JsonObject &object = _jsonBuffer.parseObject(json); |   const JsonObject &object = _jsonBuffer.parseObject(json); | ||||||
|   ASSERT_STREQ("value", object[String("key")]); |   ASSERT_STREQ("value", object[std::string("key")]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_SetKey) { | TEST_F(StringTests, JsonObject_SetKey) { | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   String key("hello"); |   std::string key("hello"); | ||||||
|   object.set(key, "world"); |   object.set(key, "world"); | ||||||
|   eraseString(key); |   eraseString(key); | ||||||
|   ASSERT_STREQ("world", object["hello"]); |   ASSERT_STREQ("world", object["hello"]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_SetValue) { | TEST_F(StringTests, JsonObject_SetValue) { | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   String value("world"); |   std::string value("world"); | ||||||
|   object.set("hello", value); |   object.set("hello", value); | ||||||
|   eraseString(value); |   eraseString(value); | ||||||
|   ASSERT_STREQ("world", object["hello"]); |   ASSERT_STREQ("world", object["hello"]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_SetKeyValue) { | TEST_F(StringTests, JsonObject_SetKeyValue) { | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   String key("hello"); |   std::string key("hello"); | ||||||
|   String value("world"); |   std::string value("world"); | ||||||
|   object.set(key, value); |   object.set(key, value); | ||||||
|   eraseString(key); |   eraseString(key); | ||||||
|   eraseString(value); |   eraseString(value); | ||||||
|   ASSERT_STREQ("world", object["hello"]); |   ASSERT_STREQ("world", object["hello"]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_SetToArraySubscript) { | TEST_F(StringTests, JsonObject_SetToArraySubscript) { | ||||||
|   JsonArray &arr = _jsonBuffer.createArray(); |   JsonArray &arr = _jsonBuffer.createArray(); | ||||||
|   arr.add("world"); |   arr.add("world"); | ||||||
| 
 | 
 | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   object.set(String("hello"), arr[0]); |   object.set(std::string("hello"), arr[0]); | ||||||
| 
 | 
 | ||||||
|   ASSERT_STREQ("world", object["hello"]); |   ASSERT_STREQ("world", object["hello"]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_SetToObjectSubscript) { | TEST_F(StringTests, JsonObject_SetToObjectSubscript) { | ||||||
|   JsonObject &arr = _jsonBuffer.createObject(); |   JsonObject &arr = _jsonBuffer.createObject(); | ||||||
|   arr.set("x", "world"); |   arr.set("x", "world"); | ||||||
| 
 | 
 | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   object.set(String("hello"), arr["x"]); |   object.set(std::string("hello"), arr["x"]); | ||||||
| 
 | 
 | ||||||
|   ASSERT_STREQ("world", object["hello"]); |   ASSERT_STREQ("world", object["hello"]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_Get) { | TEST_F(StringTests, JsonObject_Get) { | ||||||
|   char json[] = "{\"key\":\"value\"}"; |   char json[] = "{\"key\":\"value\"}"; | ||||||
|   const JsonObject &object = _jsonBuffer.parseObject(json); |   const JsonObject &object = _jsonBuffer.parseObject(json); | ||||||
|   ASSERT_STREQ("value", object.get(String("key"))); |   ASSERT_STREQ("value", object.get<const char *>(std::string("key"))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_GetT) { | TEST_F(StringTests, JsonObject_GetT) { | ||||||
|   char json[] = "{\"key\":\"value\"}"; |   char json[] = "{\"key\":\"value\"}"; | ||||||
|   const JsonObject &object = _jsonBuffer.parseObject(json); |   const JsonObject &object = _jsonBuffer.parseObject(json); | ||||||
|   ASSERT_STREQ("value", object.get<const char *>(String("key"))); |   ASSERT_STREQ("value", object.get<const char *>(std::string("key"))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_IsT) { | TEST_F(StringTests, JsonObject_IsT) { | ||||||
|   char json[] = "{\"key\":\"value\"}"; |   char json[] = "{\"key\":\"value\"}"; | ||||||
|   const JsonObject &object = _jsonBuffer.parseObject(json); |   const JsonObject &object = _jsonBuffer.parseObject(json); | ||||||
|   ASSERT_TRUE(object.is<const char *>(String("key"))); |   ASSERT_TRUE(object.is<const char *>(std::string("key"))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_CreateNestedObject) { | TEST_F(StringTests, JsonObject_CreateNestedObject) { | ||||||
|   String key = "key"; |   std::string key = "key"; | ||||||
|   char json[64]; |   char json[64]; | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   object.createNestedObject(key); |   object.createNestedObject(key); | ||||||
| @@ -120,8 +120,8 @@ TEST_F(ArduinoStringTests, JsonObject_CreateNestedObject) { | |||||||
|   ASSERT_STREQ("{\"key\":{}}", json); |   ASSERT_STREQ("{\"key\":{}}", json); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_CreateNestedArray) { | TEST_F(StringTests, JsonObject_CreateNestedArray) { | ||||||
|   String key = "key"; |   std::string key = "key"; | ||||||
|   char json[64]; |   char json[64]; | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   object.createNestedArray(key); |   object.createNestedArray(key); | ||||||
| @@ -130,99 +130,99 @@ TEST_F(ArduinoStringTests, JsonObject_CreateNestedArray) { | |||||||
|   ASSERT_STREQ("{\"key\":[]}", json); |   ASSERT_STREQ("{\"key\":[]}", json); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_ContainsKey) { | TEST_F(StringTests, JsonObject_ContainsKey) { | ||||||
|   char json[] = "{\"key\":\"value\"}"; |   char json[] = "{\"key\":\"value\"}"; | ||||||
|   const JsonObject &object = _jsonBuffer.parseObject(json); |   const JsonObject &object = _jsonBuffer.parseObject(json); | ||||||
|   ASSERT_TRUE(object.containsKey(String("key"))); |   ASSERT_TRUE(object.containsKey(std::string("key"))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_Remove) { | TEST_F(StringTests, JsonObject_Remove) { | ||||||
|   char json[] = "{\"key\":\"value\"}"; |   char json[] = "{\"key\":\"value\"}"; | ||||||
|   JsonObject &object = _jsonBuffer.parseObject(json); |   JsonObject &object = _jsonBuffer.parseObject(json); | ||||||
|   ASSERT_EQ(1, object.size()); |   ASSERT_EQ(1, object.size()); | ||||||
|   object.remove(String("key")); |   object.remove(std::string("key")); | ||||||
|   ASSERT_EQ(0, object.size()); |   ASSERT_EQ(0, object.size()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObjectSubscript_SetKey) { | TEST_F(StringTests, JsonObjectSubscript_SetKey) { | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   String key("hello"); |   std::string key("hello"); | ||||||
|   object[key] = "world"; |   object[key] = "world"; | ||||||
|   eraseString(key); |   eraseString(key); | ||||||
|   ASSERT_STREQ("world", object["hello"]); |   ASSERT_STREQ("world", object["hello"]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObjectSubscript_SetValue) { | TEST_F(StringTests, JsonObjectSubscript_SetValue) { | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   String value("world"); |   std::string value("world"); | ||||||
|   object["hello"] = value; |   object["hello"] = value; | ||||||
|   eraseString(value); |   eraseString(value); | ||||||
|   ASSERT_STREQ("world", object["hello"]); |   ASSERT_STREQ("world", object["hello"]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonArray_Add) { | TEST_F(StringTests, JsonArray_Add) { | ||||||
|   JsonArray &array = _jsonBuffer.createArray(); |   JsonArray &array = _jsonBuffer.createArray(); | ||||||
|   String value("hello"); |   std::string value("hello"); | ||||||
|   array.add(value); |   array.add(value); | ||||||
|   eraseString(value); |   eraseString(value); | ||||||
|   ASSERT_STREQ("hello", array[0]); |   ASSERT_STREQ("hello", array[0]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonArray_Set) { | TEST_F(StringTests, JsonArray_Set) { | ||||||
|   JsonArray &array = _jsonBuffer.createArray(); |   JsonArray &array = _jsonBuffer.createArray(); | ||||||
|   String value("world"); |   std::string value("world"); | ||||||
|   array.add("hello"); |   array.add("hello"); | ||||||
|   array.set(0, value); |   array.set(0, value); | ||||||
|   eraseString(value); |   eraseString(value); | ||||||
|   ASSERT_STREQ("world", array[0]); |   ASSERT_STREQ("world", array[0]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonArraySubscript) { | TEST_F(StringTests, JsonArraySubscript) { | ||||||
|   JsonArray &array = _jsonBuffer.createArray(); |   JsonArray &array = _jsonBuffer.createArray(); | ||||||
|   String value("world"); |   std::string value("world"); | ||||||
|   array.add("hello"); |   array.add("hello"); | ||||||
|   array[0] = value; |   array[0] = value; | ||||||
|   eraseString(value); |   eraseString(value); | ||||||
|   ASSERT_STREQ("world", array[0]); |   ASSERT_STREQ("world", array[0]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonArray_PrintTo) { | TEST_F(StringTests, JsonArray_PrintTo) { | ||||||
|   JsonArray &array = _jsonBuffer.createArray(); |   JsonArray &array = _jsonBuffer.createArray(); | ||||||
|   array.add(4); |   array.add(4); | ||||||
|   array.add(2); |   array.add(2); | ||||||
|   String json; |   std::string json; | ||||||
|   array.printTo(json); |   array.printTo(json); | ||||||
|   ASSERT_EQ(String("[4,2]"), json); |   ASSERT_EQ(std::string("[4,2]"), json); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonArray_PrettyPrintTo) { | TEST_F(StringTests, JsonArray_PrettyPrintTo) { | ||||||
|   JsonArray &array = _jsonBuffer.createArray(); |   JsonArray &array = _jsonBuffer.createArray(); | ||||||
|   array.add(4); |   array.add(4); | ||||||
|   array.add(2); |   array.add(2); | ||||||
|   String json; |   std::string json; | ||||||
|   array.prettyPrintTo(json); |   array.prettyPrintTo(json); | ||||||
|   ASSERT_EQ(String("[\r\n  4,\r\n  2\r\n]"), json); |   ASSERT_EQ(std::string("[\r\n  4,\r\n  2\r\n]"), json); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_PrintTo) { | TEST_F(StringTests, JsonObject_PrintTo) { | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   object["key"] = "value"; |   object["key"] = "value"; | ||||||
|   String json; |   std::string json; | ||||||
|   object.printTo(json); |   object.printTo(json); | ||||||
|   ASSERT_EQ(String("{\"key\":\"value\"}"), json); |   ASSERT_EQ(std::string("{\"key\":\"value\"}"), json); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonObject_PrettyPrintTo) { | TEST_F(StringTests, JsonObject_PrettyPrintTo) { | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   object["key"] = "value"; |   object["key"] = "value"; | ||||||
|   String json; |   std::string json; | ||||||
|   object.prettyPrintTo(json); |   object.prettyPrintTo(json); | ||||||
|   ASSERT_EQ(String("{\r\n  \"key\": \"value\"\r\n}"), json); |   ASSERT_EQ(std::string("{\r\n  \"key\": \"value\"\r\n}"), json); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonBuffer_GrowWhenAddingNewKey) { | TEST_F(StringTests, JsonBuffer_GrowWhenAddingNewKey) { | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   String key1("hello"), key2("world"); |   std::string key1("hello"), key2("world"); | ||||||
| 
 | 
 | ||||||
|   object[key1] = 1; |   object[key1] = 1; | ||||||
|   size_t sizeBefore = _jsonBuffer.size(); |   size_t sizeBefore = _jsonBuffer.size(); | ||||||
| @@ -232,9 +232,9 @@ TEST_F(ArduinoStringTests, JsonBuffer_GrowWhenAddingNewKey) { | |||||||
|   ASSERT_GT(sizeAfter - sizeBefore, key2.size()); |   ASSERT_GT(sizeAfter - sizeBefore, key2.size()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(ArduinoStringTests, JsonBuffer_DontGrowWhenReusingKey) { | TEST_F(StringTests, JsonBuffer_DontGrowWhenReusingKey) { | ||||||
|   JsonObject &object = _jsonBuffer.createObject(); |   JsonObject &object = _jsonBuffer.createObject(); | ||||||
|   String key("hello"); |   std::string key("hello"); | ||||||
| 
 | 
 | ||||||
|   object[key] = 1; |   object[key] = 1; | ||||||
|   size_t sizeBefore = _jsonBuffer.size(); |   size_t sizeBefore = _jsonBuffer.size(); | ||||||
| @@ -243,3 +243,10 @@ TEST_F(ArduinoStringTests, JsonBuffer_DontGrowWhenReusingKey) { | |||||||
| 
 | 
 | ||||||
|   ASSERT_EQ(sizeBefore, sizeAfter); |   ASSERT_EQ(sizeBefore, sizeAfter); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | TEST_F(StringTests, JsonBuffer_strdup) { | ||||||
|  |   std::string original("hello"); | ||||||
|  |   char *copy = _jsonBuffer.strdup(original); | ||||||
|  |   original[0] = 'w'; | ||||||
|  |   ASSERT_STREQ("hello", copy); | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user