Skip to content

Commit

Permalink
Release VariantData resources explicitly before setting value
Browse files Browse the repository at this point in the history
  • Loading branch information
bblanchon committed Aug 26, 2024
1 parent 4ada3f8 commit e682337
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 64 deletions.
2 changes: 1 addition & 1 deletion src/ArduinoJson/Json/JsonDeserializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ class JsonDeserializer {
if (!member)
return DeserializationError::NoMemory;
} else {
member->setNull(resources_);
member->clear(resources_);
}

// Parse value
Expand Down
2 changes: 1 addition & 1 deletion src/ArduinoJson/Memory/ResourceManagerImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ inline Slot<VariantData> ResourceManager::allocVariant() {
}

inline void ResourceManager::freeVariant(Slot<VariantData> variant) {
variant->setNull(this);
variant->clear(this);
variantPools_.freeSlot(variant);
}

Expand Down
2 changes: 1 addition & 1 deletion src/ArduinoJson/MsgPack/MsgPackBinary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct Converter<MsgPackBinary> : 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
Expand Down Expand Up @@ -62,7 +63,6 @@ struct Converter<MsgPackBinary> : private detail::VariantAttorney {
return;
}
}
data->setNull();
}

static MsgPackBinary fromJson(JsonVariantConst src) {
Expand Down
2 changes: 1 addition & 1 deletion src/ArduinoJson/MsgPack/MsgPackExtension.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct Converter<MsgPackExtension> : private detail::VariantAttorney {
if (!data)
return;
auto resources = getResourceManager(dst);
data->clear(resources);
if (src.data()) {
uint8_t format, sizeBytes;
if (src.size() >= 0x10000) {
Expand Down Expand Up @@ -76,7 +77,6 @@ struct Converter<MsgPackExtension> : private detail::VariantAttorney {
return;
}
}
data->setNull();
}

static MsgPackExtension fromJson(JsonVariantConst src) {
Expand Down
19 changes: 12 additions & 7 deletions src/ArduinoJson/Variant/ConverterImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ struct Converter<T, detail::enable_if_t<detail::is_integral<T>::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;
}

Expand Down Expand Up @@ -103,7 +105,9 @@ struct Converter<bool> : 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;
}

Expand All @@ -125,7 +129,9 @@ struct Converter<T, detail::enable_if_t<detail::is_floating_point<T>::value>>
auto data = getData(dst);
if (!data)
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;
}

Expand Down Expand Up @@ -199,7 +205,7 @@ struct Converter<SerializedValue<T>> : private detail::VariantAttorney {
template <>
struct Converter<detail::nullptr_t> : 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;
Expand Down Expand Up @@ -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());
}

Expand Down
70 changes: 24 additions & 46 deletions src/ArduinoJson/Variant/VariantData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename T>
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;
content_.asSignedInteger = value;
}

template <typename T>
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;
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) {
ARDUINOJSON_ASSERT(type_ == VALUE_IS_NULL); // must call clear() first
ARDUINOJSON_ASSERT(s);
type_ = VALUE_IS_RAW_STRING;
content_.asOwnedString = s;
Expand All @@ -415,6 +389,7 @@ class VariantData {
ResourceManager* resources) {
if (!var)
return;
var->clear(resources);
var->setRawString(value, resources);
}

Expand All @@ -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;
Expand All @@ -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
10 changes: 5 additions & 5 deletions src/ArduinoJson/Variant/VariantImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,16 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename T>
inline void VariantData::setRawString(SerializedValue<T> 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 <typename TAdaptedString>
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;
Expand All @@ -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
2 changes: 1 addition & 1 deletion src/ArduinoJson/Variant/VariantRefBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/ArduinoJson/Variant/VariantRefBaseImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ enable_if_t<is_same<T, JsonVariant>::value, JsonVariant>
VariantRefBase<TDerived>::to() const {
auto data = getOrCreateData();
auto resources = getResourceManager();
detail::VariantData::setNull(data, resources);
detail::VariantData::clear(data, resources);
return JsonVariant(data, resources);
}

Expand Down

0 comments on commit e682337

Please sign in to comment.