diff --git a/src/ArduinoJson/Json/JsonDeserializer.hpp b/src/ArduinoJson/Json/JsonDeserializer.hpp index 29c5c4d9..38d89adb 100644 --- a/src/ArduinoJson/Json/JsonDeserializer.hpp +++ b/src/ArduinoJson/Json/JsonDeserializer.hpp @@ -283,7 +283,7 @@ class JsonDeserializer { if (!member) return DeserializationError::NoMemory; } else { - member->setNull(resources_); + member->clear(resources_); } // Parse value diff --git a/src/ArduinoJson/Memory/ResourceManagerImpl.hpp b/src/ArduinoJson/Memory/ResourceManagerImpl.hpp index db89a045..3e0bc8b1 100644 --- a/src/ArduinoJson/Memory/ResourceManagerImpl.hpp +++ b/src/ArduinoJson/Memory/ResourceManagerImpl.hpp @@ -20,7 +20,7 @@ inline Slot ResourceManager::allocVariant() { } inline void ResourceManager::freeVariant(Slot variant) { - variant->setNull(this); + variant->clear(this); variantPools_.freeSlot(variant); } diff --git a/src/ArduinoJson/MsgPack/MsgPackBinary.hpp b/src/ArduinoJson/MsgPack/MsgPackBinary.hpp index bd275d44..2c0f6b71 100644 --- a/src/ArduinoJson/MsgPack/MsgPackBinary.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackBinary.hpp @@ -29,6 +29,7 @@ struct Converter : private detail::VariantAttorney { if (!data) return; auto resources = getResourceManager(dst); + data->clear(resources); if (src.data()) { size_t headerSize = src.size() >= 0x10000 ? 5 : src.size() >= 0x100 ? 3 @@ -62,7 +63,6 @@ struct Converter : private detail::VariantAttorney { return; } } - data->setNull(); } static MsgPackBinary fromJson(JsonVariantConst src) { diff --git a/src/ArduinoJson/MsgPack/MsgPackExtension.hpp b/src/ArduinoJson/MsgPack/MsgPackExtension.hpp index 5be4e503..b51eb30b 100644 --- a/src/ArduinoJson/MsgPack/MsgPackExtension.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackExtension.hpp @@ -35,6 +35,7 @@ struct Converter : private detail::VariantAttorney { if (!data) return; auto resources = getResourceManager(dst); + data->clear(resources); if (src.data()) { uint8_t format, sizeBytes; if (src.size() >= 0x10000) { @@ -76,7 +77,6 @@ struct Converter : private detail::VariantAttorney { return; } } - data->setNull(); } static MsgPackExtension fromJson(JsonVariantConst src) { diff --git a/src/ArduinoJson/Variant/ConverterImpl.hpp b/src/ArduinoJson/Variant/ConverterImpl.hpp index 3b1c7340..a20b13f2 100644 --- a/src/ArduinoJson/Variant/ConverterImpl.hpp +++ b/src/ArduinoJson/Variant/ConverterImpl.hpp @@ -63,7 +63,9 @@ struct Converter::value && auto data = getData(dst); if (!data) return false; - data->setInteger(src, getResourceManager(dst)); + auto resources = getResourceManager(dst); + data->clear(resources); + data->setInteger(src); return true; } @@ -103,7 +105,9 @@ struct Converter : private detail::VariantAttorney { auto data = getData(dst); if (!data) return false; - data->setBoolean(src, getResourceManager(dst)); + auto resources = getResourceManager(dst); + data->clear(resources); + data->setBoolean(src); return true; } @@ -125,7 +129,9 @@ struct Converter::value>> auto data = getData(dst); if (!data) return false; - data->setFloat(static_cast(src), getResourceManager(dst)); + auto resources = getResourceManager(dst); + data->clear(resources); + data->setFloat(static_cast(src)); return true; } @@ -199,7 +205,7 @@ struct Converter> : private detail::VariantAttorney { template <> struct Converter : private detail::VariantAttorney { static void toJson(detail::nullptr_t, JsonVariant dst) { - detail::VariantData::setNull(getData(dst), getResourceManager(dst)); + detail::VariantData::clear(getData(dst), getResourceManager(dst)); } static detail::nullptr_t fromJson(JsonVariantConst) { return nullptr; @@ -252,12 +258,11 @@ inline void convertToJson(const ::Printable& src, JsonVariant dst) { auto data = detail::VariantAttorney::getData(dst); if (!resources || !data) return; + data->clear(resources); detail::StringBuilderPrint print(resources); src.printTo(print); - if (print.overflowed()) { - data->setNull(); + if (print.overflowed()) return; - } data->setOwnedString(print.save()); } diff --git a/src/ArduinoJson/Variant/VariantData.hpp b/src/ArduinoJson/Variant/VariantData.hpp index 86b2adce..b4ebe918 100644 --- a/src/ArduinoJson/Variant/VariantData.hpp +++ b/src/ArduinoJson/Variant/VariantData.hpp @@ -344,64 +344,38 @@ class VariantData { var->removeMember(key, resources); } - void reset() { + void reset() { // TODO: remove type_ = VALUE_IS_NULL; } void setBoolean(bool value) { + ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first type_ = VALUE_IS_BOOLEAN; content_.asBoolean = value; } - void setBoolean(bool value, ResourceManager* resources) { - release(resources); - setBoolean(value); - } - void setFloat(JsonFloat value) { + ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first type_ = VALUE_IS_FLOAT; content_.asFloat = value; } - void setFloat(JsonFloat value, ResourceManager* resources) { - release(resources); - setFloat(value); - } - template enable_if_t::value> setInteger(T value) { + ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first type_ = VALUE_IS_SIGNED_INTEGER; content_.asSignedInteger = value; } template enable_if_t::value> setInteger(T value) { + ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first type_ = VALUE_IS_UNSIGNED_INTEGER; content_.asUnsignedInteger = static_cast(value); } - template - void setInteger(T value, ResourceManager* resources) { - release(resources); - setInteger(value); - } - - void setNull() { - type_ = VALUE_IS_NULL; - } - - void setNull(ResourceManager* resources) { - release(resources); - setNull(); - } - - static void setNull(VariantData* var, ResourceManager* resources) { - if (!var) - return; - var->setNull(resources); - } - void setRawString(StringNode* s) { + ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first ARDUINOJSON_ASSERT(s); type_ = VALUE_IS_RAW_STRING; content_.asOwnedString = s; @@ -415,6 +389,7 @@ class VariantData { ResourceManager* resources) { if (!var) return; + var->clear(resources); var->setRawString(value, resources); } @@ -431,16 +406,19 @@ class VariantData { ResourceManager* resources) { if (!var) return; + var->clear(resources); var->setString(value, resources); } void setLinkedString(const char* s) { + ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first ARDUINOJSON_ASSERT(s); type_ = VALUE_IS_LINKED_STRING; content_.asLinkedString = s; } void setOwnedString(StringNode* s) { + ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first ARDUINOJSON_ASSERT(s); type_ = VALUE_IS_OWNED_STRING; content_.asOwnedString = s; @@ -461,45 +439,45 @@ class VariantData { } ArrayData& toArray() { + ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first type_ = VALUE_IS_ARRAY; new (&content_.asArray) ArrayData(); return content_.asArray; } - ArrayData& toArray(ResourceManager* resources) { - release(resources); - return toArray(); - } - static ArrayData* toArray(VariantData* var, ResourceManager* resources) { if (!var) return 0; - return &var->toArray(resources); + var->clear(resources); + return &var->toArray(); } ObjectData& toObject() { + ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first type_ = VALUE_IS_OBJECT; new (&content_.asObject) ObjectData(); return content_.asObject; } - ObjectData& toObject(ResourceManager* resources) { - release(resources); - return toObject(); - } - static ObjectData* toObject(VariantData* var, ResourceManager* resources) { if (!var) return 0; - return &var->toObject(resources); + var->clear(resources); + return &var->toObject(); } uint8_t type() const { return type_; } - private: - void release(ResourceManager* resources); + // Release the resources used by this variant and set it to null. + void clear(ResourceManager* resources); + + static void clear(VariantData* var, ResourceManager* resources) { + if (!var) + return; + var->clear(resources); + } }; ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Variant/VariantImpl.hpp b/src/ArduinoJson/Variant/VariantImpl.hpp index ae131509..b30a93ce 100644 --- a/src/ArduinoJson/Variant/VariantImpl.hpp +++ b/src/ArduinoJson/Variant/VariantImpl.hpp @@ -12,18 +12,16 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template inline void VariantData::setRawString(SerializedValue value, ResourceManager* resources) { - release(resources); + ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first auto dup = resources->saveString(adaptString(value.data(), value.size())); if (dup) setRawString(dup); - else - setNull(); } template inline bool VariantData::setString(TAdaptedString value, ResourceManager* resources) { - setNull(resources); + ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first if (value.isNull()) return false; @@ -42,13 +40,15 @@ inline bool VariantData::setString(TAdaptedString value, return false; } -inline void VariantData::release(ResourceManager* resources) { +inline void VariantData::clear(ResourceManager* resources) { if (type_ & OWNED_VALUE_BIT) resources->dereferenceString(content_.asOwnedString->data); auto collection = asCollection(); if (collection) collection->clear(resources); + + type_ = VALUE_IS_NULL; } ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Variant/VariantRefBase.hpp b/src/ArduinoJson/Variant/VariantRefBase.hpp index 3966f365..f64b2c6a 100644 --- a/src/ArduinoJson/Variant/VariantRefBase.hpp +++ b/src/ArduinoJson/Variant/VariantRefBase.hpp @@ -29,7 +29,7 @@ class VariantRefBase : public VariantTag { // Sets the value to null. // https://arduinojson.org/v7/api/jsonvariant/clear/ void clear() const { - VariantData::setNull(getOrCreateData(), getResourceManager()); + VariantData::clear(getOrCreateData(), getResourceManager()); } // Returns true if the value is null or the reference is unbound. diff --git a/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp b/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp index 023dfd52..594f317d 100644 --- a/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp +++ b/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp @@ -174,7 +174,7 @@ enable_if_t::value, JsonVariant> VariantRefBase::to() const { auto data = getOrCreateData(); auto resources = getResourceManager(); - detail::VariantData::setNull(data, resources); + detail::VariantData::clear(data, resources); return JsonVariant(data, resources); }