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:
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 <typename T>

View File

@ -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 <typename T>
inline bool ArrayImpl::addValue(const T& value) {
if (!data_)
if (isNull())
return false;
auto slot = allocVariant();
if (!slot)

View File

@ -24,10 +24,6 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// 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.

View File

@ -38,7 +38,7 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
// 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) {}

View File

@ -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<VariantData*>(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;
}
};

View File

@ -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<VariantData> 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_)) {

View File

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

View File

@ -22,13 +22,9 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// 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());

View File

@ -23,7 +23,7 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
// 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) {}

View File

@ -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 <typename TAdaptedString>
VariantData* addMember(TAdaptedString key);

View File

@ -29,6 +29,8 @@ VariantData* ObjectImpl::getOrAddMember(TAdaptedString key) {
template <typename TAdaptedString>
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 <typename TAdaptedString>
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)

View File

@ -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;
}

View File

@ -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 <typename TAdaptedString>
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 <typename TAdaptedString>
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;
}