CollectionImpl: attach to VariantData* instead of CollectionData*

This commit is contained in:
Benoit Blanchon
2025-07-03 11:03:10 +02:00
parent 9a26c04e39
commit 485078abcb
13 changed files with 56 additions and 77 deletions

View File

@ -12,9 +12,13 @@ class ArrayImpl : public CollectionImpl {
public: public:
ArrayImpl() {} ArrayImpl() {}
ArrayImpl(CollectionData* data, ResourceManager* resources) ArrayImpl(VariantData* data, ResourceManager* resources)
: CollectionImpl(data, resources) {} : CollectionImpl(data, resources) {}
bool isNull() const {
return !data_ || data_->type != VariantType::Array;
}
VariantData* addElement(); VariantData* addElement();
template <typename T> template <typename T>

View File

@ -11,6 +11,9 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
inline ArrayImpl::iterator ArrayImpl::at(size_t index) const { inline ArrayImpl::iterator ArrayImpl::at(size_t index) const {
if (isNull())
return iterator();
auto it = createIterator(); auto it = createIterator();
while (!it.done() && index) { while (!it.done() && index) {
it.next(resources_); it.next(resources_);
@ -20,7 +23,7 @@ inline ArrayImpl::iterator ArrayImpl::at(size_t index) const {
} }
inline VariantData* ArrayImpl::addElement() { inline VariantData* ArrayImpl::addElement() {
if (!data_) if (isNull())
return nullptr; return nullptr;
auto slot = allocVariant(); auto slot = allocVariant();
if (!slot) if (!slot)
@ -57,7 +60,7 @@ inline void ArrayImpl::removeElement(size_t index) {
template <typename T> template <typename T>
inline bool ArrayImpl::addValue(const T& value) { inline bool ArrayImpl::addValue(const T& value) {
if (!data_) if (isNull())
return false; return false;
auto slot = allocVariant(); auto slot = allocVariant();
if (!slot) if (!slot)

View File

@ -24,10 +24,6 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// INTERNAL USE ONLY // INTERNAL USE ONLY
JsonArray(detail::VariantData* data, detail::ResourceManager* resources) 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) {} : impl_(data, resources) {}
// Returns a JsonVariant pointing to the array. // Returns a JsonVariant pointing to the array.

View File

@ -38,7 +38,7 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
// INTERNAL USE ONLY // INTERNAL USE ONLY
JsonArrayConst(detail::VariantData* data, detail::ResourceManager* resources) JsonArrayConst(detail::VariantData* data, detail::ResourceManager* resources)
: impl_(data ? data->asArray() : nullptr, resources) {} : impl_(data, resources) {}
// INTERNAL USE ONLY // INTERNAL USE ONLY
JsonArrayConst(const detail::ArrayImpl& impl) : impl_(impl) {} JsonArrayConst(const detail::ArrayImpl& impl) : impl_(impl) {}

View File

@ -66,7 +66,7 @@ class CollectionIterator {
class CollectionImpl { class CollectionImpl {
protected: protected:
CollectionData* data_; VariantData* data_;
ResourceManager* resources_; ResourceManager* resources_;
public: public:
@ -74,20 +74,19 @@ class CollectionImpl {
CollectionImpl() : data_(nullptr), resources_(nullptr) {} CollectionImpl() : data_(nullptr), resources_(nullptr) {}
CollectionImpl(CollectionData* data, ResourceManager* resources) CollectionImpl(VariantData* data, ResourceManager* resources)
: data_(data), resources_(resources) {} : data_(data), resources_(resources) {}
explicit operator bool() const { explicit operator bool() const {
return data_ != nullptr; return data_ && data_->isCollection();
} }
bool isNull() const { bool isNull() const {
return data_ == nullptr; return !operator bool();
} }
VariantData* getData() const { VariantData* getData() const {
void* data = data_; // prevent warning cast-align return data_;
return reinterpret_cast<VariantData*>(data);
} }
ResourceManager* getResourceManager() const { ResourceManager* getResourceManager() const {
@ -132,7 +131,8 @@ class CollectionImpl {
CollectionData* getCollectionData() const { CollectionData* getCollectionData() const {
ARDUINOJSON_ASSERT(data_ != nullptr); ARDUINOJSON_ASSERT(data_ != nullptr);
return data_; ARDUINOJSON_ASSERT(data_->isCollection());
return &data_->content.asCollection;
} }
}; };

View File

@ -26,7 +26,7 @@ inline void CollectionIterator::next(const ResourceManager* resources) {
} }
inline CollectionImpl::iterator CollectionImpl::createIterator() const { inline CollectionImpl::iterator CollectionImpl::createIterator() const {
if (!data_) if (!data_ || !data_->isCollection())
return iterator(); return iterator();
auto coll = getCollectionData(); auto coll = getCollectionData();
return iterator(getVariant(coll->head), coll->head); return iterator(getVariant(coll->head), coll->head);
@ -62,7 +62,7 @@ inline void CollectionImpl::appendPair(Slot<VariantData> key,
} }
inline void CollectionImpl::clear() { inline void CollectionImpl::clear() {
if (!data_) if (!data_ || !data_->isCollection())
return; return;
auto coll = getCollectionData(); auto coll = getCollectionData();
@ -128,7 +128,7 @@ inline void CollectionImpl::removePair(ObjectImpl::iterator it) {
} }
inline size_t CollectionImpl::nesting() const { inline size_t CollectionImpl::nesting() const {
if (!data_) if (!data_ || !data_->isCollection())
return 0; return 0;
size_t maxChildNesting = 0; size_t maxChildNesting = 0;
for (auto it = createIterator(); !it.done(); it.next(resources_)) { for (auto it = createIterator(); !it.done(); it.next(resources_)) {

View File

@ -148,7 +148,7 @@ class JsonDeserializer {
template <typename TFilter> template <typename TFilter>
DeserializationError::Code parseArray( DeserializationError::Code parseArray(
CollectionData* arrayData, TFilter filter, VariantData* arrayData, TFilter filter,
DeserializationOption::NestingLimit nestingLimit) { DeserializationOption::NestingLimit nestingLimit) {
DeserializationError::Code err; DeserializationError::Code err;
@ -236,7 +236,7 @@ class JsonDeserializer {
template <typename TFilter> template <typename TFilter>
DeserializationError::Code parseObject( DeserializationError::Code parseObject(
CollectionData* objectData, TFilter filter, VariantData* objectData, TFilter filter,
DeserializationOption::NestingLimit nestingLimit) { DeserializationOption::NestingLimit nestingLimit) {
DeserializationError::Code err; DeserializationError::Code err;

View File

@ -22,13 +22,9 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// Creates an unbound reference. // Creates an unbound reference.
JsonObject() {} JsonObject() {}
// INTERNAL USE ONLY
JsonObject(detail::CollectionData* data, detail::ResourceManager* resource)
: impl_(data, resource) {}
// INTERNAL USE ONLY // INTERNAL USE ONLY
JsonObject(detail::VariantData* data, detail::ResourceManager* resource) JsonObject(detail::VariantData* data, detail::ResourceManager* resource)
: impl_(data ? data->asObject() : nullptr, resource) {} : impl_(data, resource) {}
operator JsonVariant() const { operator JsonVariant() const {
return JsonVariant(getData(), getResourceManager()); return JsonVariant(getData(), getResourceManager());

View File

@ -23,7 +23,7 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
// INTERNAL USE ONLY // INTERNAL USE ONLY
JsonObjectConst(detail::VariantData* data, detail::ResourceManager* resources) JsonObjectConst(detail::VariantData* data, detail::ResourceManager* resources)
: impl_(data ? data->asObject() : nullptr, resources) {} : impl_(data, resources) {}
// INTERNAL USE ONLY // INTERNAL USE ONLY
JsonObjectConst(const detail::ObjectImpl& impl) : impl_(impl) {} JsonObjectConst(const detail::ObjectImpl& impl) : impl_(impl) {}

View File

@ -14,9 +14,13 @@ class ObjectImpl : public CollectionImpl {
public: public:
ObjectImpl() {} ObjectImpl() {}
ObjectImpl(CollectionData* data, ResourceManager* resources) ObjectImpl(VariantData* data, ResourceManager* resources)
: CollectionImpl(data, resources) {} : CollectionImpl(data, resources) {}
bool isNull() const {
return !data_ || data_->type != VariantType::Object;
}
template <typename TAdaptedString> template <typename TAdaptedString>
VariantData* addMember(TAdaptedString key); VariantData* addMember(TAdaptedString key);

View File

@ -29,6 +29,8 @@ VariantData* ObjectImpl::getOrAddMember(TAdaptedString key) {
template <typename TAdaptedString> template <typename TAdaptedString>
inline ObjectImpl::iterator ObjectImpl::findKey(TAdaptedString key) const { inline ObjectImpl::iterator ObjectImpl::findKey(TAdaptedString key) const {
if (isNull())
return iterator();
if (key.isNull()) if (key.isNull())
return iterator(); return iterator();
bool isKey = true; bool isKey = true;
@ -48,7 +50,7 @@ inline void ObjectImpl::removeMember(TAdaptedString key) {
template <typename TAdaptedString> template <typename TAdaptedString>
inline VariantData* ObjectImpl::addMember(TAdaptedString key) { inline VariantData* ObjectImpl::addMember(TAdaptedString key) {
if (!data_) if (isNull())
return nullptr; return nullptr;
auto keySlot = allocVariant(); auto keySlot = allocVariant();
@ -69,8 +71,7 @@ inline VariantData* ObjectImpl::addMember(TAdaptedString key) {
} }
inline VariantData* ObjectImpl::addPair(VariantData** value) { inline VariantData* ObjectImpl::addPair(VariantData** value) {
if (!data_) ARDUINOJSON_ASSERT(!isNull());
return nullptr;
auto keySlot = allocVariant(); auto keySlot = allocVariant();
if (!keySlot) if (!keySlot)

View File

@ -71,17 +71,8 @@ struct VariantData {
content.asOwnedString = s; content.asOwnedString = s;
} }
CollectionData* asCollection() { bool isCollection() const {
return type & VariantTypeBits::CollectionMask ? &content.asCollection return type & VariantTypeBits::CollectionMask;
: nullptr;
}
CollectionData* asArray() {
return type == VariantType::Array ? &content.asCollection : nullptr;
}
CollectionData* asObject() {
return type == VariantType::Object ? &content.asCollection : nullptr;
} }
bool isFloat() const { bool isFloat() const {
@ -93,35 +84,37 @@ struct VariantData {
type == VariantType::OwnedString || type == VariantType::TinyString; type == VariantType::OwnedString || type == VariantType::TinyString;
} }
CollectionData* toArray() { VariantData* toArray() {
ARDUINOJSON_ASSERT(type == VariantType::Null); ARDUINOJSON_ASSERT(type == VariantType::Null);
type = VariantType::Array; type = VariantType::Array;
return new (&content.asCollection) CollectionData(); new (&content.asCollection) CollectionData();
return this;
} }
CollectionData* toObject() { VariantData* toObject() {
ARDUINOJSON_ASSERT(type == VariantType::Null); ARDUINOJSON_ASSERT(type == VariantType::Null);
type = VariantType::Object; type = VariantType::Object;
return new (&content.asCollection) CollectionData(); new (&content.asCollection) CollectionData();
return this;
} }
CollectionData* getOrCreateArray() { VariantData* getOrCreateArray() {
switch (type) { switch (type) {
case VariantType::Null: case VariantType::Null:
return toArray(); return toArray();
case VariantType::Array: case VariantType::Array:
return &content.asCollection; return this;
default: default:
return nullptr; return nullptr;
} }
} }
CollectionData* getOrCreateObject() { VariantData* getOrCreateObject() {
switch (type) { switch (type) {
case VariantType::Null: case VariantType::Null:
return toObject(); return toObject();
case VariantType::Object: case VariantType::Object:
return &content.asCollection; return this;
default: default:
return nullptr; return nullptr;
} }

View File

@ -48,11 +48,10 @@ class VariantImpl {
#endif #endif
case VariantType::Array: case VariantType::Array:
return visit.visit(ArrayImpl(&data_->content.asCollection, resources_)); return visit.visit(ArrayImpl(data_, resources_));
case VariantType::Object: case VariantType::Object:
return visit.visit( return visit.visit(ObjectImpl(data_, resources_));
ObjectImpl(&data_->content.asCollection, resources_));
case VariantType::TinyString: case VariantType::TinyString:
return visit.visit(JsonString(data_->content.asTinyString)); return visit.visit(JsonString(data_->content.asTinyString));
@ -264,16 +263,12 @@ class VariantImpl {
#endif #endif
VariantData* getElement(size_t index) { VariantData* getElement(size_t index) {
if (!data_) return ArrayImpl(data_, resources_).getElement(index);
return nullptr;
return ArrayImpl(data_->asArray(), resources_).getElement(index);
} }
template <typename TAdaptedString> template <typename TAdaptedString>
VariantData* getMember(TAdaptedString key) { VariantData* getMember(TAdaptedString key) {
if (!data_) return ObjectImpl(data_, resources_).getMember(key);
return nullptr;
return ObjectImpl(data_->asObject(), resources_).getMember(key);
} }
VariantData* getOrAddElement(size_t index) { VariantData* getOrAddElement(size_t index) {
@ -301,10 +296,6 @@ class VariantImpl {
return type() == VariantType::Boolean; return type() == VariantType::Boolean;
} }
bool isCollection() const {
return type() & VariantTypeBits::CollectionMask;
}
bool isFloat() const { bool isFloat() const {
return data_ && data_->isFloat(); return data_ && data_->isFloat();
} }
@ -350,22 +341,16 @@ class VariantImpl {
} }
size_t nesting() { size_t nesting() {
if (!data_) return CollectionImpl(data_, resources_).nesting();
return 0;
return CollectionImpl(data_->asCollection(), resources_).nesting();
} }
void removeElement(size_t index) { void removeElement(size_t index) {
if (!data_) ArrayImpl(data_, resources_).removeElement(index);
return;
ArrayImpl(data_->asArray(), resources_).removeElement(index);
} }
template <typename TAdaptedString> template <typename TAdaptedString>
void removeMember(TAdaptedString key) { void removeMember(TAdaptedString key) {
if (!data_) ObjectImpl(data_, resources_).removeMember(key);
return;
ObjectImpl(data_->asObject(), resources_).removeMember(key);
} }
bool setBoolean(bool value) { bool setBoolean(bool value) {
@ -470,12 +455,9 @@ class VariantImpl {
bool setLinkedString(const char* s); bool setLinkedString(const char* s);
size_t size() { size_t size() {
if (!data_) auto size = CollectionImpl(data_, resources_).size();
return 0;
auto size = CollectionImpl(data_->asCollection(), resources_).size(); if (data_ && data_->type == VariantType::Object)
if (data_->type == VariantType::Object)
size /= 2; size /= 2;
return size; return size;
@ -554,7 +536,7 @@ inline void VariantImpl::clear() {
resources_->freeEightByte(data_->content.asSlotId); resources_->freeEightByte(data_->content.asSlotId);
#endif #endif
CollectionImpl(data_->asCollection(), resources_).clear(); CollectionImpl(data_, resources_).clear();
data_->type = VariantType::Null; data_->type = VariantType::Null;
} }