mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Changed the rules of string duplication (fixes #658)
This commit is contained in:
		
							
								
								
									
										16
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,6 +1,22 @@ | |||||||
| ArduinoJson: change log | ArduinoJson: change log | ||||||
| ======================= | ======================= | ||||||
|  |  | ||||||
|  | HEAD | ||||||
|  | ---- | ||||||
|  |  | ||||||
|  | * Changed the rules of string duplication (issue #658) | ||||||
|  |  | ||||||
|  | > ### New rules for string duplication | ||||||
|  | > | ||||||
|  | > | type         | duplication | | ||||||
|  | > |:-------------|:------------| | ||||||
|  | > | const char*  | no          | | ||||||
|  | > | char*        | ~~no~~ yes  | | ||||||
|  | > | String       | yes         | | ||||||
|  | > | std::string  | yes         | | ||||||
|  | > | ||||||
|  | > These new rules make `JsonBuffer::strdup()` useless. | ||||||
|  |  | ||||||
| v5.12.0 | v5.12.0 | ||||||
| ------- | ------- | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								src/ArduinoJson/Data/ValueSaver.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/ArduinoJson/Data/ValueSaver.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "../JsonBuffer.hpp" | ||||||
|  | #include "../JsonVariant.hpp" | ||||||
|  | #include "../StringTraits/StringTraits.hpp" | ||||||
|  | #include "../TypeTraits/EnableIf.hpp" | ||||||
|  |  | ||||||
|  | namespace ArduinoJson { | ||||||
|  | namespace Internals { | ||||||
|  |  | ||||||
|  | template <typename Source, typename Enable = void> | ||||||
|  | struct ValueSaver { | ||||||
|  |   template <typename Destination> | ||||||
|  |   static bool save(JsonBuffer*, Destination& destination, Source source) { | ||||||
|  |     destination = source; | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename Source> | ||||||
|  | struct ValueSaver<Source, typename TypeTraits::EnableIf< | ||||||
|  |                               TypeTraits::IsString<Source>::value>::type> { | ||||||
|  |   template <typename Destination> | ||||||
|  |   static bool save(JsonBuffer* buffer, Destination& destination, | ||||||
|  |                    Source source) { | ||||||
|  |     return StringTraits<Source>::save(source, destination, buffer); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | } | ||||||
|  | } | ||||||
| @@ -1,48 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include "../JsonBuffer.hpp" |  | ||||||
| #include "../JsonVariant.hpp" |  | ||||||
| #include "../StringTraits/StringTraits.hpp" |  | ||||||
| #include "../TypeTraits/EnableIf.hpp" |  | ||||||
|  |  | ||||||
| namespace ArduinoJson { |  | ||||||
| namespace Internals { |  | ||||||
|  |  | ||||||
| template <typename TSourceRef, typename Enable = void> |  | ||||||
| struct ValueSetter { |  | ||||||
|   template <typename TDestination> |  | ||||||
|   static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) { |  | ||||||
|     destination = source; |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template <typename TSourceRef> |  | ||||||
| struct ValueSetter<TSourceRef, typename TypeTraits::EnableIf<StringTraits< |  | ||||||
|                                    TSourceRef>::should_duplicate>::type> { |  | ||||||
|   template <typename TDestination> |  | ||||||
|   static bool set(JsonBuffer* buffer, TDestination& destination, |  | ||||||
|                   TSourceRef source) { |  | ||||||
|     const char* copy = buffer->strdup(source); |  | ||||||
|     if (!copy) return false; |  | ||||||
|     destination = copy; |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template <typename TSourceRef> |  | ||||||
| struct ValueSetter<TSourceRef, typename TypeTraits::EnableIf<!StringTraits< |  | ||||||
|                                    TSourceRef>::should_duplicate>::type> { |  | ||||||
|   template <typename TDestination> |  | ||||||
|   static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) { |  | ||||||
|     // unsigned char* -> char* |  | ||||||
|     destination = reinterpret_cast<const char*>(source); |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| } |  | ||||||
| } |  | ||||||
| @@ -7,7 +7,7 @@ | |||||||
| #include "Data/JsonBufferAllocated.hpp" | #include "Data/JsonBufferAllocated.hpp" | ||||||
| #include "Data/List.hpp" | #include "Data/List.hpp" | ||||||
| #include "Data/ReferenceType.hpp" | #include "Data/ReferenceType.hpp" | ||||||
| #include "Data/ValueSetter.hpp" | #include "Data/ValueSaver.hpp" | ||||||
| #include "JsonVariant.hpp" | #include "JsonVariant.hpp" | ||||||
| #include "Serialization/JsonPrintable.hpp" | #include "Serialization/JsonPrintable.hpp" | ||||||
| #include "StringTraits/StringTraits.hpp" | #include "StringTraits/StringTraits.hpp" | ||||||
| @@ -56,19 +56,17 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   // |   // | ||||||
|   // bool add(TValue); |   // bool add(TValue); | ||||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, | ||||||
|   //          const std::string&, const String&, |   //          std::string, String, JsonArray, JsonObject | ||||||
|   //          const JsonArray&, const JsonObject& |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<T>::value, bool>::type add( |   bool add(const T &value) { | ||||||
|       const T &value) { |  | ||||||
|     return add_impl<const T &>(value); |     return add_impl<const T &>(value); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool add(TValue); |   // bool add(TValue); | ||||||
|   // TValue = const char*, const char[N], const FlashStringHelper* |   // TValue = char*, const char*, const FlashStringHelper* | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   bool add(const T *value) { |   bool add(T *value) { | ||||||
|     return add_impl<const T *>(value); |     return add_impl<T *>(value); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool add(TValue value, uint8_t decimals); |   // bool add(TValue value, uint8_t decimals); | ||||||
| @@ -81,21 +79,19 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|  |  | ||||||
|   // Sets the value at specified index. |   // Sets the value at specified index. | ||||||
|   // |   // | ||||||
|   // bool add(size_t index, TValue); |   // bool add(size_t index, const TValue&); | ||||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, | ||||||
|   //          const std::string&, const String&, |   //          std::string, String, JsonArray, JsonObject | ||||||
|   //          const JsonArray&, const JsonObject& |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<T>::value, bool>::type set( |   bool set(size_t index, const T &value) { | ||||||
|       size_t index, const T &value) { |  | ||||||
|     return set_impl<const T &>(index, value); |     return set_impl<const T &>(index, value); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool add(size_t index, TValue); |   // bool add(size_t index, TValue); | ||||||
|   // TValue = const char*, const char[N], const FlashStringHelper* |   // TValue = char*, const char*, const FlashStringHelper* | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   bool set(size_t index, const T *value) { |   bool set(size_t index, T *value) { | ||||||
|     return set_impl<const T *>(index, value); |     return set_impl<T *>(index, value); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool set(size_t index, TValue value, uint8_t decimals); |   // bool set(size_t index, TValue value, uint8_t decimals); | ||||||
| @@ -208,14 +204,14 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   bool set_impl(size_t index, TValueRef value) { |   bool set_impl(size_t index, TValueRef value) { | ||||||
|     iterator it = begin() += index; |     iterator it = begin() += index; | ||||||
|     if (it == end()) return false; |     if (it == end()) return false; | ||||||
|     return Internals::ValueSetter<TValueRef>::set(_buffer, *it, value); |     return Internals::ValueSaver<TValueRef>::save(_buffer, *it, value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TValueRef> |   template <typename TValueRef> | ||||||
|   bool add_impl(TValueRef value) { |   bool add_impl(TValueRef value) { | ||||||
|     iterator it = Internals::List<JsonVariant>::add(); |     iterator it = Internals::List<JsonVariant>::add(); | ||||||
|     if (it == end()) return false; |     if (it == end()) return false; | ||||||
|     return Internals::ValueSetter<TValueRef>::set(_buffer, *it, value); |     return Internals::ValueSaver<TValueRef>::save(_buffer, *it, value); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,10 +25,9 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | |||||||
|  |  | ||||||
|   // Replaces the value |   // Replaces the value | ||||||
|   // |   // | ||||||
|   // operator=(TValue) |   // operator=(const TValue&) | ||||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, | ||||||
|   //          const std::string&, const String&, |   //          std::string, String, JsonArray, JsonObject | ||||||
|   //          const JsonArray&, const JsonObject& |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE JsonArraySubscript& operator=(const T& src) { |   FORCE_INLINE JsonArraySubscript& operator=(const T& src) { | ||||||
|     _array.set(_index, src); |     _array.set(_index, src); | ||||||
| @@ -36,9 +35,9 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | |||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // operator=(TValue) |   // operator=(TValue) | ||||||
|   // TValue = const char*, const char[N], const FlashStringHelper* |   // TValue = char*, const char*, const FlashStringHelper* | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE JsonArraySubscript& operator=(const T* src) { |   FORCE_INLINE JsonArraySubscript& operator=(T* src) { | ||||||
|     _array.set(_index, src); |     _array.set(_index, src); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
| @@ -59,19 +58,18 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | |||||||
|  |  | ||||||
|   // Replaces the value |   // Replaces the value | ||||||
|   // |   // | ||||||
|   // bool set(TValue) |   // bool set(const TValue&) | ||||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, | ||||||
|   //          const std::string&, const String&, |   //          std::string, String, JsonArray, JsonObject | ||||||
|   //          const JsonArray&, const JsonObject& |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(const TValue& value) { |   FORCE_INLINE bool set(const TValue& value) { | ||||||
|     return _array.set(_index, value); |     return _array.set(_index, value); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool set(TValue) |   // bool set(TValue) | ||||||
|   // TValue = const char*, const char[N], const FlashStringHelper* |   // TValue = char*, const char*, const FlashStringHelper* | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(const TValue* value) { |   FORCE_INLINE bool set(TValue* value) { | ||||||
|     return _array.set(_index, value); |     return _array.set(_index, value); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
| #include "Data/JsonBufferAllocated.hpp" | #include "Data/JsonBufferAllocated.hpp" | ||||||
| #include "Data/List.hpp" | #include "Data/List.hpp" | ||||||
| #include "Data/ReferenceType.hpp" | #include "Data/ReferenceType.hpp" | ||||||
| #include "Data/ValueSetter.hpp" | #include "Data/ValueSaver.hpp" | ||||||
| #include "JsonPair.hpp" | #include "JsonPair.hpp" | ||||||
| #include "Serialization/JsonPrintable.hpp" | #include "Serialization/JsonPrintable.hpp" | ||||||
| #include "StringTraits/StringTraits.hpp" | #include "StringTraits/StringTraits.hpp" | ||||||
| @@ -50,17 +50,15 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // JsonObjectSubscript operator[](TKey) |   // JsonObjectSubscript operator[](TKey) | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, |   JsonObjectSubscript<const TString&> operator[](const TString& key) { | ||||||
|                                 JsonObjectSubscript<const TString&> >::type |  | ||||||
|   operator[](const TString& key) { |  | ||||||
|     return JsonObjectSubscript<const TString&>(*this, key); |     return JsonObjectSubscript<const TString&>(*this, key); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // JsonObjectSubscript operator[](TKey) |   // JsonObjectSubscript operator[](TKey) | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = char*, const char*, char[], const char[N], const FlashStringHelper* | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   JsonObjectSubscript<const TString*> operator[](const TString* key) { |   JsonObjectSubscript<TString*> operator[](TString* key) { | ||||||
|     return JsonObjectSubscript<const TString*>(*this, key); |     return JsonObjectSubscript<TString*>(*this, key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Gets the value associated with the specified key. |   // Gets the value associated with the specified key. | ||||||
| @@ -68,10 +66,8 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // const JsonObjectSubscript operator[](TKey) const; |   // const JsonObjectSubscript operator[](TKey) const; | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   typename TypeTraits::EnableIf< |   const JsonObjectSubscript<const TString&> operator[]( | ||||||
|       !TypeTraits::IsArray<TString>::value, |       const TString& key) const { | ||||||
|       const JsonObjectSubscript<const TString&> >::type |  | ||||||
|   operator[](const TString& key) const { |  | ||||||
|     return JsonObjectSubscript<const TString&>(*const_cast<JsonObject*>(this), |     return JsonObjectSubscript<const TString&>(*const_cast<JsonObject*>(this), | ||||||
|                                                key); |                                                key); | ||||||
|   } |   } | ||||||
| @@ -79,10 +75,8 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // const JsonObjectSubscript operator[](TKey) const; |   // const JsonObjectSubscript operator[](TKey) const; | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = const char*, const char[N], const FlashStringHelper* | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   const JsonObjectSubscript<const TString*> operator[]( |   const JsonObjectSubscript<TString*> operator[](TString* key) const { | ||||||
|       const TString* key) const { |     return JsonObjectSubscript<TString*>(*const_cast<JsonObject*>(this), key); | ||||||
|     return JsonObjectSubscript<const TString*>(*const_cast<JsonObject*>(this), |  | ||||||
|                                                key); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Sets the specified key with the specified value. |   // Sets the specified key with the specified value. | ||||||
| @@ -90,43 +84,35 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // bool set(TKey, TValue); |   // bool set(TKey, TValue); | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, | ||||||
|   //          const std::string&, const String&, |   //          std::string, String, JsonArray, JsonObject | ||||||
|   //          const JsonArray&, const JsonObject& |  | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value && |   bool set(const TString& key, const TValue& value) { | ||||||
|                                     !TypeTraits::IsArray<TValue>::value, |  | ||||||
|                                 bool>::type |  | ||||||
|   set(const TString& key, const TValue& value) { |  | ||||||
|     return set_impl<const TString&, const TValue&>(key, value); |     return set_impl<const TString&, const TValue&>(key, value); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool set(TKey, TValue); |   // bool set(TKey, TValue); | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   // TValue = const char*, const char[N], const FlashStringHelper* |   // TValue = char*, const char*, const FlashStringHelper* | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, |   bool set(const TString& key, TValue* value) { | ||||||
|                                 bool>::type |     return set_impl<const TString&, TValue*>(key, value); | ||||||
|   set(const TString& key, const TValue* value) { |  | ||||||
|     return set_impl<const TString&, const TValue*>(key, value); |  | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool set(TKey, TValue); |   // bool set(TKey, const TValue&); | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = char*, const char*, const FlashStringHelper* | ||||||
|   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, | ||||||
|   //          const std::string&, const String&, |   //          std::string, String, JsonArray, JsonObject | ||||||
|   //          const JsonArray&, const JsonObject& |  | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value, bool>::type |   bool set(TString* key, const TValue& value) { | ||||||
|   set(const TString* key, const TValue& value) { |     return set_impl<TString*, const TValue&>(key, value); | ||||||
|     return set_impl<const TString*, const TValue&>(key, value); |  | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool set(TKey, TValue); |   // bool set(TKey, TValue); | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = char*, const char*, const FlashStringHelper* | ||||||
|   // TValue = const char*, const char[N], const FlashStringHelper* |   // TValue = char*, const char*, const FlashStringHelper* | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|   bool set(const TString* key, const TValue* value) { |   bool set(TString* key, TValue* value) { | ||||||
|     return set_impl<const TString*, const TValue*>(key, value); |     return set_impl<TString*, TValue*>(key, value); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool set(TKey, TValue, uint8_t decimals); |   // bool set(TKey, TValue, uint8_t decimals); | ||||||
| @@ -134,8 +120,7 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // TValue = float, double |   // TValue = float, double | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|   DEPRECATED("Second argument is not supported anymore") |   DEPRECATED("Second argument is not supported anymore") | ||||||
|   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value && |   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value, | ||||||
|                                     !TypeTraits::IsArray<TString>::value, |  | ||||||
|                                 bool>::type |                                 bool>::type | ||||||
|       set(const TString& key, TValue value, uint8_t) { |       set(const TString& key, TValue value, uint8_t) { | ||||||
|     return set_impl<const TString&, const JsonVariant&>(key, |     return set_impl<const TString&, const JsonVariant&>(key, | ||||||
| @@ -143,41 +128,35 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool set(TKey, TValue, uint8_t decimals); |   // bool set(TKey, TValue, uint8_t decimals); | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = char*, const char*, const FlashStringHelper* | ||||||
|   // TValue = float, double |   // TValue = float, double | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|   DEPRECATED("Second argument is not supported anymore") |   DEPRECATED("Second argument is not supported anymore") | ||||||
|   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value, |   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value, | ||||||
|                                 bool>::type |                                 bool>::type | ||||||
|       set(const TString* key, TValue value, uint8_t) { |       set(TString* key, TValue value, uint8_t) { | ||||||
|     return set_impl<const TString*, const JsonVariant&>(key, |     return set_impl<TString*, const JsonVariant&>(key, JsonVariant(value)); | ||||||
|                                                         JsonVariant(value)); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Gets the value associated with the specified key. |   // Gets the value associated with the specified key. | ||||||
|   // |   // | ||||||
|   // TValue get<TValue>(TKey); |   // TValue get<TValue>(TKey) const; | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   // TValue = bool, char, long, int, short, float, double, |   // TValue = bool, char, long, int, short, float, double, | ||||||
|   //          const std::string&, const String&, |   //          std::string, String, JsonArray, JsonObject | ||||||
|   //          const JsonArray&, const JsonObject& |  | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|   typename TypeTraits::EnableIf< |   typename Internals::JsonVariantAs<TValue>::type get( | ||||||
|       !TypeTraits::IsArray<TString>::value, |       const TString& key) const { | ||||||
|       typename Internals::JsonVariantAs<TValue>::type>::type |  | ||||||
|   get(const TString& key) const { |  | ||||||
|     return get_impl<const TString&, TValue>(key); |     return get_impl<const TString&, TValue>(key); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // TValue get<TValue>(TKey); |   // TValue get<TValue>(TKey) const; | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = char*, const char*, const FlashStringHelper* | ||||||
|   // TValue = bool, char, long, int, short, float, double, |   // TValue = bool, char, long, int, short, float, double, | ||||||
|   //          const std::string&, const String&, |   //          std::string, String, JsonArray, JsonObject | ||||||
|   //          const JsonArray&, const JsonObject& |  | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|   typename Internals::JsonVariantAs<TValue>::type get( |   typename Internals::JsonVariantAs<TValue>::type get(TString* key) const { | ||||||
|       const TString* key) const { |     return get_impl<TString*, TValue>(key); | ||||||
|     return get_impl<const TString*, TValue>(key); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Checks the type of the value associated with the specified key. |   // Checks the type of the value associated with the specified key. | ||||||
| @@ -186,23 +165,19 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // bool is<TValue>(TKey) const; |   // bool is<TValue>(TKey) const; | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   // TValue = bool, char, long, int, short, float, double, |   // TValue = bool, char, long, int, short, float, double, | ||||||
|   //          const std::string&, const String&, |   //          std::string, String, JsonArray, JsonObject | ||||||
|   //          const JsonArray&, const JsonObject& |  | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, |   bool is(const TString& key) const { | ||||||
|                                 bool>::type |  | ||||||
|   is(const TString& key) const { |  | ||||||
|     return is_impl<const TString&, TValue>(key); |     return is_impl<const TString&, TValue>(key); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool is<TValue>(TKey) const; |   // bool is<TValue>(TKey) const; | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = char*, const char*, const FlashStringHelper* | ||||||
|   // TValue = bool, char, long, int, short, float, double, |   // TValue = bool, char, long, int, short, float, double, | ||||||
|   //          const std::string&, const String&, |   //          std::string, String, JsonArray, JsonObject | ||||||
|   //          const JsonArray&, const JsonObject& |  | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|   bool is(const TString* key) const { |   bool is(TString* key) const { | ||||||
|     return is_impl<const TString*, TValue>(key); |     return is_impl<TString*, TValue>(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Creates and adds a JsonArray. |   // Creates and adds a JsonArray. | ||||||
| @@ -210,16 +185,14 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // JsonArray& createNestedArray(TKey); |   // JsonArray& createNestedArray(TKey); | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, |   JsonArray& createNestedArray(const TString& key) { | ||||||
|                                 JsonArray&>::type |  | ||||||
|   createNestedArray(const TString& key) { |  | ||||||
|     return createNestedArray_impl<const TString&>(key); |     return createNestedArray_impl<const TString&>(key); | ||||||
|   } |   } | ||||||
|   // JsonArray& createNestedArray(TKey); |   // JsonArray& createNestedArray(TKey); | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = char*, const char*, char[], const char[], const FlashStringHelper* | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   JsonArray& createNestedArray(const TString* key) { |   JsonArray& createNestedArray(TString* key) { | ||||||
|     return createNestedArray_impl<const TString*>(key); |     return createNestedArray_impl<TString*>(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Creates and adds a JsonObject. |   // Creates and adds a JsonObject. | ||||||
| @@ -227,17 +200,15 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // JsonObject& createNestedObject(TKey); |   // JsonObject& createNestedObject(TKey); | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, |   JsonObject& createNestedObject(const TString& key) { | ||||||
|                                 JsonObject&>::type |  | ||||||
|   createNestedObject(const TString& key) { |  | ||||||
|     return createNestedObject_impl<const TString&>(key); |     return createNestedObject_impl<const TString&>(key); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // JsonObject& createNestedObject(TKey); |   // JsonObject& createNestedObject(TKey); | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = char*, const char*, char[], const char[], const FlashStringHelper* | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   JsonObject& createNestedObject(const TString* key) { |   JsonObject& createNestedObject(TString* key) { | ||||||
|     return createNestedObject_impl<const TString*>(key); |     return createNestedObject_impl<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. | ||||||
| @@ -245,17 +216,15 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // bool containsKey(TKey); |   // bool containsKey(TKey); | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, |   bool containsKey(const TString& key) const { | ||||||
|                                 bool>::type |  | ||||||
|   containsKey(const TString& key) const { |  | ||||||
|     return findKey<const TString&>(key) != end(); |     return findKey<const TString&>(key) != end(); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool containsKey(TKey); |   // bool containsKey(TKey); | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = char*, const char*, char[], const char[], const FlashStringHelper* | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   bool containsKey(const TString* key) const { |   bool containsKey(TString* key) const { | ||||||
|     return findKey<const TString*>(key) != end(); |     return findKey<TString*>(key) != end(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Removes the specified key and the associated value. |   // Removes the specified key and the associated value. | ||||||
| @@ -263,17 +232,15 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // void remove(TKey); |   // void remove(TKey); | ||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value, |   void remove(const TString& key) { | ||||||
|                                 void>::type |  | ||||||
|   remove(const TString& key) { |  | ||||||
|     remove(findKey<const TString&>(key)); |     remove(findKey<const TString&>(key)); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // void remove(TKey); |   // void remove(TKey); | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = char*, const char*, char[], const char[], const FlashStringHelper* | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   void remove(const TString* key) { |   void remove(TString* key) { | ||||||
|     remove(findKey<const TString*>(key)); |     remove(findKey<TString*>(key)); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // void remove(iterator) |   // void remove(iterator) | ||||||
| @@ -318,10 +285,10 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|       if (it == end()) return false; |       if (it == end()) return false; | ||||||
|  |  | ||||||
|       bool key_ok = |       bool key_ok = | ||||||
|           Internals::ValueSetter<TStringRef>::set(_buffer, it->key, key); |           Internals::ValueSaver<TStringRef>::save(_buffer, it->key, key); | ||||||
|       if (!key_ok) return false; |       if (!key_ok) return false; | ||||||
|     } |     } | ||||||
|     return Internals::ValueSetter<TValueRef>::set(_buffer, it->value, value); |     return Internals::ValueSaver<TValueRef>::save(_buffer, it->value, value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TStringRef, typename TValue> |   template <typename TStringRef, typename TValue> | ||||||
|   | |||||||
| @@ -31,10 +31,9 @@ class JsonObjectSubscript | |||||||
|  |  | ||||||
|   // Set the specified value |   // Set the specified value | ||||||
|   // |   // | ||||||
|   // operator=(TValue); |   // operator=(const TValue&); | ||||||
|   // TValue = bool, char, long, int, short, float, double, |   // TValue = bool, char, long, int, short, float, double, | ||||||
|   //          const std::string&, const String&, |   //          std::string, String, JsonArray, JsonObject | ||||||
|   //          const JsonArray&, const JsonObject& |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE |   FORCE_INLINE | ||||||
|       typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value, |       typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value, | ||||||
| @@ -45,7 +44,7 @@ class JsonObjectSubscript | |||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // operator=(TValue); |   // operator=(TValue); | ||||||
|   // TValue = const char*, const char[N], const FlashStringHelper* |   // TValue = char*, const char*, const FlashStringHelper* | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE this_type& operator=(const TValue* src) { |   FORCE_INLINE this_type& operator=(const TValue* src) { | ||||||
|     _object.set(_key, src); |     _object.set(_key, src); | ||||||
| @@ -68,10 +67,9 @@ class JsonObjectSubscript | |||||||
|  |  | ||||||
|   // Sets the specified value. |   // Sets the specified value. | ||||||
|   // |   // | ||||||
|   // bool set(TValue); |   // bool set(const TValue&); | ||||||
|   // TValue = bool, char, long, int, short, float, double, RawJson, JsonVariant, |   // TValue = bool, char, long, int, short, float, double, RawJson, JsonVariant, | ||||||
|   //          const std::string&, const String&, |   //          std::string, String, JsonArray, JsonObject | ||||||
|   //          const JsonArray&, const JsonObject& |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE |   FORCE_INLINE | ||||||
|       typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value, |       typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value, | ||||||
| @@ -81,7 +79,7 @@ class JsonObjectSubscript | |||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool set(TValue); |   // bool set(TValue); | ||||||
|   // TValue = const char*, const char[N], const FlashStringHelper* |   // TValue = char*, const char, const FlashStringHelper* | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(const TValue* value) { |   FORCE_INLINE bool set(const TValue* value) { | ||||||
|     return _object.set(_key, value); |     return _object.set(_key, value); | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
|  |  | ||||||
| #ifdef _MSC_VER  // Visual Studio | #ifdef _MSC_VER  // Visual Studio | ||||||
|  |  | ||||||
| #define FORCE_INLINE __forceinline | #define FORCE_INLINE  // __forceinline causes C4714 when returning std::string | ||||||
| #define NO_INLINE __declspec(noinline) | #define NO_INLINE __declspec(noinline) | ||||||
| #define DEPRECATED(msg) __declspec(deprecated(msg)) | #define DEPRECATED(msg) __declspec(deprecated(msg)) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ struct CharPointerTraits { | |||||||
|     return strcmp(reinterpret_cast<const char*>(str), expected) == 0; |     return strcmp(reinterpret_cast<const char*>(str), expected) == 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   // TODO: remove | ||||||
|   template <typename Buffer> |   template <typename Buffer> | ||||||
|   static char* duplicate(const TChar* str, Buffer* buffer) { |   static char* duplicate(const TChar* str, Buffer* buffer) { | ||||||
|     if (!str) return NULL; |     if (!str) return NULL; | ||||||
| @@ -44,12 +45,46 @@ struct CharPointerTraits { | |||||||
|  |  | ||||||
|   static const bool has_append = false; |   static const bool has_append = false; | ||||||
|   static const bool has_equals = true; |   static const bool has_equals = true; | ||||||
|   static const bool should_duplicate = false; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | // const char*, const unsigned char*, const signed char* | ||||||
| template <typename TChar> | template <typename TChar> | ||||||
| struct StringTraits<TChar*, typename TypeTraits::EnableIf< | struct StringTraits<TChar*, typename TypeTraits::EnableIf< | ||||||
|                                 TypeTraits::IsChar<TChar>::value>::type> |                                 TypeTraits::IsChar<TChar>::value && | ||||||
|     : CharPointerTraits<TChar> {}; |                                 TypeTraits::IsConst<TChar>::value>::type> | ||||||
|  |     : CharPointerTraits<TChar> { | ||||||
|  |   // Just save the pointer | ||||||
|  |   template <typename Buffer, typename Destination> | ||||||
|  |   static typename TypeTraits::EnableIf<TypeTraits::IsConst<TChar>::value, | ||||||
|  |                                        bool>::type | ||||||
|  |   save(const TChar* source, Destination& dest, Buffer*) { | ||||||
|  |     dest = reinterpret_cast<const char*>(source); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // char*, unsigned char*, signed char* | ||||||
|  | template <typename TChar> | ||||||
|  | struct StringTraits<TChar*, typename TypeTraits::EnableIf< | ||||||
|  |                                 TypeTraits::IsChar<TChar>::value && | ||||||
|  |                                 !TypeTraits::IsConst<TChar>::value>::type> | ||||||
|  |     : CharPointerTraits<TChar> { | ||||||
|  |   // Make a copy of the string | ||||||
|  |   template <typename Buffer, typename Destination> | ||||||
|  |   static typename TypeTraits::EnableIf<!TypeTraits::IsConst<TChar>::value, | ||||||
|  |                                        bool>::type | ||||||
|  |   save(const TChar* source, Destination& dest, Buffer* buffer) { | ||||||
|  |     if (source) { | ||||||
|  |       size_t size = strlen(reinterpret_cast<const char*>(source)) + 1; | ||||||
|  |       void* dup = buffer->alloc(size); | ||||||
|  |       if (!dup) return false; | ||||||
|  |       memcpy(dup, source, size); | ||||||
|  |       dest = reinterpret_cast<const char*>(dup); | ||||||
|  |     } else { | ||||||
|  |       dest = reinterpret_cast<const char*>(source); | ||||||
|  |     } | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | }; | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -34,6 +34,7 @@ struct StringTraits<const __FlashStringHelper*, void> { | |||||||
|     return strcmp_P(expected, (const char*)str) == 0; |     return strcmp_P(expected, (const char*)str) == 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   // TODO: remove | ||||||
|   template <typename Buffer> |   template <typename Buffer> | ||||||
|   static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) { |   static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) { | ||||||
|     if (!str) return NULL; |     if (!str) return NULL; | ||||||
| @@ -43,9 +44,22 @@ struct StringTraits<const __FlashStringHelper*, void> { | |||||||
|     return static_cast<char*>(dup); |     return static_cast<char*>(dup); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   template <typename Buffer, typename Destination> | ||||||
|  |   static bool save(const __FlashStringHelper* source, Destination& dest, | ||||||
|  |                    Buffer* buffer) { | ||||||
|  |     if (source) { | ||||||
|  |       size_t size = strlen_P((const char*)source) + 1; | ||||||
|  |       void* dup = buffer->alloc(size); | ||||||
|  |       if (dup != NULL) memcpy_P(dup, (const char*)source, size); | ||||||
|  |       dest = reinterpret_cast<const char*>(dup); | ||||||
|  |     } else { | ||||||
|  |       dest = reinterpret_cast<const char*>(source); | ||||||
|  |     } | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   static const bool has_append = false; |   static const bool has_append = false; | ||||||
|   static const bool has_equals = true; |   static const bool has_equals = true; | ||||||
|   static const bool should_duplicate = true; |  | ||||||
| }; | }; | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ namespace Internals { | |||||||
|  |  | ||||||
| template <typename TString> | template <typename TString> | ||||||
| struct StdStringTraits { | struct StdStringTraits { | ||||||
|  |   // TODO: remove | ||||||
|   template <typename Buffer> |   template <typename Buffer> | ||||||
|   static char* duplicate(const TString& str, Buffer* buffer) { |   static char* duplicate(const TString& str, Buffer* buffer) { | ||||||
|     if (!str.c_str()) return NULL;  // <- Arduino string can return NULL |     if (!str.c_str()) return NULL;  // <- Arduino string can return NULL | ||||||
| @@ -28,6 +29,21 @@ struct StdStringTraits { | |||||||
|     return static_cast<char*>(dup); |     return static_cast<char*>(dup); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   template <typename Buffer, typename Destination> | ||||||
|  |   static bool save(const TString& str, Destination& dest, Buffer* buffer) { | ||||||
|  |     // Arduino's String::c_str() can return NULL | ||||||
|  |     if (str.c_str()) { | ||||||
|  |       size_t size = str.length() + 1; | ||||||
|  |       void* dup = buffer->alloc(size); | ||||||
|  |       if (!dup) return false; | ||||||
|  |       memcpy(dup, str.c_str(), size); | ||||||
|  |       dest = reinterpret_cast<const char*>(dup); | ||||||
|  |     } else { | ||||||
|  |       dest = str.c_str(); | ||||||
|  |     } | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   struct Reader : CharPointerTraits<char>::Reader { |   struct Reader : CharPointerTraits<char>::Reader { | ||||||
|     Reader(const TString& str) : CharPointerTraits<char>::Reader(str.c_str()) {} |     Reader(const TString& str) : CharPointerTraits<char>::Reader(str.c_str()) {} | ||||||
|   }; |   }; | ||||||
| @@ -46,7 +62,6 @@ struct StdStringTraits { | |||||||
|  |  | ||||||
|   static const bool has_append = true; |   static const bool has_append = true; | ||||||
|   static const bool has_equals = true; |   static const bool has_equals = true; | ||||||
|   static const bool should_duplicate = true; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #if ARDUINOJSON_ENABLE_ARDUINO_STRING | #if ARDUINOJSON_ENABLE_ARDUINO_STRING | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ | |||||||
| #include "../TypeTraits/EnableIf.hpp" | #include "../TypeTraits/EnableIf.hpp" | ||||||
| #include "../TypeTraits/IsBaseOf.hpp" | #include "../TypeTraits/IsBaseOf.hpp" | ||||||
| #include "../TypeTraits/IsChar.hpp" | #include "../TypeTraits/IsChar.hpp" | ||||||
|  | #include "../TypeTraits/IsConst.hpp" | ||||||
| #include "../TypeTraits/RemoveReference.hpp" | #include "../TypeTraits/RemoveReference.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ add_executable(JsonArrayTests | |||||||
| 	printTo.cpp | 	printTo.cpp | ||||||
| 	remove.cpp | 	remove.cpp | ||||||
| 	set.cpp | 	set.cpp | ||||||
|  | 	size.cpp | ||||||
| 	subscript.cpp | 	subscript.cpp | ||||||
| ) | ) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,11 +9,6 @@ TEST_CASE("JsonArray::add()") { | |||||||
|   DynamicJsonBuffer _jsonBuffer; |   DynamicJsonBuffer _jsonBuffer; | ||||||
|   JsonArray& _array = _jsonBuffer.createArray(); |   JsonArray& _array = _jsonBuffer.createArray(); | ||||||
|  |  | ||||||
|   SECTION("SizeIncreased_WhenValuesAreAdded") { |  | ||||||
|     _array.add("hello"); |  | ||||||
|     REQUIRE(1U == _array.size()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("int") { |   SECTION("int") { | ||||||
|     _array.add(123); |     _array.add(123); | ||||||
|     REQUIRE(123 == _array[0].as<int>()); |     REQUIRE(123 == _array[0].as<int>()); | ||||||
| @@ -38,7 +33,7 @@ TEST_CASE("JsonArray::add()") { | |||||||
|   SECTION("const char*") { |   SECTION("const char*") { | ||||||
|     const char* str = "hello"; |     const char* str = "hello"; | ||||||
|     _array.add(str); |     _array.add(str); | ||||||
|     REQUIRE(str == _array[0].as<const char*>()); |     REQUIRE(str == _array[0].as<std::string>()); | ||||||
|     REQUIRE(_array[0].is<const char*>()); |     REQUIRE(_array[0].is<const char*>()); | ||||||
|     REQUIRE_FALSE(_array[0].is<int>()); |     REQUIRE_FALSE(_array[0].is<int>()); | ||||||
|   } |   } | ||||||
| @@ -82,4 +77,22 @@ TEST_CASE("JsonArray::add()") { | |||||||
|  |  | ||||||
|     REQUIRE(str == _array[0]); |     REQUIRE(str == _array[0]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("should not duplicate const char*") { | ||||||
|  |     _array.add("world"); | ||||||
|  |     const size_t expectedSize = JSON_ARRAY_SIZE(1); | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate  char*") { | ||||||
|  |     _array.add(const_cast<char*>("world")); | ||||||
|  |     const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate std::string") { | ||||||
|  |     _array.add(std::string("world")); | ||||||
|  |     const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -12,11 +12,6 @@ TEST_CASE("JsonArray::set()") { | |||||||
|   JsonArray& _array = _jsonBuffer.createArray(); |   JsonArray& _array = _jsonBuffer.createArray(); | ||||||
|   _array.add(0); |   _array.add(0); | ||||||
|  |  | ||||||
|   SECTION("SizeIsUnchanged") { |  | ||||||
|     _array.set(0, "hello"); |  | ||||||
|     REQUIRE(1U == _array.size()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("int") { |   SECTION("int") { | ||||||
|     _array.set(0, 123); |     _array.set(0, 123); | ||||||
|     REQUIRE(123 == _array[0].as<int>()); |     REQUIRE(123 == _array[0].as<int>()); | ||||||
| @@ -82,4 +77,22 @@ TEST_CASE("JsonArray::set()") { | |||||||
|  |  | ||||||
|     REQUIRE_THAT(_array[0].as<char*>(), Equals("hello")); |     REQUIRE_THAT(_array[0].as<char*>(), Equals("hello")); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("should not duplicate const char*") { | ||||||
|  |     _array.set(0, "world"); | ||||||
|  |     const size_t expectedSize = JSON_ARRAY_SIZE(1); | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate char*") { | ||||||
|  |     _array.set(0, const_cast<char*>("world")); | ||||||
|  |     const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate std::string") { | ||||||
|  |     _array.set(0, std::string("world")); | ||||||
|  |     const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										35
									
								
								test/JsonArray/size.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								test/JsonArray/size.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonArray::size()") { | ||||||
|  |   DynamicJsonBuffer _jsonBuffer; | ||||||
|  |   JsonArray& _array = _jsonBuffer.createArray(); | ||||||
|  |  | ||||||
|  |   SECTION("increases after add()") { | ||||||
|  |     _array.add("hello"); | ||||||
|  |     REQUIRE(1U == _array.size()); | ||||||
|  |  | ||||||
|  |     _array.add("world"); | ||||||
|  |     REQUIRE(2U == _array.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("remains the same after set()") { | ||||||
|  |     _array.add("hello"); | ||||||
|  |     REQUIRE(1U == _array.size()); | ||||||
|  |  | ||||||
|  |     _array.set(0, "hello"); | ||||||
|  |     REQUIRE(1U == _array.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("remains the same after assigment") { | ||||||
|  |     _array.add("hello"); | ||||||
|  |     REQUIRE(1U == _array.size()); | ||||||
|  |  | ||||||
|  |     _array[0] = "hello"; | ||||||
|  |     REQUIRE(1U == _array.size()); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -11,11 +11,6 @@ TEST_CASE("JsonArray::operator[]") { | |||||||
|   JsonArray& _array = _jsonBuffer.createArray(); |   JsonArray& _array = _jsonBuffer.createArray(); | ||||||
|   _array.add(0); |   _array.add(0); | ||||||
|  |  | ||||||
|   SECTION("SizeIsUnchanged") { |  | ||||||
|     _array[0] = "hello"; |  | ||||||
|     REQUIRE(1U == _array.size()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("int") { |   SECTION("int") { | ||||||
|     _array[0] = 123; |     _array[0] = 123; | ||||||
|     REQUIRE(123 == _array[0].as<int>()); |     REQUIRE(123 == _array[0].as<int>()); | ||||||
| @@ -103,4 +98,22 @@ TEST_CASE("JsonArray::operator[]") { | |||||||
|  |  | ||||||
|     REQUIRE(str == _array[0]); |     REQUIRE(str == _array[0]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("should not duplicate const char*") { | ||||||
|  |     _array[0] = "world"; | ||||||
|  |     const size_t expectedSize = JSON_ARRAY_SIZE(1); | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate char*") { | ||||||
|  |     _array[0] = const_cast<char*>("world"); | ||||||
|  |     const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate std::string") { | ||||||
|  |     _array[0] = std::string("world"); | ||||||
|  |     const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ add_executable(JsonObjectTests | |||||||
| 	printTo.cpp | 	printTo.cpp | ||||||
| 	remove.cpp | 	remove.cpp | ||||||
| 	set.cpp | 	set.cpp | ||||||
|  | 	size.cpp | ||||||
| 	subscript.cpp | 	subscript.cpp | ||||||
| ) | ) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,17 +10,6 @@ TEST_CASE("JsonObject::set()") { | |||||||
|   DynamicJsonBuffer jb; |   DynamicJsonBuffer jb; | ||||||
|   JsonObject& _object = jb.createObject(); |   JsonObject& _object = jb.createObject(); | ||||||
|  |  | ||||||
|   SECTION("SizeIncreased_WhenValuesAreAdded") { |  | ||||||
|     _object.set("hello", 42); |  | ||||||
|     REQUIRE(1 == _object.size()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("SizeUntouched_WhenSameValueIsAdded") { |  | ||||||
|     _object["hello"] = 1; |  | ||||||
|     _object["hello"] = 2; |  | ||||||
|     REQUIRE(1 == _object.size()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("int") { |   SECTION("int") { | ||||||
|     _object.set("hello", 123); |     _object.set("hello", 123); | ||||||
|  |  | ||||||
| @@ -91,17 +80,59 @@ TEST_CASE("JsonObject::set()") { | |||||||
|     REQUIRE(42 == _object["a"]); |     REQUIRE(42 == _object["a"]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("ShouldReturnTrue_WhenAllocationSucceeds") { |   SECTION("returns true when allocation succeeds") { | ||||||
|     StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 15> jsonBuffer; |     StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 15> jsonBuffer; | ||||||
|     JsonObject& obj = jsonBuffer.createObject(); |     JsonObject& obj = jsonBuffer.createObject(); | ||||||
|  |  | ||||||
|     REQUIRE(true == obj.set(std::string("hello"), std::string("world"))); |     REQUIRE(true == obj.set(std::string("hello"), std::string("world"))); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("ShouldReturnFalse_WhenAllocationFails") { |   SECTION("returns false when allocation fails") { | ||||||
|     StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 10> jsonBuffer; |     StaticJsonBuffer<JSON_OBJECT_SIZE(1) + 10> jsonBuffer; | ||||||
|     JsonObject& obj = jsonBuffer.createObject(); |     JsonObject& obj = jsonBuffer.createObject(); | ||||||
|  |  | ||||||
|     REQUIRE(false == obj.set(std::string("hello"), std::string("world"))); |     REQUIRE(false == obj.set(std::string("hello"), std::string("world"))); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("should not duplicate const char*") { | ||||||
|  |     _object.set("hello", "world"); | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1); | ||||||
|  |     REQUIRE(expectedSize == jb.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate char* value") { | ||||||
|  |     _object.set("hello", const_cast<char*>("world")); | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == jb.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate char* key") { | ||||||
|  |     _object.set(const_cast<char*>("hello"), "world"); | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == jb.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate char* key&value") { | ||||||
|  |     _object.set(const_cast<char*>("hello"), const_cast<char*>("world")); | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12; | ||||||
|  |     REQUIRE(expectedSize <= jb.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate std::string value") { | ||||||
|  |     _object.set("hello", std::string("world")); | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == jb.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate std::string key") { | ||||||
|  |     _object.set(std::string("hello"), "world"); | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == jb.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate std::string key&value") { | ||||||
|  |     _object.set(std::string("hello"), std::string("world")); | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12; | ||||||
|  |     REQUIRE(expectedSize <= jb.size()); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								test/JsonObject/size.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								test/JsonObject/size.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2018 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  | #include <string> | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonObject::size()") { | ||||||
|  |   DynamicJsonBuffer jb; | ||||||
|  |   JsonObject& _object = jb.createObject(); | ||||||
|  |  | ||||||
|  |   SECTION("increases when values are added") { | ||||||
|  |     _object.set("hello", 42); | ||||||
|  |     REQUIRE(1 == _object.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("doesn't increase when the smae key is added twice") { | ||||||
|  |     _object["hello"] = 1; | ||||||
|  |     _object["hello"] = 2; | ||||||
|  |     REQUIRE(1 == _object.size()); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -9,17 +9,6 @@ TEST_CASE("JsonObject::operator[]") { | |||||||
|   DynamicJsonBuffer _jsonBuffer; |   DynamicJsonBuffer _jsonBuffer; | ||||||
|   JsonObject& _object = _jsonBuffer.createObject(); |   JsonObject& _object = _jsonBuffer.createObject(); | ||||||
|  |  | ||||||
|   SECTION("SizeIncreased_WhenValuesAreAdded") { |  | ||||||
|     _object["hello"] = 1; |  | ||||||
|     REQUIRE(1 == _object.size()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("SizeUntouched_WhenSameValueIsAdded") { |  | ||||||
|     _object["hello"] = 1; |  | ||||||
|     _object["hello"] = 2; |  | ||||||
|     REQUIRE(1 == _object.size()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("int") { |   SECTION("int") { | ||||||
|     _object["hello"] = 123; |     _object["hello"] = 123; | ||||||
|  |  | ||||||
| @@ -113,9 +102,51 @@ TEST_CASE("JsonObject::operator[]") { | |||||||
|     REQUIRE(42 == _object["a"]); |     REQUIRE(42 == _object["a"]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("KeyAsCharArray") {  // issue #423 |   SECTION("char key[]") {  // issue #423 | ||||||
|     char key[] = "hello"; |     char key[] = "hello"; | ||||||
|     _object[key] = 42; |     _object[key] = 42; | ||||||
|     REQUIRE(42 == _object[key]); |     REQUIRE(42 == _object[key]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("should not duplicate const char*") { | ||||||
|  |     _object["hello"] = "world"; | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1); | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate char* value") { | ||||||
|  |     _object["hello"] = const_cast<char*>("world"); | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate char* key") { | ||||||
|  |     _object[const_cast<char*>("hello")] = "world"; | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate char* key&value") { | ||||||
|  |     _object[const_cast<char*>("hello")] = const_cast<char*>("world"); | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12; | ||||||
|  |     REQUIRE(expectedSize <= _jsonBuffer.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate std::string value") { | ||||||
|  |     _object["hello"] = std::string("world"); | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate std::string key") { | ||||||
|  |     _object[std::string("hello")] = "world"; | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; | ||||||
|  |     REQUIRE(expectedSize == _jsonBuffer.size()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate std::string key&value") { | ||||||
|  |     _object[std::string("hello")] = std::string("world"); | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12; | ||||||
|  |     REQUIRE(expectedSize <= _jsonBuffer.size()); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -36,4 +36,9 @@ TEST_CASE("TypeTraits") { | |||||||
|     REQUIRE((IsString<std::string>::value)); |     REQUIRE((IsString<std::string>::value)); | ||||||
|     REQUIRE_FALSE((IsString<double>::value)); |     REQUIRE_FALSE((IsString<double>::value)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("IsConst") { | ||||||
|  |     REQUIRE_FALSE((IsConst<char>::value)); | ||||||
|  |     REQUIRE((IsConst<const char>::value)); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user