mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Added support for custom converters (closes #687)
This commit is contained in:
		| @@ -27,7 +27,7 @@ | ||||
| #include "ArduinoJson/Collection/CollectionImpl.hpp" | ||||
| #include "ArduinoJson/Object/MemberProxy.hpp" | ||||
| #include "ArduinoJson/Object/ObjectImpl.hpp" | ||||
| #include "ArduinoJson/Variant/VariantAsImpl.hpp" | ||||
| #include "ArduinoJson/Variant/ConverterImpl.hpp" | ||||
| #include "ArduinoJson/Variant/VariantCompare.hpp" | ||||
| #include "ArduinoJson/Variant/VariantImpl.hpp" | ||||
|  | ||||
|   | ||||
| @@ -164,4 +164,42 @@ class ArrayRef : public ArrayRefBase<CollectionData>, | ||||
|  private: | ||||
|   MemoryPool* _pool; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct Converter<ArrayConstRef> { | ||||
|   static bool toJson(VariantRef variant, VariantConstRef value) { | ||||
|     return variantCopyFrom(getData(variant), getData(value), getPool(variant)); | ||||
|   } | ||||
|  | ||||
|   static ArrayConstRef fromJson(VariantConstRef variant) { | ||||
|     return ArrayConstRef(variantAsArray(getData(variant))); | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef variant) { | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data && data->isArray(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct Converter<ArrayRef> { | ||||
|   static bool toJson(VariantRef variant, VariantConstRef value) { | ||||
|     return variantCopyFrom(getData(variant), getData(value), getPool(variant)); | ||||
|   } | ||||
|  | ||||
|   static ArrayRef fromJson(VariantRef variant) { | ||||
|     VariantData* data = getData(variant); | ||||
|     MemoryPool* pool = getPool(variant); | ||||
|     return ArrayRef(pool, data != 0 ? data->asArray() : 0); | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantRef variant) { | ||||
|     VariantData* data = getData(variant); | ||||
|     return data && data->isArray(); | ||||
|   } | ||||
| }; | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
| @@ -9,6 +9,8 @@ | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
| // Forward declarations. | ||||
| class ArrayRef; | ||||
| class ObjectRef; | ||||
| template <typename> | ||||
| class ElementProxy; | ||||
|  | ||||
|   | ||||
| @@ -170,6 +170,10 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | ||||
|     return _array.getOrAddElement(_index); | ||||
|   } | ||||
|  | ||||
|   friend bool convertToJson(VariantRef variant, const this_type& value) { | ||||
|     return variant.set(value.getUpstreamElement()); | ||||
|   } | ||||
|  | ||||
|   TArray _array; | ||||
|   const size_t _index; | ||||
| }; | ||||
|   | ||||
| @@ -76,7 +76,8 @@ class ArrayCopier1D : public Visitor<size_t> { | ||||
|     VariantSlot* slot = array.head(); | ||||
|  | ||||
|     while (slot != 0 && size < _capacity) { | ||||
|       _destination[size++] = variantAs<T>(slot->data()); | ||||
|       _destination[size++] = | ||||
|           Converter<T>::fromJson(VariantConstRef(slot->data())); | ||||
|       slot = slot->next(); | ||||
|     } | ||||
|     return size; | ||||
|   | ||||
| @@ -337,4 +337,8 @@ class JsonDocument : public Visitable { | ||||
|   JsonDocument& operator=(const JsonDocument&); | ||||
| }; | ||||
|  | ||||
| inline bool convertToJson(VariantRef variant, const JsonDocument& doc) { | ||||
|   return variant.set(doc.as<VariantConstRef>()); | ||||
| } | ||||
|  | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
| @@ -10,7 +10,7 @@ | ||||
| #include <ArduinoJson/Polyfills/ctype.hpp> | ||||
| #include <ArduinoJson/Polyfills/math.hpp> | ||||
| #include <ArduinoJson/Polyfills/type_traits.hpp> | ||||
| #include <ArduinoJson/Variant/VariantAs.hpp> | ||||
| #include <ArduinoJson/Variant/Converter.hpp> | ||||
| #include <ArduinoJson/Variant/VariantData.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
| @@ -142,6 +142,6 @@ inline T parseNumber(const char* s) { | ||||
|   VariantData value; | ||||
|   value.init();  // VariantData is a POD, so it has no constructor | ||||
|   parseNumber(s, value); | ||||
|   return variantAs<T>(&value); | ||||
|   return Converter<T>::fromJson(VariantConstRef(&value)); | ||||
| } | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
| @@ -193,6 +193,10 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >, | ||||
|     return _object.getOrAddMember(_key); | ||||
|   } | ||||
|  | ||||
|   friend bool convertToJson(VariantRef variant, const this_type &value) { | ||||
|     return variant.set(value.getUpstreamMember()); | ||||
|   } | ||||
|  | ||||
|   TObject _object; | ||||
|   TStringRef _key; | ||||
| }; | ||||
|   | ||||
| @@ -236,4 +236,42 @@ class ObjectRef : public ObjectRefBase<CollectionData>, | ||||
|  private: | ||||
|   MemoryPool* _pool; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct Converter<ObjectConstRef> { | ||||
|   static bool toJson(VariantRef variant, VariantConstRef value) { | ||||
|     return variantCopyFrom(getData(variant), getData(value), getPool(variant)); | ||||
|   } | ||||
|  | ||||
|   static ObjectConstRef fromJson(VariantConstRef variant) { | ||||
|     return ObjectConstRef(variantAsObject(getData(variant))); | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef variant) { | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data && data->isObject(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct Converter<ObjectRef> { | ||||
|   static bool toJson(VariantRef variant, VariantConstRef value) { | ||||
|     return variantCopyFrom(getData(variant), getData(value), getPool(variant)); | ||||
|   } | ||||
|  | ||||
|   static ObjectRef fromJson(VariantRef variant) { | ||||
|     VariantData* data = getData(variant); | ||||
|     MemoryPool* pool = getPool(variant); | ||||
|     return ObjectRef(pool, data != 0 ? data->asObject() : 0); | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantRef variant) { | ||||
|     VariantData* data = getData(variant); | ||||
|     return data && data->isObject(); | ||||
|   } | ||||
| }; | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
							
								
								
									
										12
									
								
								src/ArduinoJson/Variant/Converter.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/ArduinoJson/Variant/Converter.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| // ArduinoJson - arduinojson.org | ||||
| // Copyright Benoit Blanchon 2014-2021 | ||||
| // MIT License | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename T, typename Enable = void> | ||||
| struct Converter; | ||||
|  | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
							
								
								
									
										209
									
								
								src/ArduinoJson/Variant/ConverterImpl.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								src/ArduinoJson/Variant/ConverterImpl.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,209 @@ | ||||
| // ArduinoJson - arduinojson.org | ||||
| // Copyright Benoit Blanchon 2014-2021 | ||||
| // MIT License | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <ArduinoJson/Strings/IsWriteableString.hpp> | ||||
| #include <ArduinoJson/Variant/VariantFunctions.hpp> | ||||
| #include <ArduinoJson/Variant/VariantRef.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename T, typename Enable> | ||||
| struct Converter { | ||||
|   static bool toJson(VariantRef variant, const T& value) { | ||||
|     // clang-format off | ||||
|     return convertToJson(variant, value); // Error here? See https://arduinojson.org/v6/unsupported-set/ | ||||
|     // clang-format on | ||||
|   } | ||||
|  | ||||
|   static T fromJson(VariantConstRef variant) { | ||||
|     // clang-format off | ||||
|     T value; // Error here? See https://arduinojson.org/v6/non-default-constructible/ | ||||
|     convertFromJson(value, variant);  // Error here? See https://arduinojson.org/v6/unsupported-as/ | ||||
|     // clang-format on | ||||
|     return value; | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef variant) { | ||||
|     T dummy; | ||||
|     // clang-format off | ||||
|     return canConvertFromJson(dummy, variant);  // Error here? See https://arduinojson.org/v6/unsupported-is/ | ||||
|     // clang-format on | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| struct Converter< | ||||
|     T, typename enable_if<is_integral<T>::value && !is_same<bool, T>::value && | ||||
|                           !is_same<char, T>::value>::type> { | ||||
|   static bool toJson(VariantRef variant, T value) { | ||||
|     VariantData* data = getData(variant); | ||||
|     ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); | ||||
|     if (!data) | ||||
|       return false; | ||||
|     data->setInteger(value); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   static T fromJson(VariantConstRef variant) { | ||||
|     ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data ? data->asIntegral<T>() : T(); | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef variant) { | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data && data->isInteger<T>(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| struct Converter<T, typename enable_if<is_enum<T>::value>::type> { | ||||
|   static bool toJson(VariantRef variant, T value) { | ||||
|     return variant.set(static_cast<Integer>(value)); | ||||
|   } | ||||
|  | ||||
|   static T fromJson(VariantConstRef variant) { | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data ? static_cast<T>(data->asIntegral<int>()) : T(); | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef variant) { | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data && data->isInteger<int>(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct Converter<bool> { | ||||
|   static bool toJson(VariantRef variant, bool value) { | ||||
|     VariantData* data = getData(variant); | ||||
|     if (!data) | ||||
|       return false; | ||||
|     data->setBoolean(value); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   static bool fromJson(VariantConstRef variant) { | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data ? data->asBoolean() : false; | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef variant) { | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data && data->isBoolean(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| struct Converter<T, typename enable_if<is_floating_point<T>::value>::type> { | ||||
|   static bool toJson(VariantRef variant, T value) { | ||||
|     VariantData* data = getData(variant); | ||||
|     if (!data) | ||||
|       return false; | ||||
|     data->setFloat(static_cast<Float>(value)); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   static T fromJson(VariantConstRef variant) { | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data ? data->asFloat<T>() : false; | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef variant) { | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data && data->isFloat(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct Converter<const char*> { | ||||
|   static bool toJson(VariantRef variant, const char* value) { | ||||
|     // TODO: don't pass pool | ||||
|     return variantSetString(getData(variant), adaptString(value), | ||||
|                             getPool(variant)); | ||||
|   } | ||||
|  | ||||
|   static const char* fromJson(VariantConstRef variant) { | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data ? data->asString() : 0; | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef variant) { | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data && data->isString(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<IsString<T>::value, bool>::type convertToJson( | ||||
|     VariantRef variant, const T& value) { | ||||
|   VariantData* data = getData(variant); | ||||
|   MemoryPool* pool = getPool(variant); | ||||
|   return variantSetString(data, adaptString(value), pool); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<IsWriteableString<T>::value>::type convertFromJson( | ||||
|     T& value, VariantConstRef variant) { | ||||
|   const VariantData* data = getData(variant); | ||||
|   const char* cstr = data != 0 ? data->asString() : 0; | ||||
|   if (cstr) | ||||
|     value = cstr; | ||||
|   else | ||||
|     serializeJson(variant, value); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<IsWriteableString<T>::value, bool>::type | ||||
| canConvertFromJson(T&, VariantConstRef variant) { | ||||
|   const VariantData* data = getData(variant); | ||||
|   return data && data->isString(); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| struct Converter<SerializedValue<const char*> > { | ||||
|   static bool toJson(VariantRef variant, SerializedValue<const char*> value) { | ||||
|     VariantData* data = getData(variant); | ||||
|     if (!data) | ||||
|       return false; | ||||
|     data->setLinkedRaw(value); | ||||
|     return true; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| // SerializedValue<std::string> | ||||
| // SerializedValue<String> | ||||
| // SerializedValue<const __FlashStringHelper*> | ||||
| template <typename T> | ||||
| struct Converter<SerializedValue<T>, | ||||
|                  typename enable_if<!is_same<const char*, T>::value>::type> { | ||||
|   static bool toJson(VariantRef variant, SerializedValue<T> value) { | ||||
|     VariantData* data = getData(variant); | ||||
|     MemoryPool* pool = getPool(variant); | ||||
|     return data != 0 && data->setOwnedRaw(value, pool); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| #if ARDUINOJSON_HAS_NULLPTR | ||||
|  | ||||
| template <> | ||||
| struct Converter<decltype(nullptr)> { | ||||
|   static bool toJson(VariantRef variant, decltype(nullptr)) { | ||||
|     variantSetNull(getData(variant)); | ||||
|     return true; | ||||
|   } | ||||
|   static decltype(nullptr) fromJson(VariantConstRef) { | ||||
|     return nullptr; | ||||
|   } | ||||
|   static bool checkJson(VariantConstRef variant) { | ||||
|     const VariantData* data = getData(variant); | ||||
|     return data == 0 || data->isNull(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
| @@ -1,76 +0,0 @@ | ||||
| // ArduinoJson - arduinojson.org | ||||
| // Copyright Benoit Blanchon 2014-2021 | ||||
| // MIT License | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <ArduinoJson/Strings/IsWriteableString.hpp> | ||||
| #include <ArduinoJson/Variant/VariantData.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| class ArrayRef; | ||||
| class ArrayConstRef; | ||||
| class ObjectRef; | ||||
| class ObjectConstRef; | ||||
| class VariantRef; | ||||
| class VariantConstRef; | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<is_integral<T>::value && !is_same<bool, T>::value && | ||||
|                               !is_same<char, T>::value, | ||||
|                           T>::type | ||||
| variantAs(const VariantData* data) { | ||||
|   ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); | ||||
|   return data != 0 ? data->asIntegral<T>() : T(0); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<is_enum<T>::value, T>::type variantAs( | ||||
|     const VariantData* data) { | ||||
|   return data != 0 ? static_cast<T>(data->asIntegral<int>()) : T(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<is_same<T, bool>::value, T>::type variantAs( | ||||
|     const VariantData* data) { | ||||
|   return data != 0 ? data->asBoolean() : false; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<is_floating_point<T>::value, T>::type variantAs( | ||||
|     const VariantData* data) { | ||||
|   return data != 0 ? data->asFloat<T>() : T(0); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<is_same<T, const char*>::value, T>::type variantAs( | ||||
|     const VariantData* data) { | ||||
|   return data != 0 ? data->asString() : 0; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| T variantAs(VariantData* data, MemoryPool*) { | ||||
|   // By default use the read-only conversion. | ||||
|   // There are specializations for | ||||
|   // - ArrayRef | ||||
|   return variantAs<T>(data); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<is_same<ArrayConstRef, T>::value, T>::type variantAs( | ||||
|     const VariantData* data); | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<is_same<ObjectConstRef, T>::value, T>::type variantAs( | ||||
|     const VariantData* data); | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type | ||||
| variantAs(const VariantData* data); | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs( | ||||
|     const VariantData* data); | ||||
|  | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
| @@ -1,57 +0,0 @@ | ||||
| // ArduinoJson - arduinojson.org | ||||
| // Copyright Benoit Blanchon 2014-2021 | ||||
| // MIT License | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <ArduinoJson/Strings/IsWriteableString.hpp> | ||||
| #include <ArduinoJson/Variant/VariantFunctions.hpp> | ||||
| #include <ArduinoJson/Variant/VariantRef.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<is_same<ArrayConstRef, T>::value, T>::type variantAs( | ||||
|     const VariantData* _data) { | ||||
|   return ArrayConstRef(variantAsArray(_data)); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<is_same<ObjectConstRef, T>::value, T>::type variantAs( | ||||
|     const VariantData* _data) { | ||||
|   return ObjectConstRef(variantAsObject(_data)); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type | ||||
| variantAs(const VariantData* _data) { | ||||
|   return VariantConstRef(_data); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs( | ||||
|     const VariantData* _data) { | ||||
|   const char* cstr = _data != 0 ? _data->asString() : 0; | ||||
|   if (cstr) | ||||
|     return T(cstr); | ||||
|   T s; | ||||
|   serializeJson(VariantConstRef(_data), s); | ||||
|   return s; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline ArrayRef variantAs<ArrayRef>(VariantData* data, MemoryPool* pool) { | ||||
|   return ArrayRef(pool, data != 0 ? data->asArray() : 0); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline ObjectRef variantAs<ObjectRef>(VariantData* data, MemoryPool* pool) { | ||||
|   return ObjectRef(pool, data != 0 ? data->asObject() : 0); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline VariantRef variantAs<VariantRef>(VariantData* data, MemoryPool* pool) { | ||||
|   return VariantRef(pool, data); | ||||
| } | ||||
|  | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
| @@ -43,34 +43,6 @@ inline bool variantCopyFrom(VariantData *dst, const VariantData *src, | ||||
|  | ||||
| inline int variantCompare(const VariantData *a, const VariantData *b); | ||||
|  | ||||
| inline bool variantSetBoolean(VariantData *var, bool value) { | ||||
|   if (!var) | ||||
|     return false; | ||||
|   var->setBoolean(value); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| inline bool variantSetFloat(VariantData *var, Float value) { | ||||
|   if (!var) | ||||
|     return false; | ||||
|   var->setFloat(value); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| inline bool variantSetLinkedRaw(VariantData *var, | ||||
|                                 SerializedValue<const char *> value) { | ||||
|   if (!var) | ||||
|     return false; | ||||
|   var->setLinkedRaw(value); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool variantSetOwnedRaw(VariantData *var, SerializedValue<T> value, | ||||
|                                MemoryPool *pool) { | ||||
|   return var != 0 && var->setOwnedRaw(value, pool); | ||||
| } | ||||
|  | ||||
| inline void variantSetNull(VariantData *var) { | ||||
|   if (!var) | ||||
|     return; | ||||
| @@ -85,15 +57,6 @@ inline bool variantSetString(VariantData *var, TAdaptedString value, | ||||
|   return var->setString(value, pool); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline bool variantSetInteger(VariantData *var, T value) { | ||||
|   ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); | ||||
|   if (!var) | ||||
|     return false; | ||||
|   var->setInteger(value); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| inline size_t variantSize(const VariantData *var) { | ||||
|   return var != 0 ? var->size() : 0; | ||||
| } | ||||
| @@ -134,4 +97,8 @@ NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, | ||||
|   return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0; | ||||
| } | ||||
|  | ||||
| inline bool variantIsNull(const VariantData *var) { | ||||
|   return var == 0 || var->isNull(); | ||||
| } | ||||
|  | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
| @@ -77,13 +77,6 @@ inline const char *VariantData::asString() const { | ||||
|   } | ||||
| } | ||||
|  | ||||
| template <typename TVariant> | ||||
| typename enable_if<IsVisitable<TVariant>::value, bool>::type VariantRef::set( | ||||
|     const TVariant &value) const { | ||||
|   VariantConstRef v = value; | ||||
|   return variantCopyFrom(_data, v._data, _pool); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type | ||||
| VariantRef::to() const { | ||||
|   | ||||
| @@ -1,146 +0,0 @@ | ||||
| // ArduinoJson - arduinojson.org | ||||
| // Copyright Benoit Blanchon 2014-2021 | ||||
| // MIT License | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <ArduinoJson/Polyfills/type_traits.hpp> | ||||
| #include <ArduinoJson/Variant/VariantFunctions.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| inline bool variantIsNull(const VariantData *var) { | ||||
|   return var == 0 || var->isNull(); | ||||
| } | ||||
|  | ||||
| // bool is<char>() const; | ||||
| // bool is<signed char>() const; | ||||
| // bool is<signed short>() const; | ||||
| // bool is<signed int>() const; | ||||
| // bool is<signed long>() const; | ||||
| // bool is<unsigned char>() const; | ||||
| // bool is<unsigned short>() const; | ||||
| // bool is<unsigned int>() const; | ||||
| // bool is<unsigned long>() const; | ||||
| template <typename T> | ||||
| NO_INLINE typename enable_if<is_integral<T>::value && !is_same<bool, T>::value, | ||||
|                              bool>::type | ||||
| variantIs(const VariantData *var) { | ||||
|   return var && var->isInteger<T>(); | ||||
| } | ||||
|  | ||||
| // bool is<double>() const; | ||||
| // bool is<float>() const; | ||||
| template <typename T> | ||||
| NO_INLINE typename enable_if<is_floating_point<T>::value, bool>::type variantIs( | ||||
|     const VariantData *var) { | ||||
|   return var && var->isFloat(); | ||||
| } | ||||
|  | ||||
| // bool is<bool>() const | ||||
| template <typename T> | ||||
| NO_INLINE typename enable_if<is_same<T, bool>::value, bool>::type variantIs( | ||||
|     const VariantData *var) { | ||||
|   return var && var->isBoolean(); | ||||
| } | ||||
|  | ||||
| // bool is<const char*>() const; | ||||
| // bool is<char*>() const; | ||||
| // bool is<std::string>() const; | ||||
| // bool is<String>() const; | ||||
| template <typename T> | ||||
| NO_INLINE typename enable_if<is_same<T, const char *>::value || | ||||
|                                  is_same<T, char *>::value || | ||||
|                                  IsWriteableString<T>::value, | ||||
|                              bool>::type | ||||
| variantIs(const VariantData *var) { | ||||
|   return var && var->isString(); | ||||
| } | ||||
|  | ||||
| // bool is<ArrayConstRef> const; | ||||
| // bool is<const ArrayConstRef> const; | ||||
| template <typename T> | ||||
| NO_INLINE typename enable_if< | ||||
|     is_same<typename remove_const<T>::type, ArrayConstRef>::value, bool>::type | ||||
| variantIs(const VariantData *var) { | ||||
|   return var && var->isArray(); | ||||
| } | ||||
|  | ||||
| // bool is<ObjectConstRef> const; | ||||
| // bool is<const ObjectConstRef> const; | ||||
| template <typename T> | ||||
| NO_INLINE typename enable_if< | ||||
|     is_same<typename remove_const<T>::type, ObjectConstRef>::value, bool>::type | ||||
| variantIs(const VariantData *var) { | ||||
|   return var && var->isObject(); | ||||
| } | ||||
|  | ||||
| // bool is<VariantConstRef> const; | ||||
| // bool is<const VariantConstRef> const; | ||||
| template <typename T> | ||||
| NO_INLINE typename enable_if< | ||||
|     is_same<typename remove_const<T>::type, VariantConstRef>::value, bool>::type | ||||
| variantIs(const VariantData *var) { | ||||
|   return !!var; | ||||
| } | ||||
| #if ARDUINOJSON_HAS_NULLPTR | ||||
|  | ||||
| // bool is<nullptr_t> const; | ||||
| template <typename T> | ||||
| NO_INLINE typename enable_if<is_same<T, decltype(nullptr)>::value, bool>::type | ||||
| variantIs(const VariantData *var) { | ||||
|   return variantIsNull(var); | ||||
| } | ||||
| #endif | ||||
| // bool is<enum>() const; | ||||
| template <typename T> | ||||
| typename enable_if<is_enum<T>::value, bool>::type variantIs( | ||||
|     const VariantData *var) { | ||||
|   return variantIs<int>(var); | ||||
| } | ||||
|  | ||||
| // bool is<ArrayRef> const; | ||||
| // bool is<const ArrayRef> const; | ||||
| template <typename T> | ||||
| NO_INLINE | ||||
|     typename enable_if<is_same<typename remove_const<T>::type, ArrayRef>::value, | ||||
|                        bool>::type | ||||
|     variantIs(VariantData *var) { | ||||
|   return var && var->isArray(); | ||||
| } | ||||
|  | ||||
| // bool is<ObjectRef> const; | ||||
| // bool is<const ObjectRef> const; | ||||
| template <typename T> | ||||
| NO_INLINE typename enable_if< | ||||
|     is_same<typename remove_const<T>::type, ObjectRef>::value, bool>::type | ||||
| variantIs(VariantData *var) { | ||||
|   return var && var->isObject(); | ||||
| } | ||||
|  | ||||
| // bool is<VariantRef> const; | ||||
| // bool is<const VariantRef> const; | ||||
| template <typename T> | ||||
| NO_INLINE typename enable_if< | ||||
|     is_same<typename remove_const<T>::type, VariantRef>::value, bool>::type | ||||
| variantIs(VariantData *var) { | ||||
|   return !!var; | ||||
| } | ||||
|  | ||||
| // bool is<ArrayRef> const; | ||||
| // bool is<const ArrayRef> const; | ||||
| // bool is<ObjectRef> const; | ||||
| // bool is<const ObjectRef> const; | ||||
| // bool is<VariantRef> const; | ||||
| // bool is<const VariantRef> const; | ||||
| template <typename T> | ||||
| typename enable_if< | ||||
|     is_same<typename remove_const<T>::type, ArrayRef>::value || | ||||
|         is_same<typename remove_const<T>::type, ObjectRef>::value || | ||||
|         is_same<typename remove_const<T>::type, VariantRef>::value, | ||||
|     bool>::type | ||||
| variantIs(const VariantData *) { | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
| @@ -8,7 +8,6 @@ | ||||
| #include <ArduinoJson/Numbers/arithmeticCompare.hpp> | ||||
| #include <ArduinoJson/Polyfills/attributes.hpp> | ||||
| #include <ArduinoJson/Polyfills/type_traits.hpp> | ||||
| #include <ArduinoJson/Variant/VariantAs.hpp> | ||||
| #include <ArduinoJson/Variant/VariantTag.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|   | ||||
| @@ -11,9 +11,8 @@ | ||||
| #include <ArduinoJson/Misc/Visitable.hpp> | ||||
| #include <ArduinoJson/Polyfills/type_traits.hpp> | ||||
| #include <ArduinoJson/Strings/StringAdapters.hpp> | ||||
| #include <ArduinoJson/Variant/VariantAs.hpp> | ||||
| #include <ArduinoJson/Variant/Converter.hpp> | ||||
| #include <ArduinoJson/Variant/VariantFunctions.hpp> | ||||
| #include <ArduinoJson/Variant/VariantIs.hpp> | ||||
| #include <ArduinoJson/Variant/VariantOperators.hpp> | ||||
| #include <ArduinoJson/Variant/VariantRef.hpp> | ||||
| #include <ArduinoJson/Variant/VariantShortcuts.hpp> | ||||
| @@ -29,11 +28,6 @@ class ObjectRef; | ||||
| template <typename TData> | ||||
| class VariantRefBase : public VariantTag { | ||||
|  public: | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool is() const { | ||||
|     return variantIs<T>(_data); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE bool isNull() const { | ||||
|     return variantIsNull(_data); | ||||
|   } | ||||
| @@ -57,6 +51,10 @@ class VariantRefBase : public VariantTag { | ||||
|  protected: | ||||
|   VariantRefBase(TData *data) : _data(data) {} | ||||
|   TData *_data; | ||||
|  | ||||
|   friend TData *getData(const VariantRefBase &variant) { | ||||
|     return variant._data; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| // A variant that can be a any value serializable to a JSON value. | ||||
| @@ -85,120 +83,29 @@ class VariantRef : public VariantRefBase<VariantData>, | ||||
|     return variantSetNull(_data); | ||||
|   } | ||||
|  | ||||
|   // set(bool value) | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool set( | ||||
|       T value, typename enable_if<is_same<T, bool>::value>::type * = 0) const { | ||||
|     return variantSetBoolean(_data, value); | ||||
|   FORCE_INLINE bool set(const T &value) const { | ||||
|     return Converter<T>::toJson(*this, value); | ||||
|   } | ||||
|  | ||||
|   // set(double value); | ||||
|   // set(float value); | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool set( | ||||
|       T value, | ||||
|       typename enable_if<is_floating_point<T>::value>::type * = 0) const { | ||||
|     return variantSetFloat(_data, static_cast<Float>(value)); | ||||
|   FORCE_INLINE bool set(T *value) const { | ||||
|     return Converter<T *>::toJson(*this, value); | ||||
|   } | ||||
|  | ||||
|   // set(char) | ||||
|   // set(signed short) | ||||
|   // set(signed int) | ||||
|   // set(signed long) | ||||
|   // set(signed char) | ||||
|   // set(unsigned short) | ||||
|   // set(unsigned int) | ||||
|   // set(unsigned long) | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool set( | ||||
|       T value, | ||||
|       typename enable_if<is_integral<T>::value && !is_same<bool, T>::value && | ||||
|                          !is_same<char, T>::value>::type * = 0) const { | ||||
|     return variantSetInteger<T>(_data, value); | ||||
|   } | ||||
|  | ||||
|   // set(SerializedValue<const char *>) | ||||
|   FORCE_INLINE bool set(SerializedValue<const char *> value) const { | ||||
|     return variantSetLinkedRaw(_data, value); | ||||
|   } | ||||
|  | ||||
|   // set(SerializedValue<std::string>) | ||||
|   // set(SerializedValue<String>) | ||||
|   // set(SerializedValue<const __FlashStringHelper*>) | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool set( | ||||
|       SerializedValue<T> value, | ||||
|       typename enable_if<!is_same<const char *, T>::value>::type * = 0) const { | ||||
|     return variantSetOwnedRaw(_data, value, _pool); | ||||
|   } | ||||
|  | ||||
|   // set(const std::string&) | ||||
|   // set(const String&) | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool set( | ||||
|       const T &value, | ||||
|       typename enable_if<IsString<T>::value>::type * = 0) const { | ||||
|     return variantSetString(_data, adaptString(value), _pool); | ||||
|   } | ||||
|   // set(char*) | ||||
|   // set(const __FlashStringHelper*) | ||||
|   // set(const char*) | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool set( | ||||
|       T *value, typename enable_if<IsString<T *>::value>::type * = 0) const { | ||||
|     return variantSetString(_data, adaptString(value), _pool); | ||||
|   } | ||||
|  | ||||
|   // set(VariantRef) | ||||
|   // set(VariantConstRef) | ||||
|   // set(ArrayRef) | ||||
|   // set(ArrayConstRef) | ||||
|   // set(ObjectRef) | ||||
|   // set(ObjecConstRef) | ||||
|   // set(const JsonDocument&) | ||||
|   template <typename TVariant> | ||||
|   typename enable_if<IsVisitable<TVariant>::value, bool>::type set( | ||||
|       const TVariant &value) const; | ||||
|  | ||||
|   // set(enum value) | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool set( | ||||
|       T value, typename enable_if<is_enum<T>::value>::type * = 0) const { | ||||
|     return variantSetInteger(_data, static_cast<Integer>(value)); | ||||
|   } | ||||
|  | ||||
| #if ARDUINOJSON_HAS_NULLPTR | ||||
|   // set(nullptr_t) | ||||
|   FORCE_INLINE bool set(decltype(nullptr)) const { | ||||
|     variantSetNull(_data); | ||||
|     return true; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   template <typename T> | ||||
|   FORCE_INLINE T as() const { | ||||
|     /******************************************************************** | ||||
|      **                THIS IS NOT A BUG IN THE LIBRARY                ** | ||||
|      **                --------------------------------                ** | ||||
|      **  Get a compilation error pointing here?                        ** | ||||
|      **  It doesn't mean the error *is* here.                          ** | ||||
|      **  Often, it's because you try to extract the wrong value type.  ** | ||||
|      **                                                                ** | ||||
|      **  For example:                                                  ** | ||||
|      **    char* name = doc["name"];                                   ** | ||||
|      **    char age = doc["age"];                                      ** | ||||
|      **    auto city = doc["city"].as<char*>()                         ** | ||||
|      **  Instead, use:                                                 ** | ||||
|      **    const char* name = doc["name"];                             ** | ||||
|      **    int8_t age = doc["age"];                                    ** | ||||
|      **    auto city = doc["city"].as<const char*>()                   ** | ||||
|      ********************************************************************/ | ||||
|     return variantAs<T>(_data, _pool); | ||||
|     return Converter<T>::fromJson(*this); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool is() const { | ||||
|     return Converter<T>::checkJson(*this); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   FORCE_INLINE operator T() const { | ||||
|     return variantAs<T>(_data, _pool); | ||||
|     return Converter<T>::fromJson(*this); | ||||
|   } | ||||
|  | ||||
|   template <typename TVisitor> | ||||
| @@ -273,7 +180,11 @@ class VariantRef : public VariantRefBase<VariantData>, | ||||
|  | ||||
|  private: | ||||
|   MemoryPool *_pool; | ||||
| };  // namespace ARDUINOJSON_NAMESPACE | ||||
|  | ||||
|   friend MemoryPool *getPool(const VariantRef &variant) { | ||||
|     return variant._pool; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| class VariantConstRef : public VariantRefBase<const VariantData>, | ||||
|                         public VariantOperators<VariantConstRef>, | ||||
| @@ -294,12 +205,17 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | ||||
|  | ||||
|   template <typename T> | ||||
|   FORCE_INLINE T as() const { | ||||
|     return variantAs<T>(_data); | ||||
|     return Converter<T>::fromJson(*this); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool is() const { | ||||
|     return Converter<T>::checkJson(*this); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   FORCE_INLINE operator T() const { | ||||
|     return variantAs<T>(_data); | ||||
|     return Converter<T>::fromJson(*this); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE VariantConstRef getElement(size_t) const; | ||||
| @@ -344,4 +260,38 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | ||||
|     return getMember(key); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct Converter<VariantRef> { | ||||
|   static bool toJson(VariantRef variant, VariantRef value) { | ||||
|     return variantCopyFrom(getData(variant), getData(value), getPool(variant)); | ||||
|   } | ||||
|   static VariantRef fromJson(VariantRef variant) { | ||||
|     return variant; | ||||
|   } | ||||
|   static bool checkJson(VariantRef variant) { | ||||
|     VariantData *data = getData(variant); | ||||
|     return !!data; | ||||
|   } | ||||
|   static bool checkJson(VariantConstRef) { | ||||
|     return false; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct Converter<VariantConstRef> { | ||||
|   static bool toJson(VariantRef variant, VariantConstRef value) { | ||||
|     return variantCopyFrom(getData(variant), getData(value), getPool(variant)); | ||||
|   } | ||||
|  | ||||
|   static VariantConstRef fromJson(VariantConstRef variant) { | ||||
|     return VariantConstRef(getData(variant)); | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef variant) { | ||||
|     const VariantData *data = getData(variant); | ||||
|     return !!data; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
		Reference in New Issue
	
	Block a user