mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 08:42:39 +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 | ||||
| ---- | ||||
|  | ||||
| * 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) | ||||
|  | ||||
| **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 | ||||
| ------ | ||||
|  | ||||
|   | ||||
							
								
								
									
										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 | ||||
| #endif | ||||
|  | ||||
| // arduino has its own implementation of String to replace std::string | ||||
| #ifndef ARDUINOJSON_USE_ARDUINO_STRING | ||||
| #define ARDUINOJSON_USE_ARDUINO_STRING 1 | ||||
| // Arduino has its own implementation of String to replace std::string | ||||
| #ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING | ||||
| #define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 | ||||
| #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 | ||||
| #define ARDUINOJSON_ENABLE_STD_STREAM 0 | ||||
| #endif | ||||
| @@ -73,8 +78,13 @@ | ||||
| #endif | ||||
|  | ||||
| // on a computer, we can use std::string | ||||
| #ifndef ARDUINOJSON_USE_ARDUINO_STRING | ||||
| #define ARDUINOJSON_USE_ARDUINO_STRING 0 | ||||
| #ifndef ARDUINOJSON_ENABLE_STD_STRING | ||||
| #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 | ||||
|  | ||||
| // on a computer, we can assume that the STL is there | ||||
|   | ||||
| @@ -8,26 +8,26 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "../Print.hpp" | ||||
| #include "../String.hpp" | ||||
| #include "StringFuncs.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| namespace Internals { | ||||
|  | ||||
| // A Print implementation that allows to write in a String | ||||
| template <typename TString> | ||||
| class DynamicStringBuilder : public Print { | ||||
|  public: | ||||
|   DynamicStringBuilder(String &str) : _str(str) {} | ||||
|   DynamicStringBuilder(TString &str) : _str(str) {} | ||||
|  | ||||
|   virtual size_t write(uint8_t c) { | ||||
|     // Need to cast to char, otherwise String will print a number (issue #120) | ||||
|     _str += static_cast<char>(c); | ||||
|     StringFuncs<TString>::append(_str, static_cast<char>(c)); | ||||
|     return 1; | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   DynamicStringBuilder &operator=(const DynamicStringBuilder &); | ||||
|  | ||||
|   String &_str; | ||||
|   TString &_str; | ||||
| }; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "../Configuration.hpp" | ||||
| #include "../TypeTraits/EnableIf.hpp" | ||||
| #include "DummyPrint.hpp" | ||||
| #include "DynamicStringBuilder.hpp" | ||||
| #include "IndentedPrint.hpp" | ||||
| @@ -49,8 +50,10 @@ class JsonPrintable { | ||||
|     return printTo(sb); | ||||
|   } | ||||
|  | ||||
|   size_t printTo(String &str) const { | ||||
|     DynamicStringBuilder sb(str); | ||||
|   template <typename TString> | ||||
|   typename TypeTraits::EnableIf<StringFuncs<TString>::has_append, size_t>::type | ||||
|   printTo(TString &str) const { | ||||
|     DynamicStringBuilder<TString> sb(str); | ||||
|     return printTo(sb); | ||||
|   } | ||||
|  | ||||
| @@ -69,8 +72,10 @@ class JsonPrintable { | ||||
|     return prettyPrintTo(indentedPrint); | ||||
|   } | ||||
|  | ||||
|   size_t prettyPrintTo(String &str) const { | ||||
|     DynamicStringBuilder sb(str); | ||||
|   template <typename TString> | ||||
|   typename TypeTraits::EnableIf<StringFuncs<TString>::has_append, size_t>::type | ||||
|   prettyPrintTo(TString &str) const { | ||||
|     DynamicStringBuilder<TString> sb(str); | ||||
|     return prettyPrintTo(sb); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -8,17 +8,19 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| namespace ArduinoJson { | ||||
| namespace TypeTraits { | ||||
| namespace Internals { | ||||
| 
 | ||||
| // A meta-function that returns true if T is a reference
 | ||||
| template <typename T> | ||||
| struct IsReference { | ||||
|   static const bool value = false; | ||||
| struct JsonVariantDefault { | ||||
|   static T get() { | ||||
|     return T(); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct IsReference<T&> { | ||||
|   static const bool value = true; | ||||
| }; | ||||
| struct JsonVariantDefault<const T> : JsonVariantDefault<T> {}; | ||||
| 
 | ||||
| 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/List.hpp" | ||||
| #include "Internals/ReferenceType.hpp" | ||||
| #include "Internals/StringFuncs.hpp" | ||||
| #include "Internals/ValueSetter.hpp" | ||||
| #include "JsonVariant.hpp" | ||||
| #include "TypeTraits/ConstRefOrConstPtr.hpp" | ||||
| #include "TypeTraits/EnableIf.hpp" | ||||
| #include "TypeTraits/IsFloatingPoint.hpp" | ||||
| #include "TypeTraits/IsReference.hpp" | ||||
| #include "TypeTraits/IsSame.hpp" | ||||
|  | ||||
| // Returns the size (in bytes) of an array with n elements. | ||||
| @@ -40,15 +42,6 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|                   public Internals::List<JsonVariant>, | ||||
|                   public Internals::JsonBufferAllocated { | ||||
|  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. | ||||
|   // You should not call this constructor directly. | ||||
|   // Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray(). | ||||
| @@ -57,7 +50,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|  | ||||
|   // Gets the value at the specified index | ||||
|   JsonVariant operator[](size_t index) const { | ||||
|     return get(index); | ||||
|     return get<JsonVariant>(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(double value); | ||||
|   // bool add(const char*); | ||||
|   template <typename T> | ||||
|   bool add( | ||||
|       T value, | ||||
|       typename TypeTraits::EnableIf< | ||||
|           CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) { | ||||
|     return addNode<T>(value); | ||||
|   } | ||||
|   // bool add(const char[]); | ||||
|   // bool add(const char[N]); | ||||
|   // bool add(RawJson); | ||||
|   // bool add(const std::string&) | ||||
|   // bool add(const String&) | ||||
|   // bool add(const JsonVariant&); | ||||
|   // bool add(JsonArray&); | ||||
|   // bool add(JsonObject&); | ||||
|   template <typename T> | ||||
|   bool add(const T &value, | ||||
|            typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) { | ||||
|     return addNode<T &>(const_cast<T &>(value)); | ||||
|   bool add(const T &value) { | ||||
|     // reduce the number of template function instanciation to reduce code size | ||||
|     return addNodeImpl<typename TypeTraits::ConstRefOrConstPtr<T>::type>(value); | ||||
|   } | ||||
|   // bool add(float value, uint8_t decimals); | ||||
|   // bool add(double value, uint8_t decimals); | ||||
|   template <typename T> | ||||
|   bool add(T value, uint8_t decimals, | ||||
|            typename TypeTraits::EnableIf< | ||||
|                TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { | ||||
|     return addNode<JsonVariant>(JsonVariant(value, decimals)); | ||||
|   bool add(T value, uint8_t decimals) { | ||||
|     return add(JsonVariant(value, decimals)); | ||||
|   } | ||||
|  | ||||
|   // 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, int value); | ||||
|   // bool set(size_t index, short value); | ||||
|   template <typename T> | ||||
|   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 std::string&) | ||||
|   // bool set(size_t index, const String&) | ||||
|   // bool set(size_t index, const JsonVariant&); | ||||
|   // bool set(size_t index, JsonArray&); | ||||
|   // bool set(size_t index, JsonObject&); | ||||
|   template <typename T> | ||||
|   bool set(size_t index, const T &value, | ||||
|            typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) { | ||||
|     return setNodeAt<T &>(index, const_cast<T &>(value)); | ||||
|   bool set(size_t index, const T &value) { | ||||
|     // reduce the number of template function instanciation to reduce code size | ||||
|     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, double value, uint8_t decimals = 2); | ||||
|   template <typename T> | ||||
|   bool set(size_t index, T value, uint8_t decimals, | ||||
|            typename TypeTraits::EnableIf< | ||||
|                TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { | ||||
|     return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals)); | ||||
|   } | ||||
|  | ||||
|   // Gets the value at the specified index. | ||||
|   JsonVariant get(size_t index) const { | ||||
|     node_type *node = getNodeAt(index); | ||||
|     return node ? node->content : JsonVariant(); | ||||
|   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value, | ||||
|                                 bool>::type | ||||
|   set(size_t index, T value, uint8_t decimals) { | ||||
|     return set(index, JsonVariant(value, decimals)); | ||||
|   } | ||||
|  | ||||
|   // Gets the value at the specified index. | ||||
|   template <typename T> | ||||
|   typename Internals::JsonVariantAs<T>::type get(size_t index) const { | ||||
|     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. | ||||
| @@ -172,7 +151,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|  | ||||
|   // Imports a 1D array | ||||
|   template <typename T, size_t N> | ||||
|   bool copyFrom(T(&array)[N]) { | ||||
|   bool copyFrom(T (&array)[N]) { | ||||
|     return copyFrom(array, N); | ||||
|   } | ||||
|  | ||||
| @@ -188,7 +167,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|  | ||||
|   // Imports a 2D array | ||||
|   template <typename T, size_t N1, size_t N2> | ||||
|   bool copyFrom(T(&array)[N1][N2]) { | ||||
|   bool copyFrom(T (&array)[N1][N2]) { | ||||
|     bool ok = true; | ||||
|     for (size_t i = 0; i < N1; i++) { | ||||
|       JsonArray &nestedArray = createNestedArray(); | ||||
| @@ -201,7 +180,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|  | ||||
|   // Exports a 1D array | ||||
|   template <typename T, size_t N> | ||||
|   size_t copyTo(T(&array)[N]) const { | ||||
|   size_t copyTo(T (&array)[N]) const { | ||||
|     return copyTo(array, N); | ||||
|   } | ||||
|  | ||||
| @@ -216,7 +195,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|  | ||||
|   // Exports a 2D array | ||||
|   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; | ||||
|     for (const_iterator it = begin(); it != end() && i < N1; ++it) { | ||||
|       it->asArray().copyTo(array[i++]); | ||||
| @@ -230,22 +209,22 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | ||||
|     return node; | ||||
|   } | ||||
|  | ||||
|   template <typename TValue> | ||||
|   bool setNodeAt(size_t index, TValue value) { | ||||
|   template <typename TValueRef> | ||||
|   bool setNodeAt(size_t index, TValueRef value) { | ||||
|     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> | ||||
|   bool addNode(TValue value) { | ||||
|   template <typename TValueRef> | ||||
|   bool addNodeImpl(TValueRef value) { | ||||
|     node_type *node = addNewNode(); | ||||
|     return node != NULL && setNodeValue<TValue>(node, value); | ||||
|   } | ||||
|     if (!node) return false; | ||||
|  | ||||
|   template <typename T> | ||||
|   bool setNodeValue(node_type *node, T value) { | ||||
|     node->content = value; | ||||
|     return true; | ||||
|     return Internals::ValueSetter<TValueRef>::set(_buffer, node->content, | ||||
|                                                   value); | ||||
|   } | ||||
| }; | ||||
| } | ||||
|   | ||||
| @@ -13,50 +13,31 @@ | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|  | ||||
| inline JsonVariant::JsonVariant(JsonArray &array) { | ||||
| inline JsonVariant::JsonVariant(const JsonArray &array) { | ||||
|   if (array.success()) { | ||||
|     _type = Internals::JSON_ARRAY; | ||||
|     _content.asArray = &array; | ||||
|     _content.asArray = const_cast<JsonArray *>(&array); | ||||
|   } else { | ||||
|     _type = Internals::JSON_UNDEFINED; | ||||
|   } | ||||
| } | ||||
|  | ||||
| inline JsonVariant::JsonVariant(JsonObject &object) { | ||||
| inline JsonVariant::JsonVariant(const JsonObject &object) { | ||||
|   if (object.success()) { | ||||
|     _type = Internals::JSON_OBJECT; | ||||
|     _content.asObject = &object; | ||||
|     _content.asObject = const_cast<JsonObject *>(&object); | ||||
|   } else { | ||||
|     _type = Internals::JSON_UNDEFINED; | ||||
|   } | ||||
| } | ||||
|  | ||||
| namespace Internals { | ||||
| template <> | ||||
| inline bool JsonArray::setNodeValue(node_type *node, String &value) { | ||||
|   const char *copy = _buffer->strdup(value); | ||||
|   if (!copy) return false; | ||||
|   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(); | ||||
| struct JsonVariantDefault<JsonArray> { | ||||
|   static JsonArray &get() { | ||||
|     return JsonArray::invalid(); | ||||
|   } | ||||
| }; | ||||
| } | ||||
|  | ||||
| inline JsonArray &JsonVariant::asArray() const { | ||||
| @@ -71,10 +52,11 @@ inline JsonArray &JsonArray::createNestedArray() { | ||||
|   return array; | ||||
| } | ||||
|  | ||||
| inline JsonArray &JsonObject::createNestedArray(JsonObjectKey key) { | ||||
| template <typename TString> | ||||
| inline JsonArray &JsonObject::createNestedArray(const TString &key) { | ||||
|   if (!_buffer) return JsonArray::invalid(); | ||||
|   JsonArray &array = _buffer->createArray(); | ||||
|   setNodeAt<const JsonVariant &>(key, array); | ||||
|   set(key, array); | ||||
|   return array; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -21,24 +21,14 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | ||||
|   FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index) | ||||
|       : _array(array), _index(index) {} | ||||
|  | ||||
|   JsonArraySubscript& operator=(const JsonArraySubscript& src) { | ||||
|     _array.set<const JsonVariant&>(_index, src); | ||||
|   FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) { | ||||
|     _array.set(_index, src); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   typename TypeTraits::EnableIf<JsonArray::CanSet<T&>::value, | ||||
|                                 JsonArraySubscript>::type& | ||||
|   operator=(const T& src) { | ||||
|     _array.set<T&>(_index, const_cast<T&>(src)); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   typename TypeTraits::EnableIf<JsonArray::CanSet<T>::value, | ||||
|                                 JsonArraySubscript>::type& | ||||
|   operator=(T src) { | ||||
|     _array.set<T>(_index, src); | ||||
|   FORCE_INLINE JsonArraySubscript& operator=(const T& src) { | ||||
|     _array.set(_index, src); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
| @@ -46,10 +36,6 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | ||||
|     return _index < _array.size(); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE operator JsonVariant() const { | ||||
|     return _array.get(_index); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   FORCE_INLINE typename Internals::JsonVariantAs<T>::type as() const { | ||||
|     return _array.get<T>(_index); | ||||
| @@ -61,7 +47,7 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | ||||
|   } | ||||
|  | ||||
|   template <typename TValue> | ||||
|   void set(TValue value) { | ||||
|   FORCE_INLINE void set(const TValue& value) { | ||||
|     _array.set(_index, value); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -12,7 +12,6 @@ | ||||
| #include <string.h> | ||||
|  | ||||
| #include "JsonVariant.hpp" | ||||
| #include "String.hpp" | ||||
|  | ||||
| #if defined(__clang__) | ||||
| #pragma clang diagnostic push | ||||
| @@ -58,67 +57,56 @@ class JsonBuffer { | ||||
|   // writable | ||||
|   // 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 | ||||
|   // 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 | ||||
|   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); | ||||
|   } | ||||
|  | ||||
|   // 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. | ||||
|   // | ||||
|   // The First argument is a pointer to the JSON string, the memory must be | ||||
|   // writable | ||||
|   // 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 | ||||
|   // 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 | ||||
|   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); | ||||
|   } | ||||
|  | ||||
|   // 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 | ||||
|   // 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 | ||||
|   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); | ||||
|   } | ||||
|  | ||||
|   // 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 | ||||
|   char *strdup(const char *src) { | ||||
|     return src ? strdup(src, strlen(src)) : NULL; | ||||
|   } | ||||
|   char *strdup(const String &src) { | ||||
|     return strdup(src.c_str(), src.length()); | ||||
|   template <typename TString> | ||||
|   char *strdup(const TString &src) { | ||||
|     return Internals::StringFuncs<TString>::duplicate(src, this); | ||||
|   } | ||||
|  | ||||
|   // Allocates n bytes in the JsonBuffer. | ||||
| @@ -135,23 +123,6 @@ class JsonBuffer { | ||||
|     return bytes; | ||||
| #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); | ||||
|   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 | ||||
|  | ||||
| #include "String.hpp" | ||||
| #include "Internals/JsonBufferAllocated.hpp" | ||||
| #include "Internals/JsonPrintable.hpp" | ||||
| #include "Internals/List.hpp" | ||||
| #include "Internals/ReferenceType.hpp" | ||||
| #include "Internals/StringFuncs.hpp" | ||||
| #include "Internals/ValueSetter.hpp" | ||||
| #include "JsonPair.hpp" | ||||
| #include "TypeTraits/ConstRefOrConstPtr.hpp" | ||||
| #include "TypeTraits/EnableIf.hpp" | ||||
| #include "TypeTraits/IsFloatingPoint.hpp" | ||||
| #include "TypeTraits/IsReference.hpp" | ||||
| #include "TypeTraits/IsSame.hpp" | ||||
|  | ||||
| // Returns the size (in bytes) of an object with n elements. | ||||
| @@ -40,27 +41,19 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | ||||
|                    public Internals::List<JsonPair>, | ||||
|                    public Internals::JsonBufferAllocated { | ||||
|  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. | ||||
|   // You should not use this constructor directly. | ||||
|   // Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject(). | ||||
|   explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {} | ||||
|  | ||||
|   // Gets or sets the value associated with the specified key. | ||||
|   JsonObjectSubscript<const char*> operator[](const char* key); | ||||
|   JsonObjectSubscript<const String&> operator[](const String& key); | ||||
|   template <typename TString> | ||||
|   JsonObjectSubscript<TString> operator[](const TString& key); | ||||
|  | ||||
|   // Gets the value associated with the specified key. | ||||
|   JsonVariant operator[](JsonObjectKey key) const { | ||||
|     return get(key); | ||||
|   template <typename TString> | ||||
|   JsonVariant operator[](const TString& key) const { | ||||
|     return get<JsonVariant>(key); | ||||
|   } | ||||
|  | ||||
|   // 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, const char* 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, JsonArray&); | ||||
|   // bool set(Key, JsonObject&); | ||||
|   // bool set(Key, JsonVariant&); | ||||
|   template <typename T> | ||||
|   bool set(JsonObjectKey key, const T& value, | ||||
|            typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) { | ||||
|     return setNodeAt<T&>(key, const_cast<T&>(value)); | ||||
|   template <typename TValue, typename TString> | ||||
|   bool set(const TString& key, const TValue& value) { | ||||
|     // reduce the number of template function instanciation to reduce code size | ||||
|     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, double value, uint8_t decimals); | ||||
|   template <typename TValue> | ||||
|   bool set(JsonObjectKey key, TValue value, uint8_t decimals, | ||||
|            typename TypeTraits::EnableIf< | ||||
|                TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) { | ||||
|     return setNodeAt<const JsonVariant&>(key, JsonVariant(value, decimals)); | ||||
|   template <typename TValue, typename TString> | ||||
|   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value, | ||||
|                                 bool>::type | ||||
|   set(const TString& key, TValue value, uint8_t decimals) { | ||||
|     return set(key, JsonVariant(value, decimals)); | ||||
|   } | ||||
|  | ||||
|   // Gets the value associated with the specified key. | ||||
|   JsonVariant get(JsonObjectKey key) const { | ||||
|     node_type* node = getNodeAt(key.c_str()); | ||||
|     return node ? node->content.value : JsonVariant(); | ||||
|   } | ||||
|  | ||||
|   // Gets the value associated with the specified key. | ||||
|   template <typename T> | ||||
|   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>(); | ||||
|   template <typename TValue, typename TString> | ||||
|   typename Internals::JsonVariantAs<TValue>::type get( | ||||
|       const TString& key) const { | ||||
|     node_type* node = getNodeAt(key); | ||||
|     return node ? node->content.value.as<TValue>() | ||||
|                 : Internals::JsonVariantDefault<TValue>::get(); | ||||
|   } | ||||
|  | ||||
|   // Checks the type of the value associated with the specified key. | ||||
|   template <typename T> | ||||
|   bool is(JsonObjectKey key) const { | ||||
|     node_type* node = getNodeAt(key.c_str()); | ||||
|     return node ? node->content.value.is<T>() : false; | ||||
|   template <typename TValue, typename TString> | ||||
|   bool is(const TString& key) const { | ||||
|     node_type* node = getNodeAt(key); | ||||
|     return node ? node->content.value.is<TValue>() : false; | ||||
|   } | ||||
|  | ||||
|   // Creates and adds a JsonArray. | ||||
|   // 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. | ||||
|   // 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. | ||||
|   bool containsKey(JsonObjectKey key) const { | ||||
|     return getNodeAt(key.c_str()) != NULL; | ||||
|   template <typename TString> | ||||
|   bool containsKey(const TString& key) const { | ||||
|     return getNodeAt(key) != NULL; | ||||
|   } | ||||
|  | ||||
|   // Removes the specified key and the associated value. | ||||
|   void remove(JsonObjectKey key) { | ||||
|     removeNode(getNodeAt(key.c_str())); | ||||
|   template <typename TString> | ||||
|   void remove(const TString& key) { | ||||
|     removeNode(getNodeAt(key)); | ||||
|   } | ||||
|  | ||||
|   // Returns a reference an invalid JsonObject. | ||||
| @@ -146,37 +134,35 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | ||||
|  | ||||
|  private: | ||||
|   // 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) { | ||||
|       if (!strcmp(node->content.key, key)) return node; | ||||
|       if (Internals::StringFuncs<TStringRef>::equals(key, node->content.key)) | ||||
|         return node; | ||||
|     } | ||||
|     return NULL; | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   bool setNodeAt(JsonObjectKey key, T value) { | ||||
|     node_type* node = getNodeAt(key.c_str()); | ||||
|   template <typename TStringRef, typename TValueRef> | ||||
|   bool setNodeAt(TStringRef key, TValueRef value) { | ||||
|     node_type* node = getNodeAtImpl<TStringRef>(key); | ||||
|     if (!node) { | ||||
|       node = addNewNode(); | ||||
|       if (!node || !setNodeKey(node, key)) return false; | ||||
|     } | ||||
|     return setNodeValue<T>(node, value); | ||||
|   } | ||||
|       if (!node) return false; | ||||
|  | ||||
|   bool setNodeKey(node_type* node, JsonObjectKey key) { | ||||
|     if (key.needs_copy()) { | ||||
|       node->content.key = _buffer->strdup(key.c_str()); | ||||
|       if (node->content.key == NULL) return false; | ||||
|     } else { | ||||
|       node->content.key = key.c_str(); | ||||
|       bool key_ok = Internals::ValueSetter<TStringRef>::set( | ||||
|           _buffer, node->content.key, key); | ||||
|       if (!key_ok) return false; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   bool setNodeValue(node_type* node, T value) { | ||||
|     node->content.value = value; | ||||
|     return true; | ||||
|     return Internals::ValueSetter<TValueRef>::set(_buffer, node->content.value, | ||||
|                                                   value); | ||||
|   } | ||||
| }; | ||||
| } | ||||
|   | ||||
| @@ -13,38 +13,13 @@ | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|  | ||||
| namespace Internals { | ||||
| template <> | ||||
| inline bool JsonObject::setNodeValue(node_type *node, String &value) { | ||||
|   const char *dup = _buffer->strdup(value); | ||||
|   node->content.value = dup; | ||||
|   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(); | ||||
| struct JsonVariantDefault<JsonObject> { | ||||
|   static JsonObject &get() { | ||||
|     return JsonObject::invalid(); | ||||
|   } | ||||
| }; | ||||
| } | ||||
|  | ||||
| inline JsonObject &JsonVariant::asObject() const { | ||||
| @@ -52,11 +27,12 @@ inline JsonObject &JsonVariant::asObject() const { | ||||
|   return JsonObject::invalid(); | ||||
| } | ||||
|  | ||||
| inline JsonObject &JsonObject::createNestedObject(JsonObjectKey key) { | ||||
| template <typename TString> | ||||
| inline JsonObject &JsonObject::createNestedObject(const TString &key) { | ||||
|   if (!_buffer) return JsonObject::invalid(); | ||||
|   JsonObject &array = _buffer->createObject(); | ||||
|   setNodeAt<const JsonVariant &>(key, array); | ||||
|   return array; | ||||
|   JsonObject &object = _buffer->createObject(); | ||||
|   set(key, object); | ||||
|   return object; | ||||
| } | ||||
|  | ||||
| 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 "JsonVariantBase.hpp" | ||||
| #include "TypeTraits/ConstRefOrConstPtr.hpp" | ||||
| #include "TypeTraits/EnableIf.hpp" | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| @@ -18,30 +19,27 @@ | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|  | ||||
| template <typename TKey> | ||||
| class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > { | ||||
| template <typename TString> | ||||
| class JsonObjectSubscript | ||||
|     : public JsonVariantBase<JsonObjectSubscript<TString> > { | ||||
|   // const String& | ||||
|   // const std::string& | ||||
|   // const char* | ||||
|   typedef typename TypeTraits::ConstRefOrConstPtr<TString>::type TStringRef; | ||||
|  | ||||
|  public: | ||||
|   FORCE_INLINE JsonObjectSubscript(JsonObject& object, TKey key) | ||||
|   FORCE_INLINE JsonObjectSubscript(JsonObject& object, TStringRef key) | ||||
|       : _object(object), _key(key) {} | ||||
|  | ||||
|   JsonObjectSubscript<TKey>& operator=(const JsonObjectSubscript<TKey>& src) { | ||||
|     _object.set<const JsonVariant&>(_key, src); | ||||
|   FORCE_INLINE JsonObjectSubscript<TString>& operator=( | ||||
|       const JsonObjectSubscript<TString>& src) { | ||||
|     _object.set(_key, src); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   typename TypeTraits::EnableIf<JsonObject::CanSet<T&>::value, | ||||
|                                 JsonObjectSubscript<TKey> >::type& | ||||
|   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); | ||||
|   FORCE_INLINE JsonObjectSubscript<TString>& operator=(const T& src) { | ||||
|     _object.set(_key, src); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
| @@ -49,13 +47,9 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > { | ||||
|     return _object.containsKey(_key); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE operator JsonVariant() const { | ||||
|     return _object.get(_key); | ||||
|   } | ||||
|  | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type as() const { | ||||
|     return _object.get<TValue>(_key); | ||||
|     return _object.get<TValue, TStringRef>(_key); | ||||
|   } | ||||
|  | ||||
|   template <typename TValue> | ||||
| @@ -64,58 +58,39 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > { | ||||
|   } | ||||
|  | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE bool set(TValue value) { | ||||
|     return _object.set<TValue>(_key, value); | ||||
|   FORCE_INLINE bool set(const TValue& value) { | ||||
|     return _object.set(_key, value); | ||||
|   } | ||||
|  | ||||
|   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); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE JsonVariant get() { | ||||
|     return _object.get(_key); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   JsonObject& _object; | ||||
|   TKey _key; | ||||
|   TStringRef _key; | ||||
| }; | ||||
|  | ||||
| #if ARDUINOJSON_ENABLE_STD_STREAM | ||||
| inline std::ostream& operator<<( | ||||
|     std::ostream& os, const JsonObjectSubscript<const String&>& source) { | ||||
|   return source.printTo(os); | ||||
| } | ||||
|  | ||||
| inline std::ostream& operator<<( | ||||
|     std::ostream& os, const JsonObjectSubscript<const char*>& source) { | ||||
| template <typename TString> | ||||
| inline std::ostream& operator<<(std::ostream& os, | ||||
|                                 const JsonObjectSubscript<TString>& source) { | ||||
|   return source.printTo(os); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| inline JsonObjectSubscript<const char*> JsonObject::operator[]( | ||||
|     const char* key) { | ||||
|   return JsonObjectSubscript<const char*>(*this, key); | ||||
| } | ||||
|  | ||||
| inline JsonObjectSubscript<const String&> JsonObject::operator[]( | ||||
|     const String& key) { | ||||
|   return JsonObjectSubscript<const String&>(*this, key); | ||||
| template <typename TString> | ||||
| inline JsonObjectSubscript<TString> JsonObject::operator[](const TString& key) { | ||||
|   return JsonObjectSubscript<TString>(*this, key); | ||||
| } | ||||
|  | ||||
| template <typename TImplem> | ||||
| inline const JsonObjectSubscript<const char*> JsonVariantBase<TImplem>:: | ||||
| operator[](const char* key) const { | ||||
| template <class TString> | ||||
| inline const JsonObjectSubscript<TString> JsonVariantBase<TImplem>::operator[]( | ||||
|     const TString& key) const { | ||||
|   return asObject()[key]; | ||||
| } | ||||
|  | ||||
| template <typename TImplem> | ||||
| inline const JsonObjectSubscript<const String&> JsonVariantBase<TImplem>:: | ||||
| operator[](const String& key) const { | ||||
|   return asObject()[key]; | ||||
| } | ||||
|  | ||||
| }  // namespace ArduinoJson | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
|   | ||||
| @@ -7,7 +7,6 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "JsonObjectKey.hpp" | ||||
| #include "JsonVariant.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
|  | ||||
| #include "Internals/JsonPrintable.hpp" | ||||
| #include "Internals/JsonVariantContent.hpp" | ||||
| #include "Internals/JsonVariantDefault.hpp" | ||||
| #include "Internals/JsonVariantType.hpp" | ||||
| #include "JsonVariantBase.hpp" | ||||
| #include "RawJson.hpp" | ||||
| @@ -19,6 +20,8 @@ | ||||
| #include "TypeTraits/IsFloatingPoint.hpp" | ||||
| #include "TypeTraits/IsIntegral.hpp" | ||||
| #include "TypeTraits/IsSame.hpp" | ||||
| #include "TypeTraits/IsSignedIntegral.hpp" | ||||
| #include "TypeTraits/IsUnsignedIntegral.hpp" | ||||
| #include "TypeTraits/RemoveConst.hpp" | ||||
| #include "TypeTraits/RemoveReference.hpp" | ||||
|  | ||||
| @@ -40,9 +43,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|                                                    JsonWriter &); | ||||
|  | ||||
|  public: | ||||
|   template <typename T> | ||||
|   struct IsConstructibleFrom; | ||||
|  | ||||
|   // Creates an uninitialized JsonVariant | ||||
|   JsonVariant() : _type(Internals::JSON_UNDEFINED) {} | ||||
|  | ||||
| @@ -110,10 +110,14 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|   } | ||||
|  | ||||
|   // 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. | ||||
|   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. | ||||
|   // | ||||
| @@ -146,14 +150,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|     return static_cast<T>(asFloat()); | ||||
|   } | ||||
|   // | ||||
|   // const String as<String>() const; | ||||
|   template <typename T> | ||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, String>::value, | ||||
|                                       T>::type | ||||
|   as() const { | ||||
|     return toString(); | ||||
|   } | ||||
|   // | ||||
|   // const char* as<const char*>() const; | ||||
|   // const char* as<char*>() const; | ||||
|   template <typename T> | ||||
| @@ -164,6 +160,18 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|     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 | ||||
|   template <typename T> | ||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value, | ||||
| @@ -230,7 +238,8 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|   // int as<int>() const; | ||||
|   // long as<long>() const; | ||||
|   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 | ||||
|   is() const { | ||||
|     return isInteger(); | ||||
| @@ -296,12 +305,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|     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 | ||||
|   const char *asString() const; | ||||
|  | ||||
| @@ -317,7 +320,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|   JsonVariant(T value, typename TypeTraits::EnableIf< | ||||
|                            TypeTraits::IsSame<T, char>::value>::type * = 0); | ||||
|  | ||||
|   String toString() const; | ||||
|   Internals::JsonFloat asFloat() const; | ||||
|   Internals::JsonInteger asInteger() 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) { | ||||
|   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 | ||||
|  | ||||
| #include "Configuration.hpp" | ||||
| #include "JsonVariant.hpp" | ||||
| #include "Internals/Parse.hpp" | ||||
| #include "JsonArray.hpp" | ||||
| #include "JsonObject.hpp" | ||||
| #include "JsonVariant.hpp" | ||||
|  | ||||
| #include <string.h>  // for strcmp | ||||
| #include <errno.h>   // for errno | ||||
| #include <stdlib.h>  // for strtol, strtod | ||||
| #include <string.h>  // for strcmp | ||||
|  | ||||
| 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 { | ||||
|   using namespace Internals; | ||||
|   if (_type == JSON_BOOLEAN) return true; | ||||
|   | ||||
| @@ -8,7 +8,6 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "Internals/JsonVariantAs.hpp" | ||||
| #include "JsonObjectKey.hpp" | ||||
| #include "Polyfills/attributes.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| @@ -77,10 +76,9 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> { | ||||
|   // Returns the value associated with the specified key if the variant is | ||||
|   // an object. | ||||
|   // Return JsonVariant::invalid() if the variant is not an object. | ||||
|   FORCE_INLINE const JsonObjectSubscript<const char *> operator[]( | ||||
|       const char *key) const; | ||||
|   FORCE_INLINE const JsonObjectSubscript<const String &> operator[]( | ||||
|       const String &key) const; | ||||
|   template <typename TString> | ||||
|   FORCE_INLINE const JsonObjectSubscript<TString> operator[]( | ||||
|       const TString &key) const; | ||||
|  | ||||
|  private: | ||||
|   const TImpl *impl() const { | ||||
|   | ||||
| @@ -13,7 +13,9 @@ namespace ArduinoJson { | ||||
| class RawJson { | ||||
|  public: | ||||
|   explicit RawJson(const char* str) : _str(str) {} | ||||
|   operator const char*() const { return _str; } | ||||
|   operator const char*() const { | ||||
|     return _str; | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   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 | ||||
|  | ||||
| #include "../Configuration.hpp" | ||||
| #include "IsSame.hpp" | ||||
| #include "IsSignedIntegral.hpp" | ||||
| #include "IsUnsignedIntegral.hpp" | ||||
| @@ -20,7 +19,11 @@ template <typename T> | ||||
| struct IsIntegral { | ||||
|   static const bool value = TypeTraits::IsSignedIntegral<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 | ||||
| // If you like this project, please add a star! | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
| #include <ArduinoJson.h> | ||||
| #include <gtest/gtest.h> | ||||
|  | ||||
| class DynamicJsonBuffer_Basic_Tests : public testing::Test { | ||||
|  protected: | ||||
| @@ -38,3 +38,16 @@ TEST_F(DynamicJsonBuffer_Basic_Tests, Alignment) { | ||||
|     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 | ||||
| // If you like this project, please add a star! | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
| #include <ArduinoJson.h> | ||||
| #include <gtest/gtest.h> | ||||
|  | ||||
| TEST(JsonObject_Invalid_Tests, SubscriptFails) { | ||||
|   ASSERT_FALSE(JsonObject::invalid()[0].success()); | ||||
|   ASSERT_FALSE(JsonObject::invalid()["key"].success()); | ||||
| } | ||||
|  | ||||
| TEST(JsonObject_Invalid_Tests, AddFails) { | ||||
|   | ||||
| @@ -5,8 +5,8 @@ | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
| // If you like this project, please add a star! | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
| #include <ArduinoJson.h> | ||||
| #include <gtest/gtest.h> | ||||
|  | ||||
| class JsonObject_Set_Tests : public ::testing::Test { | ||||
|  public: | ||||
| @@ -112,7 +112,7 @@ TEST_(ShouldReturnTrue_WhenAllocationSucceeds) { | ||||
|   StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 15> jsonBuffer; | ||||
|   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); | ||||
| } | ||||
| @@ -121,7 +121,7 @@ TEST_(ShouldReturnFalse_WhenAllocationFails) { | ||||
|   StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 10> jsonBuffer; | ||||
|   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); | ||||
| } | ||||
|   | ||||
| @@ -24,7 +24,7 @@ TEST(JsonVariant_As_Tests, DoubleAsCstr) { | ||||
|  | ||||
| TEST(JsonVariant_As_Tests, DoubleAsString) { | ||||
|   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) { | ||||
| @@ -64,7 +64,7 @@ TEST(JsonVariant_As_Tests, FalseAsLong) { | ||||
|  | ||||
| TEST(JsonVariant_As_Tests, FalseAsString) { | ||||
|   JsonVariant variant = false; | ||||
|   ASSERT_EQ(String("false"), variant.as<String>()); | ||||
|   ASSERT_EQ(std::string("false"), variant.as<std::string>()); | ||||
| } | ||||
|  | ||||
| TEST(JsonVariant_As_Tests, TrueAsBool) { | ||||
| @@ -84,7 +84,7 @@ TEST(JsonVariant_As_Tests, TrueAsLong) { | ||||
|  | ||||
| TEST(JsonVariant_As_Tests, TrueAsString) { | ||||
|   JsonVariant variant = true; | ||||
|   ASSERT_EQ(String("true"), variant.as<String>()); | ||||
|   ASSERT_EQ(std::string("true"), variant.as<std::string>()); | ||||
| } | ||||
|  | ||||
| TEST(JsonVariant_As_Tests, LongAsBool) { | ||||
| @@ -109,7 +109,7 @@ TEST(JsonVariant_As_Tests, NegativeLongAsDouble) { | ||||
|  | ||||
| TEST(JsonVariant_As_Tests, LongAsString) { | ||||
|   JsonVariant variant = 42L; | ||||
|   ASSERT_EQ(String("42"), variant.as<String>()); | ||||
|   ASSERT_EQ(std::string("42"), variant.as<std::string>()); | ||||
| } | ||||
|  | ||||
| TEST(JsonVariant_As_Tests, LongZeroAsDouble) { | ||||
| @@ -134,7 +134,7 @@ TEST(JsonVariant_As_Tests, NullAsLong) { | ||||
|  | ||||
| TEST(JsonVariant_As_Tests, NullAsString) { | ||||
|   JsonVariant variant = null; | ||||
|   ASSERT_EQ(String("null"), variant.as<String>()); | ||||
|   ASSERT_EQ(std::string("null"), variant.as<std::string>()); | ||||
| } | ||||
|  | ||||
| TEST(JsonVariant_As_Tests, NumberStringAsBool) { | ||||
| @@ -181,7 +181,7 @@ TEST(JsonVariant_As_Tests, RandomStringAsCharPtr) { | ||||
|  | ||||
| TEST(JsonVariant_As_Tests, RandomStringAsString) { | ||||
|   JsonVariant variant = "hello"; | ||||
|   ASSERT_EQ(String("hello"), variant.as<String>()); | ||||
|   ASSERT_EQ(std::string("hello"), variant.as<std::string>()); | ||||
| } | ||||
|  | ||||
| TEST(JsonVariant_As_Tests, TrueStringAsBool) { | ||||
| @@ -201,7 +201,7 @@ TEST(JsonVariant_As_Tests, ObjectAsString) { | ||||
|   obj["key"] = "value"; | ||||
|  | ||||
|   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) { | ||||
| @@ -212,7 +212,7 @@ TEST(JsonVariant_As_Tests, ArrayAsString) { | ||||
|   arr.add(2); | ||||
|  | ||||
|   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) { | ||||
|   | ||||
| @@ -5,12 +5,12 @@ | ||||
| // https://github.com/bblanchon/ArduinoJson
 | ||||
| // If you like this project, please add a star!
 | ||||
| 
 | ||||
| #include <gtest/gtest.h> | ||||
| #include <ArduinoJson.h> | ||||
| #include <gtest/gtest.h> | ||||
| 
 | ||||
| class ArduinoStringTests : public ::testing::Test { | ||||
| class StringTests : public ::testing::Test { | ||||
|  protected: | ||||
|   static void eraseString(String &str) { | ||||
|   static void eraseString(std::string &str) { | ||||
|     char *p = const_cast<char *>(str.c_str()); | ||||
|     while (*p) *p++ = '*'; | ||||
|   } | ||||
| @@ -18,100 +18,100 @@ class ArduinoStringTests : public ::testing::Test { | ||||
|   DynamicJsonBuffer _jsonBuffer; | ||||
| }; | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonBuffer_ParseArray) { | ||||
|   String json("[\"hello\"]"); | ||||
| TEST_F(StringTests, JsonBuffer_ParseArray) { | ||||
|   std::string json("[\"hello\"]"); | ||||
|   JsonArray &array = _jsonBuffer.parseArray(json); | ||||
|   eraseString(json); | ||||
|   ASSERT_TRUE(array.success()); | ||||
|   ASSERT_STREQ("hello", array[0]); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonBuffer_ParseObject) { | ||||
|   String json("{\"hello\":\"world\"}"); | ||||
| TEST_F(StringTests, JsonBuffer_ParseObject) { | ||||
|   std::string json("{\"hello\":\"world\"}"); | ||||
|   JsonObject &object = _jsonBuffer.parseObject(json); | ||||
|   eraseString(json); | ||||
|   ASSERT_TRUE(object.success()); | ||||
|   ASSERT_STREQ("world", object["hello"]); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonObject_Subscript) { | ||||
| TEST_F(StringTests, JsonObject_Subscript) { | ||||
|   char json[] = "{\"key\":\"value\"}"; | ||||
|   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\"}"; | ||||
|   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(); | ||||
|   String key("hello"); | ||||
|   std::string key("hello"); | ||||
|   object.set(key, "world"); | ||||
|   eraseString(key); | ||||
|   ASSERT_STREQ("world", object["hello"]); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonObject_SetValue) { | ||||
| TEST_F(StringTests, JsonObject_SetValue) { | ||||
|   JsonObject &object = _jsonBuffer.createObject(); | ||||
|   String value("world"); | ||||
|   std::string value("world"); | ||||
|   object.set("hello", value); | ||||
|   eraseString(value); | ||||
|   ASSERT_STREQ("world", object["hello"]); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonObject_SetKeyValue) { | ||||
| TEST_F(StringTests, JsonObject_SetKeyValue) { | ||||
|   JsonObject &object = _jsonBuffer.createObject(); | ||||
|   String key("hello"); | ||||
|   String value("world"); | ||||
|   std::string key("hello"); | ||||
|   std::string value("world"); | ||||
|   object.set(key, value); | ||||
|   eraseString(key); | ||||
|   eraseString(value); | ||||
|   ASSERT_STREQ("world", object["hello"]); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonObject_SetToArraySubscript) { | ||||
| TEST_F(StringTests, JsonObject_SetToArraySubscript) { | ||||
|   JsonArray &arr = _jsonBuffer.createArray(); | ||||
|   arr.add("world"); | ||||
| 
 | ||||
|   JsonObject &object = _jsonBuffer.createObject(); | ||||
|   object.set(String("hello"), arr[0]); | ||||
|   object.set(std::string("hello"), arr[0]); | ||||
| 
 | ||||
|   ASSERT_STREQ("world", object["hello"]); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonObject_SetToObjectSubscript) { | ||||
| TEST_F(StringTests, JsonObject_SetToObjectSubscript) { | ||||
|   JsonObject &arr = _jsonBuffer.createObject(); | ||||
|   arr.set("x", "world"); | ||||
| 
 | ||||
|   JsonObject &object = _jsonBuffer.createObject(); | ||||
|   object.set(String("hello"), arr["x"]); | ||||
|   object.set(std::string("hello"), arr["x"]); | ||||
| 
 | ||||
|   ASSERT_STREQ("world", object["hello"]); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonObject_Get) { | ||||
| TEST_F(StringTests, JsonObject_Get) { | ||||
|   char json[] = "{\"key\":\"value\"}"; | ||||
|   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\"}"; | ||||
|   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\"}"; | ||||
|   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) { | ||||
|   String key = "key"; | ||||
| TEST_F(StringTests, JsonObject_CreateNestedObject) { | ||||
|   std::string key = "key"; | ||||
|   char json[64]; | ||||
|   JsonObject &object = _jsonBuffer.createObject(); | ||||
|   object.createNestedObject(key); | ||||
| @@ -120,8 +120,8 @@ TEST_F(ArduinoStringTests, JsonObject_CreateNestedObject) { | ||||
|   ASSERT_STREQ("{\"key\":{}}", json); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonObject_CreateNestedArray) { | ||||
|   String key = "key"; | ||||
| TEST_F(StringTests, JsonObject_CreateNestedArray) { | ||||
|   std::string key = "key"; | ||||
|   char json[64]; | ||||
|   JsonObject &object = _jsonBuffer.createObject(); | ||||
|   object.createNestedArray(key); | ||||
| @@ -130,99 +130,99 @@ TEST_F(ArduinoStringTests, JsonObject_CreateNestedArray) { | ||||
|   ASSERT_STREQ("{\"key\":[]}", json); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonObject_ContainsKey) { | ||||
| TEST_F(StringTests, JsonObject_ContainsKey) { | ||||
|   char json[] = "{\"key\":\"value\"}"; | ||||
|   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\"}"; | ||||
|   JsonObject &object = _jsonBuffer.parseObject(json); | ||||
|   ASSERT_EQ(1, object.size()); | ||||
|   object.remove(String("key")); | ||||
|   object.remove(std::string("key")); | ||||
|   ASSERT_EQ(0, object.size()); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonObjectSubscript_SetKey) { | ||||
| TEST_F(StringTests, JsonObjectSubscript_SetKey) { | ||||
|   JsonObject &object = _jsonBuffer.createObject(); | ||||
|   String key("hello"); | ||||
|   std::string key("hello"); | ||||
|   object[key] = "world"; | ||||
|   eraseString(key); | ||||
|   ASSERT_STREQ("world", object["hello"]); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonObjectSubscript_SetValue) { | ||||
| TEST_F(StringTests, JsonObjectSubscript_SetValue) { | ||||
|   JsonObject &object = _jsonBuffer.createObject(); | ||||
|   String value("world"); | ||||
|   std::string value("world"); | ||||
|   object["hello"] = value; | ||||
|   eraseString(value); | ||||
|   ASSERT_STREQ("world", object["hello"]); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonArray_Add) { | ||||
| TEST_F(StringTests, JsonArray_Add) { | ||||
|   JsonArray &array = _jsonBuffer.createArray(); | ||||
|   String value("hello"); | ||||
|   std::string value("hello"); | ||||
|   array.add(value); | ||||
|   eraseString(value); | ||||
|   ASSERT_STREQ("hello", array[0]); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonArray_Set) { | ||||
| TEST_F(StringTests, JsonArray_Set) { | ||||
|   JsonArray &array = _jsonBuffer.createArray(); | ||||
|   String value("world"); | ||||
|   std::string value("world"); | ||||
|   array.add("hello"); | ||||
|   array.set(0, value); | ||||
|   eraseString(value); | ||||
|   ASSERT_STREQ("world", array[0]); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonArraySubscript) { | ||||
| TEST_F(StringTests, JsonArraySubscript) { | ||||
|   JsonArray &array = _jsonBuffer.createArray(); | ||||
|   String value("world"); | ||||
|   std::string value("world"); | ||||
|   array.add("hello"); | ||||
|   array[0] = value; | ||||
|   eraseString(value); | ||||
|   ASSERT_STREQ("world", array[0]); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonArray_PrintTo) { | ||||
| TEST_F(StringTests, JsonArray_PrintTo) { | ||||
|   JsonArray &array = _jsonBuffer.createArray(); | ||||
|   array.add(4); | ||||
|   array.add(2); | ||||
|   String json; | ||||
|   std::string 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(); | ||||
|   array.add(4); | ||||
|   array.add(2); | ||||
|   String json; | ||||
|   std::string 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(); | ||||
|   object["key"] = "value"; | ||||
|   String json; | ||||
|   std::string 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(); | ||||
|   object["key"] = "value"; | ||||
|   String json; | ||||
|   std::string 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(); | ||||
|   String key1("hello"), key2("world"); | ||||
|   std::string key1("hello"), key2("world"); | ||||
| 
 | ||||
|   object[key1] = 1; | ||||
|   size_t sizeBefore = _jsonBuffer.size(); | ||||
| @@ -232,9 +232,9 @@ TEST_F(ArduinoStringTests, JsonBuffer_GrowWhenAddingNewKey) { | ||||
|   ASSERT_GT(sizeAfter - sizeBefore, key2.size()); | ||||
| } | ||||
| 
 | ||||
| TEST_F(ArduinoStringTests, JsonBuffer_DontGrowWhenReusingKey) { | ||||
| TEST_F(StringTests, JsonBuffer_DontGrowWhenReusingKey) { | ||||
|   JsonObject &object = _jsonBuffer.createObject(); | ||||
|   String key("hello"); | ||||
|   std::string key("hello"); | ||||
| 
 | ||||
|   object[key] = 1; | ||||
|   size_t sizeBefore = _jsonBuffer.size(); | ||||
| @@ -243,3 +243,10 @@ TEST_F(ArduinoStringTests, JsonBuffer_DontGrowWhenReusingKey) { | ||||
| 
 | ||||
|   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