mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Added implicit conversion from JsonArray and JsonObject to JsonVariant
				
					
				
			This commit is contained in:
		| @@ -1,6 +1,11 @@ | ||||
| ArduinoJson: change log | ||||
| ======================= | ||||
|  | ||||
| HEAD | ||||
| ---- | ||||
|  | ||||
| * Added implicit conversion from `JsonArray` and `JsonObject` to `JsonVariant` | ||||
|  | ||||
| v6.4.0-beta (2018-09-11) | ||||
| ----------- | ||||
|  | ||||
|   | ||||
| @@ -4,158 +4,32 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "../Numbers/parseFloat.hpp" | ||||
| #include "../Numbers/parseInteger.hpp" | ||||
| #include "JsonVariantContent.hpp" | ||||
| #include "JsonVariantType.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| namespace Internals { | ||||
|  | ||||
| // this struct must be a POD type to prevent error calling offsetof on clang | ||||
| struct JsonVariantData { | ||||
|   JsonVariantType type; | ||||
|   JsonVariantContent content; | ||||
|  | ||||
|   JsonVariantData() { | ||||
|     type = JSON_NULL; | ||||
|   } | ||||
|  | ||||
|   void setBoolean(bool value) { | ||||
|     type = JSON_BOOLEAN; | ||||
|     content.asInteger = static_cast<JsonUInt>(value); | ||||
|   } | ||||
|  | ||||
|   void setFloat(JsonFloat value) { | ||||
|     type = JSON_FLOAT; | ||||
|     content.asFloat = value; | ||||
|   } | ||||
|  | ||||
|   void setNegativeInteger(JsonUInt value) { | ||||
|     type = JSON_NEGATIVE_INTEGER; | ||||
|     content.asInteger = value; | ||||
|   } | ||||
|  | ||||
|   void setPostiveInteger(JsonUInt value) { | ||||
|     type = JSON_POSITIVE_INTEGER; | ||||
|     content.asInteger = value; | ||||
|   } | ||||
|  | ||||
|   void setOwnedString(const char *value) { | ||||
|     type = JSON_OWNED_STRING; | ||||
|     content.asString = value; | ||||
|   } | ||||
|  | ||||
|   void setLinkedString(const char *value) { | ||||
|     type = JSON_LINKED_STRING; | ||||
|     content.asString = value; | ||||
|   } | ||||
|  | ||||
|   void setOwnedRaw(const char *data, size_t size) { | ||||
|     type = JSON_OWNED_RAW; | ||||
|     content.asRaw.data = data; | ||||
|     content.asRaw.size = size; | ||||
|   } | ||||
|  | ||||
|   void setLinkedRaw(const char *data, size_t size) { | ||||
|     type = JSON_LINKED_RAW; | ||||
|     content.asRaw.data = data; | ||||
|     content.asRaw.size = size; | ||||
|   } | ||||
|  | ||||
|   void setNull() { | ||||
|     type = JSON_NULL; | ||||
|   } | ||||
|  | ||||
|   JsonArrayData *toArray() { | ||||
|     type = JSON_ARRAY; | ||||
|     content.asArray.head = 0; | ||||
|     content.asArray.tail = 0; | ||||
|     return &content.asArray; | ||||
|   } | ||||
|  | ||||
|   JsonObjectData *toObject() { | ||||
|     type = JSON_OBJECT; | ||||
|     content.asObject.head = 0; | ||||
|     content.asObject.tail = 0; | ||||
|     return &content.asObject; | ||||
|   } | ||||
|  | ||||
|   JsonArrayData *asArray() { | ||||
|     return type == JSON_ARRAY ? &content.asArray : 0; | ||||
|   } | ||||
|  | ||||
|   JsonObjectData *asObject() { | ||||
|     return type == JSON_OBJECT ? &content.asObject : 0; | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   T asInteger() const { | ||||
|     switch (type) { | ||||
|       case JSON_POSITIVE_INTEGER: | ||||
|       case JSON_BOOLEAN: | ||||
|         return T(content.asInteger); | ||||
|       case JSON_NEGATIVE_INTEGER: | ||||
|         return T(~content.asInteger + 1); | ||||
|       case JSON_LINKED_STRING: | ||||
|       case JSON_OWNED_STRING: | ||||
|         return parseInteger<T>(content.asString); | ||||
|       case JSON_FLOAT: | ||||
|         return T(content.asFloat); | ||||
|       default: | ||||
|         return 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   T asFloat() const { | ||||
|     switch (type) { | ||||
|       case JSON_POSITIVE_INTEGER: | ||||
|       case JSON_BOOLEAN: | ||||
|         return static_cast<T>(content.asInteger); | ||||
|       case JSON_NEGATIVE_INTEGER: | ||||
|         return -static_cast<T>(content.asInteger); | ||||
|       case JSON_LINKED_STRING: | ||||
|       case JSON_OWNED_STRING: | ||||
|         return parseFloat<T>(content.asString); | ||||
|       case JSON_FLOAT: | ||||
|         return static_cast<T>(content.asFloat); | ||||
|       default: | ||||
|         return 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   const char *asString() const { | ||||
|     return isString() ? content.asString : NULL; | ||||
|   } | ||||
|  | ||||
|   bool isArray() const { | ||||
|     return type == JSON_ARRAY; | ||||
|   } | ||||
|  | ||||
|   bool isBoolean() const { | ||||
|     return type == JSON_BOOLEAN; | ||||
|   } | ||||
|  | ||||
|   bool isFloat() const { | ||||
|     return type == JSON_FLOAT || type == JSON_POSITIVE_INTEGER || | ||||
|            type == JSON_NEGATIVE_INTEGER; | ||||
|   } | ||||
|  | ||||
|   bool isInteger() const { | ||||
|     return type == JSON_POSITIVE_INTEGER || type == JSON_NEGATIVE_INTEGER; | ||||
|   } | ||||
|  | ||||
|   bool isNull() const { | ||||
|     return type == JSON_NULL; | ||||
|   } | ||||
|  | ||||
|   bool isObject() const { | ||||
|     return type == JSON_OBJECT; | ||||
|   } | ||||
|  | ||||
|   bool isString() const { | ||||
|     return type == JSON_LINKED_STRING || type == JSON_OWNED_STRING; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| inline JsonVariantData *getVariantData(JsonArrayData *arr) { | ||||
|   const ptrdiff_t offset = offsetof(JsonVariantData, content) - | ||||
|                            offsetof(JsonVariantContent, asArray); | ||||
|   if (!arr) return 0; | ||||
|   return reinterpret_cast<JsonVariantData *>(reinterpret_cast<char *>(arr) - | ||||
|                                              offset); | ||||
| } | ||||
|  | ||||
| inline JsonVariantData *getVariantData(JsonObjectData *obj) { | ||||
|   const ptrdiff_t offset = offsetof(JsonVariantData, content) - | ||||
|                            offsetof(JsonVariantContent, asObject); | ||||
|   if (!obj) return 0; | ||||
|   return reinterpret_cast<JsonVariantData *>(reinterpret_cast<char *>(obj) - | ||||
|                                              offset); | ||||
| } | ||||
| }  // namespace Internals | ||||
| }  // namespace ArduinoJson | ||||
|   | ||||
| @@ -37,7 +37,7 @@ class DynamicJsonDocument { | ||||
|  | ||||
|   void clear() { | ||||
|     _memoryPool.clear(); | ||||
|     _rootData.setNull(); | ||||
|     _rootData.type = Internals::JSON_NULL; | ||||
|   } | ||||
|  | ||||
|   size_t memoryUsage() const { | ||||
|   | ||||
| @@ -26,9 +26,14 @@ class JsonArray { | ||||
|   typedef JsonArrayIterator iterator; | ||||
|  | ||||
|   FORCE_INLINE JsonArray() : _memoryPool(0), _data(0) {} | ||||
|   FORCE_INLINE JsonArray(Internals::MemoryPool* buf, | ||||
|   FORCE_INLINE JsonArray(Internals::MemoryPool* pool, | ||||
|                          Internals::JsonArrayData* arr) | ||||
|       : _memoryPool(buf), _data(arr) {} | ||||
|       : _memoryPool(pool), _data(arr) {} | ||||
|  | ||||
|   operator JsonVariant() { | ||||
|     using namespace Internals; | ||||
|     return JsonVariant(_memoryPool, getVariantData(_data)); | ||||
|   } | ||||
|  | ||||
|   // Adds the specified value at the end of the array. | ||||
|   // | ||||
|   | ||||
| @@ -24,6 +24,11 @@ class JsonObject { | ||||
|                           Internals::JsonObjectData* object) | ||||
|       : _memoryPool(buf), _data(object) {} | ||||
|  | ||||
|   operator JsonVariant() { | ||||
|     using namespace Internals; | ||||
|     return JsonVariant(_memoryPool, getVariantData(_data)); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE iterator begin() const { | ||||
|     if (!_data) return iterator(); | ||||
|     return iterator(_memoryPool, _data->head); | ||||
|   | ||||
| @@ -11,6 +11,8 @@ | ||||
| #include "JsonVariant.hpp" | ||||
| #include "JsonVariantBase.hpp" | ||||
| #include "Memory/MemoryPool.hpp" | ||||
| #include "Numbers/parseFloat.hpp" | ||||
| #include "Numbers/parseInteger.hpp" | ||||
| #include "Polyfills/type_traits.hpp" | ||||
| #include "Serialization/DynamicStringWriter.hpp" | ||||
| #include "SerializedValue.hpp" | ||||
| @@ -41,7 +43,8 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|   // set(bool value) | ||||
|   FORCE_INLINE bool set(bool value) { | ||||
|     if (!_data) return false; | ||||
|     _data->setBoolean(value); | ||||
|     _data->type = Internals::JSON_BOOLEAN; | ||||
|     _data->content.asInteger = static_cast<Internals::JsonUInt>(value); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -52,7 +55,8 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|       T value, typename Internals::enable_if< | ||||
|                    Internals::is_floating_point<T>::value>::type * = 0) { | ||||
|     if (!_data) return false; | ||||
|     _data->setFloat(static_cast<Internals::JsonFloat>(value)); | ||||
|     _data->type = Internals::JSON_FLOAT; | ||||
|     _data->content.asFloat = static_cast<Internals::JsonFloat>(value); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -68,10 +72,13 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|                                     Internals::is_signed<T>::value>::type * = | ||||
|           0) { | ||||
|     if (!_data) return false; | ||||
|     if (value >= 0) | ||||
|       _data->setPostiveInteger(static_cast<Internals::JsonUInt>(value)); | ||||
|     else | ||||
|       _data->setNegativeInteger(~static_cast<Internals::JsonUInt>(value) + 1); | ||||
|     if (value >= 0) { | ||||
|       _data->type = Internals::JSON_POSITIVE_INTEGER; | ||||
|       _data->content.asInteger = static_cast<Internals::JsonUInt>(value); | ||||
|     } else { | ||||
|       _data->type = Internals::JSON_NEGATIVE_INTEGER; | ||||
|       _data->content.asInteger = ~static_cast<Internals::JsonUInt>(value) + 1; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -85,14 +92,17 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|                                     Internals::is_unsigned<T>::value>::type * = | ||||
|           0) { | ||||
|     if (!_data) return false; | ||||
|     _data->setPostiveInteger(static_cast<Internals::JsonUInt>(value)); | ||||
|     _data->type = Internals::JSON_POSITIVE_INTEGER; | ||||
|     _data->content.asInteger = static_cast<Internals::JsonUInt>(value); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   // set(SerializedValue<const char *>) | ||||
|   FORCE_INLINE bool set(Internals::SerializedValue<const char *> value) { | ||||
|     if (!_data) return false; | ||||
|     _data->setLinkedRaw(value.data(), value.size()); | ||||
|     _data->type = Internals::JSON_LINKED_RAW; | ||||
|     _data->content.asRaw.data = value.data(); | ||||
|     _data->content.asRaw.size = value.size(); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -107,11 +117,15 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|     if (!_data) return false; | ||||
|     const char *dup = | ||||
|         Internals::makeString(value.data(), value.size()).save(_memoryPool); | ||||
|     if (dup) | ||||
|       _data->setOwnedRaw(dup, value.size()); | ||||
|     else | ||||
|       _data->setNull(); | ||||
|     return true; | ||||
|     if (dup) { | ||||
|       _data->type = Internals::JSON_OWNED_RAW; | ||||
|       _data->content.asRaw.data = dup; | ||||
|       _data->content.asRaw.size = value.size(); | ||||
|       return true; | ||||
|     } else { | ||||
|       _data->type = Internals::JSON_NULL; | ||||
|       return false; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // set(const std::string&) | ||||
| @@ -124,10 +138,11 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|     if (!_data) return false; | ||||
|     const char *dup = Internals::makeString(value).save(_memoryPool); | ||||
|     if (dup) { | ||||
|       _data->setOwnedString(dup); | ||||
|       _data->type = Internals::JSON_OWNED_STRING; | ||||
|       _data->content.asString = dup; | ||||
|       return true; | ||||
|     } else { | ||||
|       _data->setNull(); | ||||
|       _data->type = Internals::JSON_NULL; | ||||
|       return false; | ||||
|     } | ||||
|   } | ||||
| @@ -141,10 +156,11 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|     if (!_data) return false; | ||||
|     const char *dup = Internals::makeString(value).save(_memoryPool); | ||||
|     if (dup) { | ||||
|       _data->setOwnedString(dup); | ||||
|       _data->type = Internals::JSON_OWNED_STRING; | ||||
|       _data->content.asString = dup; | ||||
|       return true; | ||||
|     } else { | ||||
|       _data->setNull(); | ||||
|       _data->type = Internals::JSON_NULL; | ||||
|       return false; | ||||
|     } | ||||
|   } | ||||
| @@ -152,7 +168,8 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|   // set(const char*); | ||||
|   FORCE_INLINE bool set(const char *value) { | ||||
|     if (!_data) return false; | ||||
|     _data->setLinkedString(value); | ||||
|     _data->type = Internals::JSON_LINKED_STRING; | ||||
|     _data->content.asString = value; | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -179,14 +196,28 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|   FORCE_INLINE const typename Internals::enable_if< | ||||
|       Internals::is_integral<T>::value, T>::type | ||||
|   as() const { | ||||
|     return _data ? _data->asInteger<T>() : T(); | ||||
|     if (!_data) return 0; | ||||
|     switch (_data->type) { | ||||
|       case Internals::JSON_POSITIVE_INTEGER: | ||||
|       case Internals::JSON_BOOLEAN: | ||||
|         return T(_data->content.asInteger); | ||||
|       case Internals::JSON_NEGATIVE_INTEGER: | ||||
|         return T(~_data->content.asInteger + 1); | ||||
|       case Internals::JSON_LINKED_STRING: | ||||
|       case Internals::JSON_OWNED_STRING: | ||||
|         return Internals::parseInteger<T>(_data->content.asString); | ||||
|       case Internals::JSON_FLOAT: | ||||
|         return T(_data->content.asFloat); | ||||
|       default: | ||||
|         return 0; | ||||
|     } | ||||
|   } | ||||
|   // bool as<bool>() const | ||||
|   template <typename T> | ||||
|   FORCE_INLINE const typename Internals::enable_if< | ||||
|       Internals::is_same<T, bool>::value, T>::type | ||||
|   as() const { | ||||
|     return _data && _data->asInteger<int>() != 0; | ||||
|     return as<int>() != 0; | ||||
|   } | ||||
|   // | ||||
|   // double as<double>() const; | ||||
| @@ -195,7 +226,21 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|   FORCE_INLINE const typename Internals::enable_if< | ||||
|       Internals::is_floating_point<T>::value, T>::type | ||||
|   as() const { | ||||
|     return _data ? _data->asFloat<T>() : 0; | ||||
|     if (!_data) return 0; | ||||
|     switch (_data->type) { | ||||
|       case Internals::JSON_POSITIVE_INTEGER: | ||||
|       case Internals::JSON_BOOLEAN: | ||||
|         return static_cast<T>(_data->content.asInteger); | ||||
|       case Internals::JSON_NEGATIVE_INTEGER: | ||||
|         return -static_cast<T>(_data->content.asInteger); | ||||
|       case Internals::JSON_LINKED_STRING: | ||||
|       case Internals::JSON_OWNED_STRING: | ||||
|         return Internals::parseFloat<T>(_data->content.asString); | ||||
|       case Internals::JSON_FLOAT: | ||||
|         return static_cast<T>(_data->content.asFloat); | ||||
|       default: | ||||
|         return 0; | ||||
|     } | ||||
|   } | ||||
|   // | ||||
|   // const char* as<const char*>() const; | ||||
| @@ -206,7 +251,12 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|           Internals::is_same<T, char *>::value, | ||||
|       const char *>::type | ||||
|   as() const { | ||||
|     return _data ? _data->asString() : 0; | ||||
|     if (!_data) return 0; | ||||
|     if (_data && (_data->type == Internals::JSON_LINKED_STRING || | ||||
|                   _data->type == Internals::JSON_OWNED_STRING)) | ||||
|       return _data->content.asString; | ||||
|     else | ||||
|       return 0; | ||||
|   } | ||||
|   // | ||||
|   // std::string as<std::string>() const; | ||||
| @@ -216,7 +266,7 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|       typename Internals::enable_if<Internals::IsWriteableString<T>::value, | ||||
|                                     T>::type | ||||
|       as() const { | ||||
|     const char *cstr = _data ? _data->asString() : 0; | ||||
|     const char *cstr = as<const char *>(); | ||||
|     if (cstr) return T(cstr); | ||||
|     T s; | ||||
|     serializeJson(*this, s); | ||||
| @@ -266,7 +316,8 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|   FORCE_INLINE typename Internals::enable_if<Internals::is_integral<T>::value, | ||||
|                                              bool>::type | ||||
|   is() const { | ||||
|     return _data && _data->isInteger(); | ||||
|     return _data && (_data->type == Internals::JSON_POSITIVE_INTEGER || | ||||
|                      _data->type == Internals::JSON_NEGATIVE_INTEGER); | ||||
|   } | ||||
|   // | ||||
|   // bool is<double>() const; | ||||
| @@ -276,7 +327,9 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|       typename Internals::enable_if<Internals::is_floating_point<T>::value, | ||||
|                                     bool>::type | ||||
|       is() const { | ||||
|     return _data && _data->isFloat(); | ||||
|     return _data && (_data->type == Internals::JSON_FLOAT || | ||||
|                      _data->type == Internals::JSON_POSITIVE_INTEGER || | ||||
|                      _data->type == Internals::JSON_NEGATIVE_INTEGER); | ||||
|   } | ||||
|   // | ||||
|   // bool is<bool>() const | ||||
| @@ -284,7 +337,7 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|   FORCE_INLINE typename Internals::enable_if<Internals::is_same<T, bool>::value, | ||||
|                                              bool>::type | ||||
|   is() const { | ||||
|     return _data && _data->isBoolean(); | ||||
|     return _data && _data->type == Internals::JSON_BOOLEAN; | ||||
|   } | ||||
|   // | ||||
|   // bool is<const char*>() const; | ||||
| @@ -295,7 +348,8 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|           Internals::is_same<T, char *>::value, | ||||
|       bool>::type | ||||
|   is() const { | ||||
|     return _data && _data->isString(); | ||||
|     return _data && (_data->type == Internals::JSON_LINKED_STRING || | ||||
|                      _data->type == Internals::JSON_OWNED_STRING); | ||||
|   } | ||||
|   // | ||||
|   // bool is<JsonArray> const; | ||||
| @@ -306,7 +360,7 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|                          JsonArray>::value, | ||||
|       bool>::type | ||||
|   is() const { | ||||
|     return _data && _data->isArray(); | ||||
|     return _data && _data->type == Internals::JSON_ARRAY; | ||||
|   } | ||||
|   // | ||||
|   // bool is<JsonObject> const; | ||||
| @@ -317,11 +371,11 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|                          JsonObject>::value, | ||||
|       bool>::type | ||||
|   is() const { | ||||
|     return _data && _data->isObject(); | ||||
|     return _data && _data->type == Internals::JSON_OBJECT; | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE bool isNull() const { | ||||
|     return _data == 0 || _data->isNull(); | ||||
|     return _data == 0 || _data->type == Internals::JSON_NULL; | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE bool isInvalid() const { | ||||
| @@ -354,5 +408,16 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> { | ||||
|  private: | ||||
|   Internals::MemoryPool *_memoryPool; | ||||
|   Internals::JsonVariantData *_data; | ||||
| };  // namespace ArduinoJson | ||||
| }; | ||||
|  | ||||
| class JsonVariantLocal : public JsonVariant { | ||||
|  public: | ||||
|   explicit JsonVariantLocal(Internals::MemoryPool *memoryPool) | ||||
|       : JsonVariant(memoryPool, &_localData) { | ||||
|     _localData.type = Internals::JSON_NULL; | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   Internals::JsonVariantData _localData; | ||||
| }; | ||||
| }  // namespace ArduinoJson | ||||
|   | ||||
| @@ -34,7 +34,7 @@ inline bool JsonVariant::set( | ||||
| inline bool JsonVariant::set(const JsonVariant& value) { | ||||
|   if (!_data) return false; | ||||
|   if (!value._data) { | ||||
|     _data->setNull(); | ||||
|     _data->type = Internals::JSON_NULL; | ||||
|     return true; | ||||
|   } | ||||
|   switch (value._data->type) { | ||||
| @@ -59,7 +59,10 @@ inline typename Internals::enable_if< | ||||
|                        JsonArray>::value, | ||||
|     JsonArray>::type | ||||
| JsonVariant::as() const { | ||||
|   return _data ? JsonArray(_memoryPool, _data->asArray()) : JsonArray(); | ||||
|   if (_data && _data->type == Internals::JSON_ARRAY) | ||||
|     return JsonArray(_memoryPool, &_data->content.asArray); | ||||
|   else | ||||
|     return JsonArray(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| @@ -68,7 +71,10 @@ inline typename Internals::enable_if< | ||||
|                        JsonObject>::value, | ||||
|     T>::type | ||||
| JsonVariant::as() const { | ||||
|   return _data ? JsonObject(_memoryPool, _data->asObject()) : JsonObject(); | ||||
|   if (_data && _data->type == Internals::JSON_OBJECT) | ||||
|     return JsonObject(_memoryPool, &_data->content.asObject); | ||||
|   else | ||||
|     return JsonObject(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| @@ -76,7 +82,10 @@ inline typename Internals::enable_if<Internals::is_same<T, JsonArray>::value, | ||||
|                                      JsonArray>::type | ||||
| JsonVariant::to() { | ||||
|   if (!_data) return JsonArray(); | ||||
|   return JsonArray(_memoryPool, _data->toArray()); | ||||
|   _data->type = Internals::JSON_ARRAY; | ||||
|   _data->content.asArray.head = 0; | ||||
|   _data->content.asArray.tail = 0; | ||||
|   return JsonArray(_memoryPool, &_data->content.asArray); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| @@ -84,7 +93,10 @@ typename Internals::enable_if<Internals::is_same<T, JsonObject>::value, | ||||
|                               JsonObject>::type | ||||
| JsonVariant::to() { | ||||
|   if (!_data) return JsonObject(); | ||||
|   return JsonObject(_memoryPool, _data->toObject()); | ||||
|   _data->type = Internals::JSON_OBJECT; | ||||
|   _data->content.asObject.head = 0; | ||||
|   _data->content.asObject.tail = 0; | ||||
|   return JsonObject(_memoryPool, &_data->content.asObject); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| @@ -92,7 +104,7 @@ typename Internals::enable_if<Internals::is_same<T, JsonVariant>::value, | ||||
|                               JsonVariant>::type | ||||
| JsonVariant::to() { | ||||
|   if (!_data) return JsonVariant(); | ||||
|   _data->setNull(); | ||||
|   _data->type = Internals::JSON_NULL; | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -277,13 +277,12 @@ class MsgPackDeserializer { | ||||
|     if (_nestingLimit == 0) return DeserializationError::TooDeep; | ||||
|     --_nestingLimit; | ||||
|     for (; n; --n) { | ||||
|       JsonVariantData keyData; | ||||
|       JsonVariant key(_memoryPool, &keyData); | ||||
|       JsonVariantLocal key(_memoryPool); | ||||
|       DeserializationError err = parse(key); | ||||
|       if (err) return err; | ||||
|       if (!keyData.isString()) return DeserializationError::NotSupported; | ||||
|       if (!key.is<char *>()) return DeserializationError::NotSupported; | ||||
|  | ||||
|       JsonVariant value = object.set(keyData.asString()); | ||||
|       JsonVariant value = object.set(key.as<char *>()); | ||||
|       if (value.isInvalid()) return DeserializationError::NoMemory; | ||||
|  | ||||
|       err = parse(value); | ||||
|   | ||||
| @@ -39,7 +39,7 @@ class StaticJsonDocument { | ||||
|  | ||||
|   void clear() { | ||||
|     _memoryPool.clear(); | ||||
|     _rootData.setNull(); | ||||
|     _rootData.type = Internals::JSON_NULL; | ||||
|   } | ||||
|  | ||||
|   size_t memoryUsage() const { | ||||
|   | ||||
| @@ -8,6 +8,7 @@ add_executable(JsonVariantTests | ||||
| 	copy.cpp | ||||
| 	is.cpp | ||||
| 	isnull.cpp | ||||
| 	misc.cpp | ||||
| 	or.cpp | ||||
| 	set_get.cpp | ||||
| 	subscript.cpp | ||||
|   | ||||
							
								
								
									
										50
									
								
								test/JsonVariant/misc.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								test/JsonVariant/misc.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| // ArduinoJson - arduinojson.org | ||||
| // Copyright Benoit Blanchon 2014-2018 | ||||
| // MIT License | ||||
|  | ||||
| #include <ArduinoJson.h> | ||||
| #include <catch.hpp> | ||||
|  | ||||
| TEST_CASE("JsonVariant from JsonArray") { | ||||
|   SECTION("JsonArray is null") { | ||||
|     JsonArray arr; | ||||
|     JsonVariant v = arr; | ||||
|     REQUIRE(v.isNull() == true); | ||||
|   } | ||||
|  | ||||
|   SECTION("JsonArray is not null") { | ||||
|     DynamicJsonDocument doc; | ||||
|     JsonArray arr = doc.to<JsonArray>(); | ||||
|     arr.add(12); | ||||
|     arr.add(34); | ||||
|  | ||||
|     JsonVariant v = arr; | ||||
|  | ||||
|     REQUIRE(v.is<JsonArray>() == true); | ||||
|     REQUIRE(v.size() == 2); | ||||
|     REQUIRE(v[0] == 12); | ||||
|     REQUIRE(v[1] == 34); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_CASE("JsonVariant from JsonObject") { | ||||
|   SECTION("JsonObject is null") { | ||||
|     JsonObject obj; | ||||
|     JsonVariant v = obj; | ||||
|     REQUIRE(v.isNull() == true); | ||||
|   } | ||||
|  | ||||
|   SECTION("JsonObject is not null") { | ||||
|     DynamicJsonDocument doc; | ||||
|     JsonObject obj = doc.to<JsonObject>(); | ||||
|     obj["a"] = 12; | ||||
|     obj["b"] = 34; | ||||
|  | ||||
|     JsonVariant v = obj; | ||||
|  | ||||
|     REQUIRE(v.is<JsonObject>() == true); | ||||
|     REQUIRE(v.size() == 2); | ||||
|     REQUIRE(v["a"] == 12); | ||||
|     REQUIRE(v["b"] == 34); | ||||
|   } | ||||
| } | ||||
| @@ -205,7 +205,20 @@ TEST_CASE("JsonVariant and strings") { | ||||
|  | ||||
|     REQUIRE(variant == "hello"); | ||||
|   } | ||||
|  | ||||
|   // TODO: string | ||||
|   // TODO: serialized() | ||||
| } | ||||
|  | ||||
| TEST_CASE("JsonVariant with not enough memory") { | ||||
|   StaticJsonDocument<1> doc; | ||||
|  | ||||
|   JsonVariant v = doc.to<JsonVariant>(); | ||||
|  | ||||
|   SECTION("std::string") { | ||||
|     v.set(std::string("hello")); | ||||
|     REQUIRE(v.isNull()); | ||||
|   } | ||||
|  | ||||
|   SECTION("Serialized<std::string>") { | ||||
|     v.set(serialized(std::string("hello"))); | ||||
|     REQUIRE(v.isNull()); | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user