mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-30 02:37:35 +02:00
Release VariantData
resources explicitly before setting value
This commit is contained in:
@ -283,7 +283,7 @@ class JsonDeserializer {
|
|||||||
if (!member)
|
if (!member)
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
} else {
|
} else {
|
||||||
member->setNull(resources_);
|
member->clear(resources_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse value
|
// Parse value
|
||||||
|
@ -20,7 +20,7 @@ inline Slot<VariantData> ResourceManager::allocVariant() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void ResourceManager::freeVariant(Slot<VariantData> variant) {
|
inline void ResourceManager::freeVariant(Slot<VariantData> variant) {
|
||||||
variant->setNull(this);
|
variant->clear(this);
|
||||||
variantPools_.freeSlot(variant);
|
variantPools_.freeSlot(variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ struct Converter<MsgPackBinary> : private detail::VariantAttorney {
|
|||||||
if (!data)
|
if (!data)
|
||||||
return;
|
return;
|
||||||
auto resources = getResourceManager(dst);
|
auto resources = getResourceManager(dst);
|
||||||
|
data->clear(resources);
|
||||||
if (src.data()) {
|
if (src.data()) {
|
||||||
size_t headerSize = src.size() >= 0x10000 ? 5
|
size_t headerSize = src.size() >= 0x10000 ? 5
|
||||||
: src.size() >= 0x100 ? 3
|
: src.size() >= 0x100 ? 3
|
||||||
@ -62,7 +63,6 @@ struct Converter<MsgPackBinary> : private detail::VariantAttorney {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data->setNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static MsgPackBinary fromJson(JsonVariantConst src) {
|
static MsgPackBinary fromJson(JsonVariantConst src) {
|
||||||
|
@ -35,6 +35,7 @@ struct Converter<MsgPackExtension> : private detail::VariantAttorney {
|
|||||||
if (!data)
|
if (!data)
|
||||||
return;
|
return;
|
||||||
auto resources = getResourceManager(dst);
|
auto resources = getResourceManager(dst);
|
||||||
|
data->clear(resources);
|
||||||
if (src.data()) {
|
if (src.data()) {
|
||||||
uint8_t format, sizeBytes;
|
uint8_t format, sizeBytes;
|
||||||
if (src.size() >= 0x10000) {
|
if (src.size() >= 0x10000) {
|
||||||
@ -76,7 +77,6 @@ struct Converter<MsgPackExtension> : private detail::VariantAttorney {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data->setNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static MsgPackExtension fromJson(JsonVariantConst src) {
|
static MsgPackExtension fromJson(JsonVariantConst src) {
|
||||||
|
@ -63,7 +63,9 @@ struct Converter<T, detail::enable_if_t<detail::is_integral<T>::value &&
|
|||||||
auto data = getData(dst);
|
auto data = getData(dst);
|
||||||
if (!data)
|
if (!data)
|
||||||
return false;
|
return false;
|
||||||
data->setInteger(src, getResourceManager(dst));
|
auto resources = getResourceManager(dst);
|
||||||
|
data->clear(resources);
|
||||||
|
data->setInteger(src);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +105,9 @@ struct Converter<bool> : private detail::VariantAttorney {
|
|||||||
auto data = getData(dst);
|
auto data = getData(dst);
|
||||||
if (!data)
|
if (!data)
|
||||||
return false;
|
return false;
|
||||||
data->setBoolean(src, getResourceManager(dst));
|
auto resources = getResourceManager(dst);
|
||||||
|
data->clear(resources);
|
||||||
|
data->setBoolean(src);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +129,9 @@ struct Converter<T, detail::enable_if_t<detail::is_floating_point<T>::value>>
|
|||||||
auto data = getData(dst);
|
auto data = getData(dst);
|
||||||
if (!data)
|
if (!data)
|
||||||
return false;
|
return false;
|
||||||
data->setFloat(static_cast<JsonFloat>(src), getResourceManager(dst));
|
auto resources = getResourceManager(dst);
|
||||||
|
data->clear(resources);
|
||||||
|
data->setFloat(static_cast<JsonFloat>(src));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +205,7 @@ struct Converter<SerializedValue<T>> : private detail::VariantAttorney {
|
|||||||
template <>
|
template <>
|
||||||
struct Converter<detail::nullptr_t> : private detail::VariantAttorney {
|
struct Converter<detail::nullptr_t> : private detail::VariantAttorney {
|
||||||
static void toJson(detail::nullptr_t, JsonVariant dst) {
|
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) {
|
static detail::nullptr_t fromJson(JsonVariantConst) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -252,12 +258,11 @@ inline void convertToJson(const ::Printable& src, JsonVariant dst) {
|
|||||||
auto data = detail::VariantAttorney::getData(dst);
|
auto data = detail::VariantAttorney::getData(dst);
|
||||||
if (!resources || !data)
|
if (!resources || !data)
|
||||||
return;
|
return;
|
||||||
|
data->clear(resources);
|
||||||
detail::StringBuilderPrint print(resources);
|
detail::StringBuilderPrint print(resources);
|
||||||
src.printTo(print);
|
src.printTo(print);
|
||||||
if (print.overflowed()) {
|
if (print.overflowed())
|
||||||
data->setNull();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
data->setOwnedString(print.save());
|
data->setOwnedString(print.save());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,64 +344,38 @@ class VariantData {
|
|||||||
var->removeMember(key, resources);
|
var->removeMember(key, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() { // TODO: remove
|
||||||
type_ = VALUE_IS_NULL;
|
type_ = VALUE_IS_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBoolean(bool value) {
|
void setBoolean(bool value) {
|
||||||
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
type_ = VALUE_IS_BOOLEAN;
|
type_ = VALUE_IS_BOOLEAN;
|
||||||
content_.asBoolean = value;
|
content_.asBoolean = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBoolean(bool value, ResourceManager* resources) {
|
|
||||||
release(resources);
|
|
||||||
setBoolean(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFloat(JsonFloat value) {
|
void setFloat(JsonFloat value) {
|
||||||
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
type_ = VALUE_IS_FLOAT;
|
type_ = VALUE_IS_FLOAT;
|
||||||
content_.asFloat = value;
|
content_.asFloat = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFloat(JsonFloat value, ResourceManager* resources) {
|
|
||||||
release(resources);
|
|
||||||
setFloat(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
enable_if_t<is_signed<T>::value> setInteger(T value) {
|
enable_if_t<is_signed<T>::value> setInteger(T value) {
|
||||||
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
type_ = VALUE_IS_SIGNED_INTEGER;
|
type_ = VALUE_IS_SIGNED_INTEGER;
|
||||||
content_.asSignedInteger = value;
|
content_.asSignedInteger = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
enable_if_t<is_unsigned<T>::value> setInteger(T value) {
|
enable_if_t<is_unsigned<T>::value> setInteger(T value) {
|
||||||
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
type_ = VALUE_IS_UNSIGNED_INTEGER;
|
type_ = VALUE_IS_UNSIGNED_INTEGER;
|
||||||
content_.asUnsignedInteger = static_cast<JsonUInt>(value);
|
content_.asUnsignedInteger = static_cast<JsonUInt>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
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) {
|
void setRawString(StringNode* s) {
|
||||||
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
ARDUINOJSON_ASSERT(s);
|
ARDUINOJSON_ASSERT(s);
|
||||||
type_ = VALUE_IS_RAW_STRING;
|
type_ = VALUE_IS_RAW_STRING;
|
||||||
content_.asOwnedString = s;
|
content_.asOwnedString = s;
|
||||||
@ -415,6 +389,7 @@ class VariantData {
|
|||||||
ResourceManager* resources) {
|
ResourceManager* resources) {
|
||||||
if (!var)
|
if (!var)
|
||||||
return;
|
return;
|
||||||
|
var->clear(resources);
|
||||||
var->setRawString(value, resources);
|
var->setRawString(value, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,16 +406,19 @@ class VariantData {
|
|||||||
ResourceManager* resources) {
|
ResourceManager* resources) {
|
||||||
if (!var)
|
if (!var)
|
||||||
return;
|
return;
|
||||||
|
var->clear(resources);
|
||||||
var->setString(value, resources);
|
var->setString(value, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLinkedString(const char* s) {
|
void setLinkedString(const char* s) {
|
||||||
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
ARDUINOJSON_ASSERT(s);
|
ARDUINOJSON_ASSERT(s);
|
||||||
type_ = VALUE_IS_LINKED_STRING;
|
type_ = VALUE_IS_LINKED_STRING;
|
||||||
content_.asLinkedString = s;
|
content_.asLinkedString = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setOwnedString(StringNode* s) {
|
void setOwnedString(StringNode* s) {
|
||||||
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
ARDUINOJSON_ASSERT(s);
|
ARDUINOJSON_ASSERT(s);
|
||||||
type_ = VALUE_IS_OWNED_STRING;
|
type_ = VALUE_IS_OWNED_STRING;
|
||||||
content_.asOwnedString = s;
|
content_.asOwnedString = s;
|
||||||
@ -461,45 +439,45 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ArrayData& toArray() {
|
ArrayData& toArray() {
|
||||||
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
type_ = VALUE_IS_ARRAY;
|
type_ = VALUE_IS_ARRAY;
|
||||||
new (&content_.asArray) ArrayData();
|
new (&content_.asArray) ArrayData();
|
||||||
return content_.asArray;
|
return content_.asArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayData& toArray(ResourceManager* resources) {
|
|
||||||
release(resources);
|
|
||||||
return toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
static ArrayData* toArray(VariantData* var, ResourceManager* resources) {
|
static ArrayData* toArray(VariantData* var, ResourceManager* resources) {
|
||||||
if (!var)
|
if (!var)
|
||||||
return 0;
|
return 0;
|
||||||
return &var->toArray(resources);
|
var->clear(resources);
|
||||||
|
return &var->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectData& toObject() {
|
ObjectData& toObject() {
|
||||||
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
type_ = VALUE_IS_OBJECT;
|
type_ = VALUE_IS_OBJECT;
|
||||||
new (&content_.asObject) ObjectData();
|
new (&content_.asObject) ObjectData();
|
||||||
return content_.asObject;
|
return content_.asObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectData& toObject(ResourceManager* resources) {
|
|
||||||
release(resources);
|
|
||||||
return toObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
static ObjectData* toObject(VariantData* var, ResourceManager* resources) {
|
static ObjectData* toObject(VariantData* var, ResourceManager* resources) {
|
||||||
if (!var)
|
if (!var)
|
||||||
return 0;
|
return 0;
|
||||||
return &var->toObject(resources);
|
var->clear(resources);
|
||||||
|
return &var->toObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t type() const {
|
uint8_t type() const {
|
||||||
return type_;
|
return type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
// Release the resources used by this variant and set it to null.
|
||||||
void release(ResourceManager* resources);
|
void clear(ResourceManager* resources);
|
||||||
|
|
||||||
|
static void clear(VariantData* var, ResourceManager* resources) {
|
||||||
|
if (!var)
|
||||||
|
return;
|
||||||
|
var->clear(resources);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
@ -12,18 +12,16 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline void VariantData::setRawString(SerializedValue<T> value,
|
inline void VariantData::setRawString(SerializedValue<T> value,
|
||||||
ResourceManager* resources) {
|
ResourceManager* resources) {
|
||||||
release(resources);
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
auto dup = resources->saveString(adaptString(value.data(), value.size()));
|
auto dup = resources->saveString(adaptString(value.data(), value.size()));
|
||||||
if (dup)
|
if (dup)
|
||||||
setRawString(dup);
|
setRawString(dup);
|
||||||
else
|
|
||||||
setNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
inline bool VariantData::setString(TAdaptedString value,
|
inline bool VariantData::setString(TAdaptedString value,
|
||||||
ResourceManager* resources) {
|
ResourceManager* resources) {
|
||||||
setNull(resources);
|
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
|
||||||
|
|
||||||
if (value.isNull())
|
if (value.isNull())
|
||||||
return false;
|
return false;
|
||||||
@ -42,13 +40,15 @@ inline bool VariantData::setString(TAdaptedString value,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void VariantData::release(ResourceManager* resources) {
|
inline void VariantData::clear(ResourceManager* resources) {
|
||||||
if (type_ & OWNED_VALUE_BIT)
|
if (type_ & OWNED_VALUE_BIT)
|
||||||
resources->dereferenceString(content_.asOwnedString->data);
|
resources->dereferenceString(content_.asOwnedString->data);
|
||||||
|
|
||||||
auto collection = asCollection();
|
auto collection = asCollection();
|
||||||
if (collection)
|
if (collection)
|
||||||
collection->clear(resources);
|
collection->clear(resources);
|
||||||
|
|
||||||
|
type_ = VALUE_IS_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
@ -29,7 +29,7 @@ class VariantRefBase : public VariantTag {
|
|||||||
// Sets the value to null.
|
// Sets the value to null.
|
||||||
// https://arduinojson.org/v7/api/jsonvariant/clear/
|
// https://arduinojson.org/v7/api/jsonvariant/clear/
|
||||||
void clear() const {
|
void clear() const {
|
||||||
VariantData::setNull(getOrCreateData(), getResourceManager());
|
VariantData::clear(getOrCreateData(), getResourceManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the value is null or the reference is unbound.
|
// Returns true if the value is null or the reference is unbound.
|
||||||
|
@ -174,7 +174,7 @@ enable_if_t<is_same<T, JsonVariant>::value, JsonVariant>
|
|||||||
VariantRefBase<TDerived>::to() const {
|
VariantRefBase<TDerived>::to() const {
|
||||||
auto data = getOrCreateData();
|
auto data = getOrCreateData();
|
||||||
auto resources = getResourceManager();
|
auto resources = getResourceManager();
|
||||||
detail::VariantData::setNull(data, resources);
|
detail::VariantData::clear(data, resources);
|
||||||
return JsonVariant(data, resources);
|
return JsonVariant(data, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user