From 485078abcbe692b9711973e3058f264e99a5301d Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Thu, 3 Jul 2025 11:03:10 +0200 Subject: [PATCH] CollectionImpl: attach to `VariantData*` instead of `CollectionData*` --- src/ArduinoJson/Array/ArrayData.hpp | 6 ++- src/ArduinoJson/Array/ArrayImpl.hpp | 7 +++- src/ArduinoJson/Array/JsonArray.hpp | 4 -- src/ArduinoJson/Array/JsonArrayConst.hpp | 2 +- src/ArduinoJson/Collection/CollectionData.hpp | 14 +++---- src/ArduinoJson/Collection/CollectionImpl.hpp | 6 +-- src/ArduinoJson/Json/JsonDeserializer.hpp | 4 +- src/ArduinoJson/Object/JsonObject.hpp | 6 +-- src/ArduinoJson/Object/JsonObjectConst.hpp | 2 +- src/ArduinoJson/Object/ObjectData.hpp | 6 ++- src/ArduinoJson/Object/ObjectImpl.hpp | 7 ++-- src/ArduinoJson/Variant/VariantData.hpp | 31 ++++++--------- src/ArduinoJson/Variant/VariantImpl.hpp | 38 +++++-------------- 13 files changed, 56 insertions(+), 77 deletions(-) diff --git a/src/ArduinoJson/Array/ArrayData.hpp b/src/ArduinoJson/Array/ArrayData.hpp index 12855bcd..b6330476 100644 --- a/src/ArduinoJson/Array/ArrayData.hpp +++ b/src/ArduinoJson/Array/ArrayData.hpp @@ -12,9 +12,13 @@ class ArrayImpl : public CollectionImpl { public: ArrayImpl() {} - ArrayImpl(CollectionData* data, ResourceManager* resources) + ArrayImpl(VariantData* data, ResourceManager* resources) : CollectionImpl(data, resources) {} + bool isNull() const { + return !data_ || data_->type != VariantType::Array; + } + VariantData* addElement(); template diff --git a/src/ArduinoJson/Array/ArrayImpl.hpp b/src/ArduinoJson/Array/ArrayImpl.hpp index 5f074d10..c73d5ccd 100644 --- a/src/ArduinoJson/Array/ArrayImpl.hpp +++ b/src/ArduinoJson/Array/ArrayImpl.hpp @@ -11,6 +11,9 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE inline ArrayImpl::iterator ArrayImpl::at(size_t index) const { + if (isNull()) + return iterator(); + auto it = createIterator(); while (!it.done() && index) { it.next(resources_); @@ -20,7 +23,7 @@ inline ArrayImpl::iterator ArrayImpl::at(size_t index) const { } inline VariantData* ArrayImpl::addElement() { - if (!data_) + if (isNull()) return nullptr; auto slot = allocVariant(); if (!slot) @@ -57,7 +60,7 @@ inline void ArrayImpl::removeElement(size_t index) { template inline bool ArrayImpl::addValue(const T& value) { - if (!data_) + if (isNull()) return false; auto slot = allocVariant(); if (!slot) diff --git a/src/ArduinoJson/Array/JsonArray.hpp b/src/ArduinoJson/Array/JsonArray.hpp index 636cfe5a..74f1caf4 100644 --- a/src/ArduinoJson/Array/JsonArray.hpp +++ b/src/ArduinoJson/Array/JsonArray.hpp @@ -24,10 +24,6 @@ class JsonArray : public detail::VariantOperators { // INTERNAL USE ONLY JsonArray(detail::VariantData* data, detail::ResourceManager* resources) - : impl_(data ? data->asArray() : nullptr, resources) {} - - // INTERNAL USE ONLY - JsonArray(detail::CollectionData* data, detail::ResourceManager* resources) : impl_(data, resources) {} // Returns a JsonVariant pointing to the array. diff --git a/src/ArduinoJson/Array/JsonArrayConst.hpp b/src/ArduinoJson/Array/JsonArrayConst.hpp index 2d9938b7..feae9ab1 100644 --- a/src/ArduinoJson/Array/JsonArrayConst.hpp +++ b/src/ArduinoJson/Array/JsonArrayConst.hpp @@ -38,7 +38,7 @@ class JsonArrayConst : public detail::VariantOperators { // INTERNAL USE ONLY JsonArrayConst(detail::VariantData* data, detail::ResourceManager* resources) - : impl_(data ? data->asArray() : nullptr, resources) {} + : impl_(data, resources) {} // INTERNAL USE ONLY JsonArrayConst(const detail::ArrayImpl& impl) : impl_(impl) {} diff --git a/src/ArduinoJson/Collection/CollectionData.hpp b/src/ArduinoJson/Collection/CollectionData.hpp index 7d78c433..3fd6287f 100644 --- a/src/ArduinoJson/Collection/CollectionData.hpp +++ b/src/ArduinoJson/Collection/CollectionData.hpp @@ -66,7 +66,7 @@ class CollectionIterator { class CollectionImpl { protected: - CollectionData* data_; + VariantData* data_; ResourceManager* resources_; public: @@ -74,20 +74,19 @@ class CollectionImpl { CollectionImpl() : data_(nullptr), resources_(nullptr) {} - CollectionImpl(CollectionData* data, ResourceManager* resources) + CollectionImpl(VariantData* data, ResourceManager* resources) : data_(data), resources_(resources) {} explicit operator bool() const { - return data_ != nullptr; + return data_ && data_->isCollection(); } bool isNull() const { - return data_ == nullptr; + return !operator bool(); } VariantData* getData() const { - void* data = data_; // prevent warning cast-align - return reinterpret_cast(data); + return data_; } ResourceManager* getResourceManager() const { @@ -132,7 +131,8 @@ class CollectionImpl { CollectionData* getCollectionData() const { ARDUINOJSON_ASSERT(data_ != nullptr); - return data_; + ARDUINOJSON_ASSERT(data_->isCollection()); + return &data_->content.asCollection; } }; diff --git a/src/ArduinoJson/Collection/CollectionImpl.hpp b/src/ArduinoJson/Collection/CollectionImpl.hpp index 3e980b8c..17b168cc 100644 --- a/src/ArduinoJson/Collection/CollectionImpl.hpp +++ b/src/ArduinoJson/Collection/CollectionImpl.hpp @@ -26,7 +26,7 @@ inline void CollectionIterator::next(const ResourceManager* resources) { } inline CollectionImpl::iterator CollectionImpl::createIterator() const { - if (!data_) + if (!data_ || !data_->isCollection()) return iterator(); auto coll = getCollectionData(); return iterator(getVariant(coll->head), coll->head); @@ -62,7 +62,7 @@ inline void CollectionImpl::appendPair(Slot key, } inline void CollectionImpl::clear() { - if (!data_) + if (!data_ || !data_->isCollection()) return; auto coll = getCollectionData(); @@ -128,7 +128,7 @@ inline void CollectionImpl::removePair(ObjectImpl::iterator it) { } inline size_t CollectionImpl::nesting() const { - if (!data_) + if (!data_ || !data_->isCollection()) return 0; size_t maxChildNesting = 0; for (auto it = createIterator(); !it.done(); it.next(resources_)) { diff --git a/src/ArduinoJson/Json/JsonDeserializer.hpp b/src/ArduinoJson/Json/JsonDeserializer.hpp index bddb631f..1f29535e 100644 --- a/src/ArduinoJson/Json/JsonDeserializer.hpp +++ b/src/ArduinoJson/Json/JsonDeserializer.hpp @@ -148,7 +148,7 @@ class JsonDeserializer { template DeserializationError::Code parseArray( - CollectionData* arrayData, TFilter filter, + VariantData* arrayData, TFilter filter, DeserializationOption::NestingLimit nestingLimit) { DeserializationError::Code err; @@ -236,7 +236,7 @@ class JsonDeserializer { template DeserializationError::Code parseObject( - CollectionData* objectData, TFilter filter, + VariantData* objectData, TFilter filter, DeserializationOption::NestingLimit nestingLimit) { DeserializationError::Code err; diff --git a/src/ArduinoJson/Object/JsonObject.hpp b/src/ArduinoJson/Object/JsonObject.hpp index 76f7ace8..b1fc5b2b 100644 --- a/src/ArduinoJson/Object/JsonObject.hpp +++ b/src/ArduinoJson/Object/JsonObject.hpp @@ -22,13 +22,9 @@ class JsonObject : public detail::VariantOperators { // Creates an unbound reference. JsonObject() {} - // INTERNAL USE ONLY - JsonObject(detail::CollectionData* data, detail::ResourceManager* resource) - : impl_(data, resource) {} - // INTERNAL USE ONLY JsonObject(detail::VariantData* data, detail::ResourceManager* resource) - : impl_(data ? data->asObject() : nullptr, resource) {} + : impl_(data, resource) {} operator JsonVariant() const { return JsonVariant(getData(), getResourceManager()); diff --git a/src/ArduinoJson/Object/JsonObjectConst.hpp b/src/ArduinoJson/Object/JsonObjectConst.hpp index 685a6162..9c4586eb 100644 --- a/src/ArduinoJson/Object/JsonObjectConst.hpp +++ b/src/ArduinoJson/Object/JsonObjectConst.hpp @@ -23,7 +23,7 @@ class JsonObjectConst : public detail::VariantOperators { // INTERNAL USE ONLY JsonObjectConst(detail::VariantData* data, detail::ResourceManager* resources) - : impl_(data ? data->asObject() : nullptr, resources) {} + : impl_(data, resources) {} // INTERNAL USE ONLY JsonObjectConst(const detail::ObjectImpl& impl) : impl_(impl) {} diff --git a/src/ArduinoJson/Object/ObjectData.hpp b/src/ArduinoJson/Object/ObjectData.hpp index a52f8b96..6e8ece08 100644 --- a/src/ArduinoJson/Object/ObjectData.hpp +++ b/src/ArduinoJson/Object/ObjectData.hpp @@ -14,9 +14,13 @@ class ObjectImpl : public CollectionImpl { public: ObjectImpl() {} - ObjectImpl(CollectionData* data, ResourceManager* resources) + ObjectImpl(VariantData* data, ResourceManager* resources) : CollectionImpl(data, resources) {} + bool isNull() const { + return !data_ || data_->type != VariantType::Object; + } + template VariantData* addMember(TAdaptedString key); diff --git a/src/ArduinoJson/Object/ObjectImpl.hpp b/src/ArduinoJson/Object/ObjectImpl.hpp index c2ead28e..3be3757e 100644 --- a/src/ArduinoJson/Object/ObjectImpl.hpp +++ b/src/ArduinoJson/Object/ObjectImpl.hpp @@ -29,6 +29,8 @@ VariantData* ObjectImpl::getOrAddMember(TAdaptedString key) { template inline ObjectImpl::iterator ObjectImpl::findKey(TAdaptedString key) const { + if (isNull()) + return iterator(); if (key.isNull()) return iterator(); bool isKey = true; @@ -48,7 +50,7 @@ inline void ObjectImpl::removeMember(TAdaptedString key) { template inline VariantData* ObjectImpl::addMember(TAdaptedString key) { - if (!data_) + if (isNull()) return nullptr; auto keySlot = allocVariant(); @@ -69,8 +71,7 @@ inline VariantData* ObjectImpl::addMember(TAdaptedString key) { } inline VariantData* ObjectImpl::addPair(VariantData** value) { - if (!data_) - return nullptr; + ARDUINOJSON_ASSERT(!isNull()); auto keySlot = allocVariant(); if (!keySlot) diff --git a/src/ArduinoJson/Variant/VariantData.hpp b/src/ArduinoJson/Variant/VariantData.hpp index 1b900007..82b60b63 100644 --- a/src/ArduinoJson/Variant/VariantData.hpp +++ b/src/ArduinoJson/Variant/VariantData.hpp @@ -71,17 +71,8 @@ struct VariantData { content.asOwnedString = s; } - CollectionData* asCollection() { - return type & VariantTypeBits::CollectionMask ? &content.asCollection - : nullptr; - } - - CollectionData* asArray() { - return type == VariantType::Array ? &content.asCollection : nullptr; - } - - CollectionData* asObject() { - return type == VariantType::Object ? &content.asCollection : nullptr; + bool isCollection() const { + return type & VariantTypeBits::CollectionMask; } bool isFloat() const { @@ -93,35 +84,37 @@ struct VariantData { type == VariantType::OwnedString || type == VariantType::TinyString; } - CollectionData* toArray() { + VariantData* toArray() { ARDUINOJSON_ASSERT(type == VariantType::Null); type = VariantType::Array; - return new (&content.asCollection) CollectionData(); + new (&content.asCollection) CollectionData(); + return this; } - CollectionData* toObject() { + VariantData* toObject() { ARDUINOJSON_ASSERT(type == VariantType::Null); type = VariantType::Object; - return new (&content.asCollection) CollectionData(); + new (&content.asCollection) CollectionData(); + return this; } - CollectionData* getOrCreateArray() { + VariantData* getOrCreateArray() { switch (type) { case VariantType::Null: return toArray(); case VariantType::Array: - return &content.asCollection; + return this; default: return nullptr; } } - CollectionData* getOrCreateObject() { + VariantData* getOrCreateObject() { switch (type) { case VariantType::Null: return toObject(); case VariantType::Object: - return &content.asCollection; + return this; default: return nullptr; } diff --git a/src/ArduinoJson/Variant/VariantImpl.hpp b/src/ArduinoJson/Variant/VariantImpl.hpp index 9c5acf78..424afd65 100644 --- a/src/ArduinoJson/Variant/VariantImpl.hpp +++ b/src/ArduinoJson/Variant/VariantImpl.hpp @@ -48,11 +48,10 @@ class VariantImpl { #endif case VariantType::Array: - return visit.visit(ArrayImpl(&data_->content.asCollection, resources_)); + return visit.visit(ArrayImpl(data_, resources_)); case VariantType::Object: - return visit.visit( - ObjectImpl(&data_->content.asCollection, resources_)); + return visit.visit(ObjectImpl(data_, resources_)); case VariantType::TinyString: return visit.visit(JsonString(data_->content.asTinyString)); @@ -264,16 +263,12 @@ class VariantImpl { #endif VariantData* getElement(size_t index) { - if (!data_) - return nullptr; - return ArrayImpl(data_->asArray(), resources_).getElement(index); + return ArrayImpl(data_, resources_).getElement(index); } template VariantData* getMember(TAdaptedString key) { - if (!data_) - return nullptr; - return ObjectImpl(data_->asObject(), resources_).getMember(key); + return ObjectImpl(data_, resources_).getMember(key); } VariantData* getOrAddElement(size_t index) { @@ -301,10 +296,6 @@ class VariantImpl { return type() == VariantType::Boolean; } - bool isCollection() const { - return type() & VariantTypeBits::CollectionMask; - } - bool isFloat() const { return data_ && data_->isFloat(); } @@ -350,22 +341,16 @@ class VariantImpl { } size_t nesting() { - if (!data_) - return 0; - return CollectionImpl(data_->asCollection(), resources_).nesting(); + return CollectionImpl(data_, resources_).nesting(); } void removeElement(size_t index) { - if (!data_) - return; - ArrayImpl(data_->asArray(), resources_).removeElement(index); + ArrayImpl(data_, resources_).removeElement(index); } template void removeMember(TAdaptedString key) { - if (!data_) - return; - ObjectImpl(data_->asObject(), resources_).removeMember(key); + ObjectImpl(data_, resources_).removeMember(key); } bool setBoolean(bool value) { @@ -470,12 +455,9 @@ class VariantImpl { bool setLinkedString(const char* s); size_t size() { - if (!data_) - return 0; + auto size = CollectionImpl(data_, resources_).size(); - auto size = CollectionImpl(data_->asCollection(), resources_).size(); - - if (data_->type == VariantType::Object) + if (data_ && data_->type == VariantType::Object) size /= 2; return size; @@ -554,7 +536,7 @@ inline void VariantImpl::clear() { resources_->freeEightByte(data_->content.asSlotId); #endif - CollectionImpl(data_->asCollection(), resources_).clear(); + CollectionImpl(data_, resources_).clear(); data_->type = VariantType::Null; }