From 48dec78781595e1f5442648c4a10dc9f0afbc847 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 25 Jun 2025 16:29:07 +0200 Subject: [PATCH] Extract `ArrayImpl`, `CollectionImpl`, and `ObjectImpl` --- src/ArduinoJson/Array/ArrayData.hpp | 55 ++----- src/ArduinoJson/Array/ArrayImpl.hpp | 48 +++--- src/ArduinoJson/Array/ElementProxy.hpp | 6 +- src/ArduinoJson/Array/JsonArray.hpp | 51 +++--- src/ArduinoJson/Array/JsonArrayConst.hpp | 33 ++-- src/ArduinoJson/Array/JsonArrayIterator.hpp | 12 +- src/ArduinoJson/Collection/CollectionData.hpp | 78 ++++++---- src/ArduinoJson/Collection/CollectionImpl.hpp | 94 +++++------ src/ArduinoJson/Document/JsonDocument.hpp | 4 +- src/ArduinoJson/Json/JsonDeserializer.hpp | 15 +- src/ArduinoJson/Json/JsonSerializer.hpp | 8 +- src/ArduinoJson/Json/PrettyJsonSerializer.hpp | 10 +- .../MsgPack/MsgPackDeserializer.hpp | 19 +-- src/ArduinoJson/MsgPack/MsgPackSerializer.hpp | 12 +- src/ArduinoJson/Object/JsonObject.hpp | 54 +++---- src/ArduinoJson/Object/JsonObjectConst.hpp | 44 +++--- src/ArduinoJson/Object/JsonObjectIterator.hpp | 12 +- src/ArduinoJson/Object/JsonPair.hpp | 6 +- src/ArduinoJson/Object/ObjectData.hpp | 61 +++----- src/ArduinoJson/Object/ObjectImpl.hpp | 54 +++---- src/ArduinoJson/Variant/JsonVariantConst.hpp | 12 +- .../Variant/JsonVariantVisitor.hpp | 16 +- src/ArduinoJson/Variant/VariantContent.hpp | 2 - src/ArduinoJson/Variant/VariantData.hpp | 146 +++++++----------- src/ArduinoJson/Variant/VariantImpl.hpp | 4 +- .../Variant/VariantRefBaseImpl.hpp | 6 +- 26 files changed, 382 insertions(+), 480 deletions(-) diff --git a/src/ArduinoJson/Array/ArrayData.hpp b/src/ArduinoJson/Array/ArrayData.hpp index 79ade355..12855bcd 100644 --- a/src/ArduinoJson/Array/ArrayData.hpp +++ b/src/ArduinoJson/Array/ArrayData.hpp @@ -8,59 +8,30 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE -class ArrayData : public CollectionData { +class ArrayImpl : public CollectionImpl { public: - VariantData* addElement(ResourceManager* resources); + ArrayImpl() {} - static VariantData* addElement(ArrayData* array, ResourceManager* resources) { - if (!array) - return nullptr; - return array->addElement(resources); - } + ArrayImpl(CollectionData* data, ResourceManager* resources) + : CollectionImpl(data, resources) {} + + VariantData* addElement(); template - bool addValue(const T& value, ResourceManager* resources); + bool addValue(const T& value); - template - static bool addValue(ArrayData* array, const T& value, - ResourceManager* resources) { - if (!array) - return false; - return array->addValue(value, resources); - } + VariantData* getOrAddElement(size_t index); - VariantData* getOrAddElement(size_t index, ResourceManager* resources); + VariantData* getElement(size_t index) const; - VariantData* getElement(size_t index, const ResourceManager* resources) const; + void removeElement(size_t index); - static VariantData* getElement(const ArrayData* array, size_t index, - const ResourceManager* resources) { - if (!array) - return nullptr; - return array->getElement(index, resources); - } - - void removeElement(size_t index, ResourceManager* resources); - - static void removeElement(ArrayData* array, size_t index, - ResourceManager* resources) { - if (!array) - return; - array->removeElement(index, resources); - } - - void remove(iterator it, ResourceManager* resources) { - CollectionData::removeOne(it, resources); - } - - static void remove(ArrayData* array, iterator it, - ResourceManager* resources) { - if (array) - return array->remove(it, resources); + void remove(iterator it) { + CollectionImpl::removeOne(it); } private: - iterator at(size_t index, const ResourceManager* resources) const; + iterator at(size_t index) const; }; ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Array/ArrayImpl.hpp b/src/ArduinoJson/Array/ArrayImpl.hpp index 8db18959..3fdcb554 100644 --- a/src/ArduinoJson/Array/ArrayImpl.hpp +++ b/src/ArduinoJson/Array/ArrayImpl.hpp @@ -10,36 +10,37 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE -inline ArrayData::iterator ArrayData::at( - size_t index, const ResourceManager* resources) const { - auto it = createIterator(resources); +inline ArrayImpl::iterator ArrayImpl::at(size_t index) const { + auto it = createIterator(); while (!it.done() && index) { - it.next(resources); + it.next(resources_); --index; } return it; } -inline VariantData* ArrayData::addElement(ResourceManager* resources) { - auto slot = resources->allocVariant(); +inline VariantData* ArrayImpl::addElement() { + if (!data_) + return nullptr; + ARDUINOJSON_ASSERT(resources_ != nullptr); + auto slot = resources_->allocVariant(); if (!slot) return nullptr; - CollectionData::appendOne(slot, resources); + CollectionImpl::appendOne(slot); return slot.ptr(); } -inline VariantData* ArrayData::getOrAddElement(size_t index, - ResourceManager* resources) { - auto it = createIterator(resources); +inline VariantData* ArrayImpl::getOrAddElement(size_t index) { + auto it = createIterator(); while (!it.done() && index > 0) { - it.next(resources); + it.next(resources_); index--; } if (it.done()) index++; VariantData* element = it.data(); while (index > 0) { - element = addElement(resources); + element = addElement(); if (!element) return nullptr; index--; @@ -47,27 +48,28 @@ inline VariantData* ArrayData::getOrAddElement(size_t index, return element; } -inline VariantData* ArrayData::getElement( - size_t index, const ResourceManager* resources) const { - return at(index, resources).data(); +inline VariantData* ArrayImpl::getElement(size_t index) const { + return at(index).data(); } -inline void ArrayData::removeElement(size_t index, ResourceManager* resources) { - remove(at(index, resources), resources); +inline void ArrayImpl::removeElement(size_t index) { + remove(at(index)); } template -inline bool ArrayData::addValue(const T& value, ResourceManager* resources) { - ARDUINOJSON_ASSERT(resources != nullptr); - auto slot = resources->allocVariant(); +inline bool ArrayImpl::addValue(const T& value) { + if (!data_) + return false; + ARDUINOJSON_ASSERT(resources_ != nullptr); + auto slot = resources_->allocVariant(); if (!slot) return false; - JsonVariant variant(slot.ptr(), resources); + JsonVariant variant(slot.ptr(), resources_); if (!variant.set(value)) { - resources->freeVariant(slot); + resources_->freeVariant(slot); return false; } - CollectionData::appendOne(slot, resources); + CollectionImpl::appendOne(slot); return true; } diff --git a/src/ArduinoJson/Array/ElementProxy.hpp b/src/ArduinoJson/Array/ElementProxy.hpp index ec2ea547..05f69d95 100644 --- a/src/ArduinoJson/Array/ElementProxy.hpp +++ b/src/ArduinoJson/Array/ElementProxy.hpp @@ -55,9 +55,9 @@ class ElementProxy : public VariantRefBase>, } FORCE_INLINE VariantData* getData() const { - return VariantData::getElement( - VariantAttorney::getData(upstream_), index_, - VariantAttorney::getResourceManager(upstream_)); + auto data = VariantAttorney::getData(upstream_); + auto resources = VariantAttorney::getResourceManager(upstream_); + return VariantData::asArray(data, resources).getElement(index_); } VariantData* getOrCreateData() const { diff --git a/src/ArduinoJson/Array/JsonArray.hpp b/src/ArduinoJson/Array/JsonArray.hpp index c84eac55..a2d2c1ae 100644 --- a/src/ArduinoJson/Array/JsonArray.hpp +++ b/src/ArduinoJson/Array/JsonArray.hpp @@ -20,24 +20,25 @@ class JsonArray : public detail::VariantOperators { using iterator = JsonArrayIterator; // Constructs an unbound reference. - JsonArray() : data_(0), resources_(0) {} + JsonArray() {} // INTERNAL USE ONLY JsonArray(detail::VariantData* data, detail::ResourceManager* resources) - : data_(data), resources_(resources) {} + : impl_(detail::VariantData::asArray(data, resources)) {} + + // INTERNAL USE ONLY + JsonArray(const detail::ArrayImpl& impl) : impl_(impl) {} // Returns a JsonVariant pointing to the array. // https://arduinojson.org/v7/api/jsonvariant/ operator JsonVariant() { - void* data = data_; // prevent warning cast-align - return JsonVariant(reinterpret_cast(data), - resources_); + return JsonVariant(getData(), getResourceManager()); } // Returns a read-only reference to the array. // https://arduinojson.org/v7/api/jsonarrayconst/ operator JsonArrayConst() const { - return JsonArrayConst(getData(), resources_); + return JsonArrayConst(getData(), getResourceManager()); } // Appends a new (empty) element to the array. @@ -55,15 +56,14 @@ class JsonArray : public detail::VariantOperators { template ::value, int> = 0> JsonVariant add() const { - return JsonVariant(detail::VariantData::addElement(data_, resources_), - resources_); + return JsonVariant(impl_.addElement(), impl_.getResourceManager()); } // Appends a value to the array. // https://arduinojson.org/v7/api/jsonarray/add/ template bool add(const T& value) const { - return detail::VariantData::addValue(data_, value, resources_); + return impl_.addValue(value); } // Appends a value to the array. @@ -71,16 +71,13 @@ class JsonArray : public detail::VariantOperators { template ::value, int> = 0> bool add(T* value) const { - return detail::VariantData::addValue(data_, value, resources_); + return impl_.addValue(value); } // Returns an iterator to the first element of the array. // https://arduinojson.org/v7/api/jsonarray/begin/ iterator begin() const { - auto array = detail::VariantData::asArray(data_); - if (!array) - return iterator(); - return iterator(array->createIterator(resources_), resources_); + return iterator(impl_.createIterator(), impl_.getResourceManager()); } // Returns an iterator following the last element of the array. @@ -92,7 +89,7 @@ class JsonArray : public detail::VariantOperators { // Copies an array. // https://arduinojson.org/v7/api/jsonarray/set/ bool set(JsonArrayConst src) const { - if (!data_) + if (isNull()) return false; clear(); @@ -107,14 +104,13 @@ class JsonArray : public detail::VariantOperators { // Removes the element at the specified iterator. // https://arduinojson.org/v7/api/jsonarray/remove/ void remove(iterator it) const { - detail::ArrayData::remove(detail::VariantData::asArray(data_), it.iterator_, - resources_); + impl_.remove(it.iterator_); } // Removes the element at the specified index. // https://arduinojson.org/v7/api/jsonarray/remove/ void remove(size_t index) const { - detail::VariantData::removeElement(data_, index, resources_); + impl_.removeElement(index); } // Removes the element at the specified index. @@ -129,7 +125,7 @@ class JsonArray : public detail::VariantOperators { // Removes all the elements of the array. // https://arduinojson.org/v7/api/jsonarray/clear/ void clear() const { - detail::ArrayData::clear(detail::VariantData::asArray(data_), resources_); + impl_.clear(); } // Gets or sets the element at the specified index. @@ -152,13 +148,13 @@ class JsonArray : public detail::VariantOperators { } operator JsonVariantConst() const { - return JsonVariantConst(data_, resources_); + return JsonVariantConst(getData(), getResourceManager()); } // Returns true if the reference is unbound. // https://arduinojson.org/v7/api/jsonarray/isnull/ bool isNull() const { - return !data_ || !data_->isArray(); + return impl_.isNull(); } // Returns true if the reference is bound. @@ -170,13 +166,13 @@ class JsonArray : public detail::VariantOperators { // Returns the depth (nesting level) of the array. // https://arduinojson.org/v7/api/jsonarray/nesting/ size_t nesting() const { - return detail::VariantData::nesting(data_, resources_); + return impl_.nesting(); } // Returns the number of elements in the array. // https://arduinojson.org/v7/api/jsonarray/size/ size_t size() const { - return data_ ? data_->size(resources_) : 0; + return impl_.size(); } // DEPRECATED: use add() instead @@ -203,19 +199,18 @@ class JsonArray : public detail::VariantOperators { private: detail::ResourceManager* getResourceManager() const { - return resources_; + return impl_.getResourceManager(); } detail::VariantData* getData() const { - return data_; + return impl_.getData(); } detail::VariantData* getOrCreateData() const { - return data_; + return impl_.getData(); } - detail::VariantData* data_; - detail::ResourceManager* resources_; + mutable detail::ArrayImpl impl_; }; ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/src/ArduinoJson/Array/JsonArrayConst.hpp b/src/ArduinoJson/Array/JsonArrayConst.hpp index c33d8979..918f5f95 100644 --- a/src/ArduinoJson/Array/JsonArrayConst.hpp +++ b/src/ArduinoJson/Array/JsonArrayConst.hpp @@ -24,10 +24,7 @@ class JsonArrayConst : public detail::VariantOperators { // Returns an iterator to the first element of the array. // https://arduinojson.org/v7/api/jsonarrayconst/begin/ iterator begin() const { - auto array = detail::VariantData::asArray(data_); - if (!array) - return iterator(); - return iterator(array->createIterator(resources_), resources_); + return iterator(impl_.createIterator(), impl_.getResourceManager()); } // Returns an iterator to the element following the last element of the array. @@ -37,21 +34,22 @@ class JsonArrayConst : public detail::VariantOperators { } // Creates an unbound reference. - JsonArrayConst() : data_(0), resources_(0) {} + JsonArrayConst() {} // INTERNAL USE ONLY - JsonArrayConst(const detail::VariantData* data, - const detail::ResourceManager* resources) - : data_(data), resources_(resources) {} + JsonArrayConst(detail::VariantData* data, detail::ResourceManager* resources) + : impl_(detail::VariantData::asArray(data, resources)) {} + + // INTERNAL USE ONLY + JsonArrayConst(const detail::ArrayImpl& impl) : impl_(impl) {} // Returns the element at the specified index. // https://arduinojson.org/v7/api/jsonarrayconst/subscript/ template ::value, int> = 0> JsonVariantConst operator[](T index) const { - return JsonVariantConst( - detail::VariantData::getElement(data_, size_t(index), resources_), - resources_); + return JsonVariantConst(impl_.getElement(size_t(index)), + impl_.getResourceManager()); } // Returns the element at the specified index. @@ -66,13 +64,13 @@ class JsonArrayConst : public detail::VariantOperators { } operator JsonVariantConst() const { - return JsonVariantConst(getData(), resources_); + return JsonVariantConst(impl_.getData(), impl_.getResourceManager()); } // Returns true if the reference is unbound. // https://arduinojson.org/v7/api/jsonarrayconst/isnull/ bool isNull() const { - return !data_ || !data_->isArray(); + return impl_.isNull(); } // Returns true if the reference is bound. @@ -84,13 +82,13 @@ class JsonArrayConst : public detail::VariantOperators { // Returns the depth (nesting level) of the array. // https://arduinojson.org/v7/api/jsonarrayconst/nesting/ size_t nesting() const { - return detail::VariantData::nesting(getData(), resources_); + return impl_.nesting(); } // Returns the number of elements in the array. // https://arduinojson.org/v7/api/jsonarrayconst/size/ size_t size() const { - return data_ ? data_->size(resources_) : 0; + return impl_.size(); } // DEPRECATED: always returns zero @@ -101,11 +99,10 @@ class JsonArrayConst : public detail::VariantOperators { private: const detail::VariantData* getData() const { - return data_; + return impl_.getData(); } - const detail::VariantData* data_; - const detail::ResourceManager* resources_; + detail::ArrayImpl impl_; }; // Compares the content of two arrays. diff --git a/src/ArduinoJson/Array/JsonArrayIterator.hpp b/src/ArduinoJson/Array/JsonArrayIterator.hpp index 39ca45e7..1cc92647 100644 --- a/src/ArduinoJson/Array/JsonArrayIterator.hpp +++ b/src/ArduinoJson/Array/JsonArrayIterator.hpp @@ -30,7 +30,7 @@ class JsonArrayIterator { public: JsonArrayIterator() {} - explicit JsonArrayIterator(detail::ArrayData::iterator iterator, + explicit JsonArrayIterator(detail::ArrayImpl::iterator iterator, detail::ResourceManager* resources) : iterator_(iterator), resources_(resources) {} @@ -55,7 +55,7 @@ class JsonArrayIterator { } private: - detail::ArrayData::iterator iterator_; + detail::ArrayImpl::iterator iterator_; detail::ResourceManager* resources_; }; @@ -64,8 +64,8 @@ class JsonArrayConstIterator { public: JsonArrayConstIterator() {} - explicit JsonArrayConstIterator(detail::ArrayData::iterator iterator, - const detail::ResourceManager* resources) + explicit JsonArrayConstIterator(detail::ArrayImpl::iterator iterator, + detail::ResourceManager* resources) : iterator_(iterator), resources_(resources) {} JsonVariantConst operator*() const { @@ -89,8 +89,8 @@ class JsonArrayConstIterator { } private: - detail::ArrayData::iterator iterator_; - const detail::ResourceManager* resources_; + mutable detail::ArrayImpl::iterator iterator_; + mutable detail::ResourceManager* resources_; }; ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/src/ArduinoJson/Collection/CollectionData.hpp b/src/ArduinoJson/Collection/CollectionData.hpp index 937c10c9..690b48b0 100644 --- a/src/ArduinoJson/Collection/CollectionData.hpp +++ b/src/ArduinoJson/Collection/CollectionData.hpp @@ -16,7 +16,7 @@ class VariantData; class ResourceManager; class CollectionIterator { - friend class CollectionData; + friend class CollectionImpl; public: CollectionIterator() : slot_(nullptr), currentId_(NULL_SLOT) {} @@ -51,11 +51,11 @@ class CollectionIterator { } VariantData* data() { - return reinterpret_cast(slot_); + return slot_; } const VariantData* data() const { - return reinterpret_cast(slot_); + return slot_; } private: @@ -65,58 +65,68 @@ class CollectionIterator { SlotId currentId_, nextId_; }; -class CollectionData { - SlotId head_ = NULL_SLOT; - SlotId tail_ = NULL_SLOT; +struct CollectionData { + SlotId head = NULL_SLOT; + SlotId tail = NULL_SLOT; - public: // Placement new static void* operator new(size_t, void* p) noexcept { return p; } static void operator delete(void*, void*) noexcept {} +}; +class CollectionImpl { + protected: + CollectionData* data_; + ResourceManager* resources_; + + public: using iterator = CollectionIterator; - iterator createIterator(const ResourceManager* resources) const; + CollectionImpl() : data_(nullptr), resources_(nullptr) {} - size_t size(const ResourceManager*) const; - size_t nesting(const ResourceManager*) const; + CollectionImpl(CollectionData* data, ResourceManager* resources) + : data_(data), resources_(resources) {} - void clear(ResourceManager* resources); - - static void clear(CollectionData* collection, ResourceManager* resources) { - if (!collection) - return; - collection->clear(resources); + explicit operator bool() const { + return data_ != nullptr; } + bool isNull() const { + return data_ == nullptr; + } + + VariantData* getData() const { + void* data = data_; // prevent warning cast-align + return reinterpret_cast(data); + } + + ResourceManager* getResourceManager() const { + return resources_; + } + + iterator createIterator() const; + + size_t size() const; + size_t nesting() const; + + void clear(); + SlotId head() const { - return head_; + return data_->head; } protected: - void appendOne(Slot slot, const ResourceManager* resources); - void appendPair(Slot key, Slot value, - const ResourceManager* resources); + void appendOne(Slot slot); + void appendPair(Slot key, Slot value); - void removeOne(iterator it, ResourceManager* resources); - void removePair(iterator it, ResourceManager* resources); + void removeOne(iterator it); + void removePair(iterator it); private: - Slot getPreviousSlot(VariantData*, const ResourceManager*) const; + Slot getPreviousSlot(VariantData*) const; }; -inline const VariantData* collectionToVariant( - const CollectionData* collection) { - const void* data = collection; // prevent warning cast-align - return reinterpret_cast(data); -} - -inline VariantData* collectionToVariant(CollectionData* collection) { - void* data = collection; // prevent warning cast-align - return reinterpret_cast(data); -} - ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Collection/CollectionImpl.hpp b/src/ArduinoJson/Collection/CollectionImpl.hpp index 559c0a5e..ef8247e1 100644 --- a/src/ArduinoJson/Collection/CollectionImpl.hpp +++ b/src/ArduinoJson/Collection/CollectionImpl.hpp @@ -25,57 +25,64 @@ inline void CollectionIterator::next(const ResourceManager* resources) { nextId_ = slot_->next(); } -inline CollectionData::iterator CollectionData::createIterator( - const ResourceManager* resources) const { - return iterator(resources->getVariant(head_), head_); +inline CollectionImpl::iterator CollectionImpl::createIterator() const { + if (!data_) + return iterator(); + return iterator(resources_->getVariant(data_->head), data_->head); } -inline void CollectionData::appendOne(Slot slot, - const ResourceManager* resources) { - if (tail_ != NULL_SLOT) { - auto tail = resources->getVariant(tail_); +inline void CollectionImpl::appendOne(Slot slot) { + ARDUINOJSON_ASSERT(data_ != nullptr); + ARDUINOJSON_ASSERT(resources_ != nullptr); + + if (data_->tail != NULL_SLOT) { + auto tail = resources_->getVariant(data_->tail); tail->setNext(slot.id()); - tail_ = slot.id(); + data_->tail = slot.id(); } else { - head_ = slot.id(); - tail_ = slot.id(); + data_->head = slot.id(); + data_->tail = slot.id(); } } -inline void CollectionData::appendPair(Slot key, - Slot value, - const ResourceManager* resources) { +inline void CollectionImpl::appendPair(Slot key, + Slot value) { + ARDUINOJSON_ASSERT(data_ != nullptr); + ARDUINOJSON_ASSERT(resources_ != nullptr); + key->setNext(value.id()); - if (tail_ != NULL_SLOT) { - auto tail = resources->getVariant(tail_); + if (data_->tail != NULL_SLOT) { + auto tail = resources_->getVariant(data_->tail); tail->setNext(key.id()); - tail_ = value.id(); + data_->tail = value.id(); } else { - head_ = key.id(); - tail_ = value.id(); + data_->head = key.id(); + data_->tail = value.id(); } } -inline void CollectionData::clear(ResourceManager* resources) { - auto next = head_; +inline void CollectionImpl::clear() { + if (!data_) + return; + auto next = data_->head; while (next != NULL_SLOT) { auto currId = next; - auto slot = resources->getVariant(next); + auto slot = resources_->getVariant(next); next = slot->next(); - resources->freeVariant({slot, currId}); + resources_->freeVariant({slot, currId}); } - head_ = NULL_SLOT; - tail_ = NULL_SLOT; + data_->head = NULL_SLOT; + data_->tail = NULL_SLOT; } -inline Slot CollectionData::getPreviousSlot( - VariantData* target, const ResourceManager* resources) const { +inline Slot CollectionImpl::getPreviousSlot( + VariantData* target) const { auto prev = Slot(); - auto currentId = head_; + auto currentId = data_->head; while (currentId != NULL_SLOT) { - auto currentSlot = resources->getVariant(currentId); + auto currentSlot = resources_->getVariant(currentId); if (currentSlot == target) break; prev = Slot(currentSlot, currentId); @@ -84,52 +91,53 @@ inline Slot CollectionData::getPreviousSlot( return prev; } -inline void CollectionData::removeOne(iterator it, ResourceManager* resources) { +inline void CollectionImpl::removeOne(iterator it) { if (it.done()) return; auto curr = it.slot_; - auto prev = getPreviousSlot(curr, resources); + auto prev = getPreviousSlot(curr); auto next = curr->next(); if (prev) prev->setNext(next); else - head_ = next; + data_->head = next; if (next == NULL_SLOT) - tail_ = prev.id(); - resources->freeVariant({it.slot_, it.currentId_}); + data_->tail = prev.id(); + resources_->freeVariant({it.slot_, it.currentId_}); } -inline void CollectionData::removePair(ObjectData::iterator it, - ResourceManager* resources) { +inline void CollectionImpl::removePair(ObjectImpl::iterator it) { if (it.done()) return; auto keySlot = it.slot_; auto valueId = it.nextId_; - auto valueSlot = resources->getVariant(valueId); + auto valueSlot = resources_->getVariant(valueId); // remove value slot keySlot->setNext(valueSlot->next()); - resources->freeVariant({valueSlot, valueId}); + resources_->freeVariant({valueSlot, valueId}); // remove key slot - removeOne(it, resources); + removeOne(it); } -inline size_t CollectionData::nesting(const ResourceManager* resources) const { +inline size_t CollectionImpl::nesting() const { + if (!data_) + return 0; size_t maxChildNesting = 0; - for (auto it = createIterator(resources); !it.done(); it.next(resources)) { - size_t childNesting = it->nesting(resources); + for (auto it = createIterator(); !it.done(); it.next(resources_)) { + size_t childNesting = it->nesting(resources_); if (childNesting > maxChildNesting) maxChildNesting = childNesting; } return maxChildNesting + 1; } -inline size_t CollectionData::size(const ResourceManager* resources) const { +inline size_t CollectionImpl::size() const { size_t count = 0; - for (auto it = createIterator(resources); !it.done(); it.next(resources)) + for (auto it = createIterator(); !it.done(); it.next(resources_)) count++; return count; } diff --git a/src/ArduinoJson/Document/JsonDocument.hpp b/src/ArduinoJson/Document/JsonDocument.hpp index 63902c4a..9980c424 100644 --- a/src/ArduinoJson/Document/JsonDocument.hpp +++ b/src/ArduinoJson/Document/JsonDocument.hpp @@ -415,8 +415,8 @@ class JsonDocument : public detail::VariantOperators { return &data_; } - detail::ResourceManager resources_; - detail::VariantData data_; + mutable detail::ResourceManager resources_; + mutable detail::VariantData data_; }; inline void convertToJson(const JsonDocument& src, JsonVariant dst) { diff --git a/src/ArduinoJson/Json/JsonDeserializer.hpp b/src/ArduinoJson/Json/JsonDeserializer.hpp index 288a22ca..b70bf4ce 100644 --- a/src/ArduinoJson/Json/JsonDeserializer.hpp +++ b/src/ArduinoJson/Json/JsonDeserializer.hpp @@ -71,13 +71,14 @@ class JsonDeserializer { switch (current()) { case '[': if (filter.allowArray()) - return parseArray(variant.toArray(), filter, nestingLimit); + return parseArray(variant.toArray(resources_), filter, nestingLimit); else return skipArray(nestingLimit); case '{': if (filter.allowObject()) - return parseObject(variant.toObject(), filter, nestingLimit); + return parseObject(variant.toObject(resources_), filter, + nestingLimit); else return skipObject(nestingLimit); @@ -146,7 +147,7 @@ class JsonDeserializer { template DeserializationError::Code parseArray( - ArrayData& array, TFilter filter, + ArrayImpl array, TFilter filter, DeserializationOption::NestingLimit nestingLimit) { DeserializationError::Code err; @@ -172,7 +173,7 @@ class JsonDeserializer { for (;;) { if (elementFilter.allow()) { // Allocate slot in array - VariantData* value = array.addElement(resources_); + VariantData* value = array.addElement(); if (!value) return DeserializationError::NoMemory; @@ -232,7 +233,7 @@ class JsonDeserializer { template DeserializationError::Code parseObject( - ObjectData& object, TFilter filter, + ObjectImpl object, TFilter filter, DeserializationOption::NestingLimit nestingLimit) { DeserializationError::Code err; @@ -273,9 +274,9 @@ class JsonDeserializer { TFilter memberFilter = filter[key]; if (memberFilter.allow()) { - auto member = object.getMember(adaptString(key), resources_); + auto member = object.getMember(adaptString(key)); if (!member) { - auto keyVariant = object.addPair(&member, resources_); + auto keyVariant = object.addPair(&member); if (!keyVariant) return DeserializationError::NoMemory; diff --git a/src/ArduinoJson/Json/JsonSerializer.hpp b/src/ArduinoJson/Json/JsonSerializer.hpp index e95bfc77..e1bb6da8 100644 --- a/src/ArduinoJson/Json/JsonSerializer.hpp +++ b/src/ArduinoJson/Json/JsonSerializer.hpp @@ -16,10 +16,10 @@ class JsonSerializer : public VariantDataVisitor { public: static const bool producesText = true; - JsonSerializer(TWriter writer, const ResourceManager* resources) + JsonSerializer(TWriter writer, ResourceManager* resources) : formatter_(writer), resources_(resources) {} - size_t visit(const ArrayData& array) { + size_t visit(const ArrayImpl& array) { write('['); auto slotId = array.head(); @@ -39,7 +39,7 @@ class JsonSerializer : public VariantDataVisitor { return bytesWritten(); } - size_t visit(const ObjectData& object) { + size_t visit(const ObjectImpl& object) { write('{'); auto slotId = object.head(); @@ -120,7 +120,7 @@ class JsonSerializer : public VariantDataVisitor { TextFormatter formatter_; protected: - const ResourceManager* resources_; + ResourceManager* resources_; }; ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Json/PrettyJsonSerializer.hpp b/src/ArduinoJson/Json/PrettyJsonSerializer.hpp index 2cfd1774..29c01f8c 100644 --- a/src/ArduinoJson/Json/PrettyJsonSerializer.hpp +++ b/src/ArduinoJson/Json/PrettyJsonSerializer.hpp @@ -16,11 +16,11 @@ class PrettyJsonSerializer : public JsonSerializer { using base = JsonSerializer; public: - PrettyJsonSerializer(TWriter writer, const ResourceManager* resources) + PrettyJsonSerializer(TWriter writer, ResourceManager* resources) : base(writer, resources), nesting_(0) {} - size_t visit(const ArrayData& array) { - auto it = array.createIterator(base::resources_); + size_t visit(const ArrayImpl& array) { + auto it = array.createIterator(); if (!it.done()) { base::write("[\r\n"); nesting_++; @@ -40,8 +40,8 @@ class PrettyJsonSerializer : public JsonSerializer { return this->bytesWritten(); } - size_t visit(const ObjectData& object) { - auto it = object.createIterator(base::resources_); + size_t visit(const ObjectImpl& object) { + auto it = object.createIterator(); if (!it.done()) { base::write("{\r\n"); nesting_++; diff --git a/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp b/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp index 904da179..ac1e4056 100644 --- a/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp @@ -349,12 +349,10 @@ class MsgPackDeserializer { bool allowArray = filter.allowArray(); - ArrayData* array; + ArrayImpl array; if (allowArray) { ARDUINOJSON_ASSERT(variant != 0); - array = &variant->toArray(); - } else { - array = 0; + array = variant->toArray(resources_); } TFilter elementFilter = filter[0U]; @@ -363,8 +361,7 @@ class MsgPackDeserializer { VariantData* value; if (elementFilter.allow()) { - ARDUINOJSON_ASSERT(array != 0); - value = array->addElement(resources_); + value = array.addElement(); if (!value) return DeserializationError::NoMemory; } else { @@ -388,12 +385,10 @@ class MsgPackDeserializer { if (nestingLimit.reached()) return DeserializationError::TooDeep; - ObjectData* object; + ObjectImpl object; if (filter.allowObject()) { ARDUINOJSON_ASSERT(variant != 0); - object = &variant->toObject(); - } else { - object = 0; + object = variant->toObject(resources_); } for (; n; --n) { @@ -406,9 +401,7 @@ class MsgPackDeserializer { VariantData* member = 0; if (memberFilter.allow()) { - ARDUINOJSON_ASSERT(object != 0); - - auto keyVariant = object->addPair(&member, resources_); + auto keyVariant = object.addPair(&member); if (!keyVariant) return DeserializationError::NoMemory; diff --git a/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp b/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp index 43f4cd26..56e725fe 100644 --- a/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp @@ -19,7 +19,7 @@ class MsgPackSerializer : public VariantDataVisitor { public: static const bool producesText = false; - MsgPackSerializer(TWriter writer, const ResourceManager* resources) + MsgPackSerializer(TWriter writer, ResourceManager* resources) : writer_(writer), resources_(resources) {} template @@ -47,8 +47,8 @@ class MsgPackSerializer : public VariantDataVisitor { return bytesWritten(); } - size_t visit(const ArrayData& array) { - size_t n = array.size(resources_); + size_t visit(const ArrayImpl& array) { + size_t n = array.size(); if (n < 0x10) { writeByte(uint8_t(0x90 + n)); } else if (n < 0x10000) { @@ -69,8 +69,8 @@ class MsgPackSerializer : public VariantDataVisitor { return bytesWritten(); } - size_t visit(const ObjectData& object) { - size_t n = object.size(resources_); + size_t visit(const ObjectImpl& object) { + size_t n = object.size(); if (n < 0x10) { writeByte(uint8_t(0x80 + n)); } else if (n < 0x10000) { @@ -209,7 +209,7 @@ class MsgPackSerializer : public VariantDataVisitor { } CountingDecorator writer_; - const ResourceManager* resources_; + ResourceManager* resources_; }; ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Object/JsonObject.hpp b/src/ArduinoJson/Object/JsonObject.hpp index eff61e34..87c49299 100644 --- a/src/ArduinoJson/Object/JsonObject.hpp +++ b/src/ArduinoJson/Object/JsonObject.hpp @@ -20,30 +20,31 @@ class JsonObject : public detail::VariantOperators { using iterator = JsonObjectIterator; // Creates an unbound reference. - JsonObject() : data_(0), resources_(0) {} + JsonObject() {} + + // INTERNAL USE ONLY + JsonObject(const detail::ObjectImpl& impl) : impl_(impl) {} // INTERNAL USE ONLY JsonObject(detail::VariantData* data, detail::ResourceManager* resource) - : data_(data), resources_(resource) {} + : impl_(detail::VariantData::asObject(data, resource)) {} operator JsonVariant() const { - void* data = data_; // prevent warning cast-align - return JsonVariant(reinterpret_cast(data), - resources_); + return JsonVariant(getData(), getResourceManager()); } operator JsonObjectConst() const { - return JsonObjectConst(data_, resources_); + return JsonObjectConst(getData(), getResourceManager()); } operator JsonVariantConst() const { - return JsonVariantConst(data_, resources_); + return JsonVariantConst(getData(), getResourceManager()); } // Returns true if the reference is unbound. // https://arduinojson.org/v7/api/jsonobject/isnull/ bool isNull() const { - return !data_ || !data_->isObject(); + return impl_.isNull(); } // Returns true if the reference is bound. @@ -55,22 +56,19 @@ class JsonObject : public detail::VariantOperators { // Returns the depth (nesting level) of the object. // https://arduinojson.org/v7/api/jsonobject/nesting/ size_t nesting() const { - return detail::VariantData::nesting(data_, resources_); + return impl_.nesting(); } // Returns the number of members in the object. // https://arduinojson.org/v7/api/jsonobject/size/ size_t size() const { - return data_ ? data_->size(resources_) : 0; + return impl_.size(); } // Returns an iterator to the first key-value pair of the object. // https://arduinojson.org/v7/api/jsonobject/begin/ iterator begin() const { - auto obj = detail::VariantData::asObject(data_); - if (!obj) - return iterator(); - return iterator(obj->createIterator(resources_), resources_); + return iterator(impl_.createIterator(), impl_.getResourceManager()); } // Returns an iterator following the last key-value pair of the object. @@ -82,13 +80,13 @@ class JsonObject : public detail::VariantOperators { // Removes all the members of the object. // https://arduinojson.org/v7/api/jsonobject/clear/ void clear() const { - detail::ObjectData::clear(detail::VariantData::asObject(data_), resources_); + impl_.clear(); } // Copies an object. // https://arduinojson.org/v7/api/jsonobject/set/ bool set(JsonObjectConst src) { - if (!data_ || !src.data_) + if (isNull() || src.isNull()) return false; clear(); @@ -132,8 +130,7 @@ class JsonObject : public detail::VariantOperators { // Removes the member at the specified iterator. // https://arduinojson.org/v7/api/jsonobject/remove/ FORCE_INLINE void remove(iterator it) const { - detail::ObjectData::remove(detail::VariantData::asObject(data_), - it.iterator_, resources_); + impl_.remove(it.iterator_); } // Removes the member with the specified key. @@ -141,8 +138,7 @@ class JsonObject : public detail::VariantOperators { template ::value, int> = 0> void remove(const TString& key) const { - detail::VariantData::removeMember(data_, detail::adaptString(key), - resources_); + impl_.removeMember(detail::adaptString(key)); } // Removes the member with the specified key. @@ -158,8 +154,7 @@ class JsonObject : public detail::VariantOperators { // https://arduinojson.org/v7/api/jsonobject/remove/ template FORCE_INLINE void remove(TChar* key) const { - detail::VariantData::removeMember(data_, detail::adaptString(key), - resources_); + impl_.removeMember(detail::adaptString(key)); } // DEPRECATED: use obj[key].is() instead @@ -168,8 +163,7 @@ class JsonObject : public detail::VariantOperators { detail::enable_if_t::value, int> = 0> ARDUINOJSON_DEPRECATED("use obj[key].is() instead") bool containsKey(const TString& key) const { - return detail::VariantData::getMember(data_, detail::adaptString(key), - resources_) != 0; + return impl_.getMember(detail::adaptString(key)) != 0; } // DEPRECATED: use obj["key"].is() instead @@ -180,8 +174,7 @@ class JsonObject : public detail::VariantOperators { int> = 0> ARDUINOJSON_DEPRECATED("use obj[\"key\"].is() instead") bool containsKey(TChar* key) const { - return detail::VariantData::getMember(data_, detail::adaptString(key), - resources_) != 0; + return impl_.getMember(detail::adaptString(key)) != 0; } // DEPRECATED: use obj[key].is() instead @@ -229,19 +222,18 @@ class JsonObject : public detail::VariantOperators { private: detail::ResourceManager* getResourceManager() const { - return resources_; + return impl_.getResourceManager(); } detail::VariantData* getData() const { - return data_; + return impl_.getData(); } detail::VariantData* getOrCreateData() const { - return data_; + return impl_.getData(); } - detail::VariantData* data_; - detail::ResourceManager* resources_; + mutable detail::ObjectImpl impl_; }; ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/src/ArduinoJson/Object/JsonObjectConst.hpp b/src/ArduinoJson/Object/JsonObjectConst.hpp index 099249d8..264f729f 100644 --- a/src/ArduinoJson/Object/JsonObjectConst.hpp +++ b/src/ArduinoJson/Object/JsonObjectConst.hpp @@ -19,21 +19,23 @@ class JsonObjectConst : public detail::VariantOperators { using iterator = JsonObjectConstIterator; // Creates an unbound reference. - JsonObjectConst() : data_(0), resources_(0) {} + JsonObjectConst() {} // INTERNAL USE ONLY - JsonObjectConst(const detail::VariantData* data, - const detail::ResourceManager* resources) - : data_(data), resources_(resources) {} + JsonObjectConst(detail::VariantData* data, detail::ResourceManager* resources) + : impl_(detail::VariantData::asObject(data, resources)) {} + + // INTERNAL USE ONLY + JsonObjectConst(const detail::ObjectImpl& impl) : impl_(impl) {} operator JsonVariantConst() const { - return JsonVariantConst(getData(), resources_); + return JsonVariantConst(impl_.getData(), impl_.getResourceManager()); } // Returns true if the reference is unbound. // https://arduinojson.org/v7/api/jsonobjectconst/isnull/ bool isNull() const { - return !data_ || !data_->isObject(); + return impl_.isNull(); } // Returns true if the reference is bound. @@ -45,22 +47,19 @@ class JsonObjectConst : public detail::VariantOperators { // Returns the depth (nesting level) of the object. // https://arduinojson.org/v7/api/jsonobjectconst/nesting/ size_t nesting() const { - return detail::VariantData::nesting(getData(), resources_); + return impl_.nesting(); } // Returns the number of members in the object. // https://arduinojson.org/v7/api/jsonobjectconst/size/ size_t size() const { - return data_ ? data_->size(resources_) : 0; + return impl_.size(); } // Returns an iterator to the first key-value pair of the object. // https://arduinojson.org/v7/api/jsonobjectconst/begin/ iterator begin() const { - auto obj = detail::VariantData::asObject(data_); - if (!obj) - return iterator(); - return iterator(obj->createIterator(resources_), resources_); + return iterator(impl_.createIterator(), impl_.getResourceManager()); } // Returns an iterator following the last key-value pair of the object. @@ -75,8 +74,7 @@ class JsonObjectConst : public detail::VariantOperators { detail::enable_if_t::value, int> = 0> ARDUINOJSON_DEPRECATED("use obj[key].is() instead") bool containsKey(const TString& key) const { - return detail::VariantData::getMember(data_, detail::adaptString(key), - resources_) != 0; + return impl_.getMember(detail::adaptString(key)) != 0; } // DEPRECATED: use obj["key"].is() instead @@ -84,8 +82,7 @@ class JsonObjectConst : public detail::VariantOperators { template ARDUINOJSON_DEPRECATED("use obj[\"key\"].is() instead") bool containsKey(TChar* key) const { - return detail::VariantData::getMember(data_, detail::adaptString(key), - resources_) != 0; + return impl_.getMember(detail::adaptString(key)) != 0; } // DEPRECATED: use obj[key].is() instead @@ -102,9 +99,8 @@ class JsonObjectConst : public detail::VariantOperators { template ::value, int> = 0> JsonVariantConst operator[](const TString& key) const { - return JsonVariantConst(detail::VariantData::getMember( - data_, detail::adaptString(key), resources_), - resources_); + return JsonVariantConst(impl_.getMember(detail::adaptString(key)), + impl_.getResourceManager()); } // Gets the member with specified key. @@ -114,9 +110,8 @@ class JsonObjectConst : public detail::VariantOperators { !detail::is_const::value, int> = 0> JsonVariantConst operator[](TChar* key) const { - return JsonVariantConst(detail::VariantData::getMember( - data_, detail::adaptString(key), resources_), - resources_); + return JsonVariantConst(impl_.getMember(detail::adaptString(key)), + impl_.getResourceManager()); } // Gets the member with specified key. @@ -138,11 +133,10 @@ class JsonObjectConst : public detail::VariantOperators { private: const detail::VariantData* getData() const { - return data_; + return impl_.getData(); } - const detail::VariantData* data_; - const detail::ResourceManager* resources_; + detail::ObjectImpl impl_; }; inline bool operator==(JsonObjectConst lhs, JsonObjectConst rhs) { diff --git a/src/ArduinoJson/Object/JsonObjectIterator.hpp b/src/ArduinoJson/Object/JsonObjectIterator.hpp index 90637f58..bf29930d 100644 --- a/src/ArduinoJson/Object/JsonObjectIterator.hpp +++ b/src/ArduinoJson/Object/JsonObjectIterator.hpp @@ -14,7 +14,7 @@ class JsonObjectIterator { public: JsonObjectIterator() {} - explicit JsonObjectIterator(detail::ObjectData::iterator iterator, + explicit JsonObjectIterator(detail::ObjectImpl::iterator iterator, detail::ResourceManager* resources) : iterator_(iterator), resources_(resources) {} @@ -40,7 +40,7 @@ class JsonObjectIterator { } private: - detail::ObjectData::iterator iterator_; + detail::ObjectImpl::iterator iterator_; detail::ResourceManager* resources_; }; @@ -50,8 +50,8 @@ class JsonObjectConstIterator { public: JsonObjectConstIterator() {} - explicit JsonObjectConstIterator(detail::ObjectData::iterator iterator, - const detail::ResourceManager* resources) + explicit JsonObjectConstIterator(detail::ObjectImpl::iterator iterator, + detail::ResourceManager* resources) : iterator_(iterator), resources_(resources) {} JsonPairConst operator*() const { @@ -76,8 +76,8 @@ class JsonObjectConstIterator { } private: - detail::ObjectData::iterator iterator_; - const detail::ResourceManager* resources_; + detail::ObjectImpl::iterator iterator_; + detail::ResourceManager* resources_; }; ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/src/ArduinoJson/Object/JsonPair.hpp b/src/ArduinoJson/Object/JsonPair.hpp index 9b2d4072..afbeba1f 100644 --- a/src/ArduinoJson/Object/JsonPair.hpp +++ b/src/ArduinoJson/Object/JsonPair.hpp @@ -15,7 +15,7 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE class JsonPair { public: // INTERNAL USE ONLY - JsonPair(detail::ObjectData::iterator iterator, + JsonPair(detail::ObjectImpl::iterator iterator, detail::ResourceManager* resources) { if (!iterator.done()) { key_ = iterator->asString(resources); @@ -43,8 +43,8 @@ class JsonPair { // https://arduinojson.org/v7/api/jsonobjectconst/begin_end/ class JsonPairConst { public: - JsonPairConst(detail::ObjectData::iterator iterator, - const detail::ResourceManager* resources) { + JsonPairConst(detail::ObjectImpl::iterator iterator, + detail::ResourceManager* resources) { if (!iterator.done()) { key_ = iterator->asString(resources); iterator.next(resources); diff --git a/src/ArduinoJson/Object/ObjectData.hpp b/src/ArduinoJson/Object/ObjectData.hpp index 9b989628..3d3cd946 100644 --- a/src/ArduinoJson/Object/ObjectData.hpp +++ b/src/ArduinoJson/Object/ObjectData.hpp @@ -8,63 +8,38 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE -class ObjectData : public CollectionData { +class ObjectImpl : public CollectionImpl { public: - template - VariantData* addMember(TAdaptedString key, ResourceManager* resources); + ObjectImpl() {} - VariantData* addPair(VariantData** value, ResourceManager* resources); + ObjectImpl(CollectionData* data, ResourceManager* resources) + : CollectionImpl(data, resources) {} template - VariantData* getOrAddMember(TAdaptedString key, ResourceManager* resources); + VariantData* addMember(TAdaptedString key); + + VariantData* addPair(VariantData** value); template - VariantData* getMember(TAdaptedString key, - const ResourceManager* resources) const; + VariantData* getOrAddMember(TAdaptedString key); template - static VariantData* getMember(const ObjectData* object, TAdaptedString key, - const ResourceManager* resources) { - if (!object) - return nullptr; - return object->getMember(key, resources); + VariantData* getMember(TAdaptedString key) const; + + template + void removeMember(TAdaptedString key); + + void remove(iterator it) { + CollectionImpl::removePair(it); } - template - void removeMember(TAdaptedString key, ResourceManager* resources); - - template - static void removeMember(ObjectData* obj, TAdaptedString key, - ResourceManager* resources) { - if (!obj) - return; - obj->removeMember(key, resources); - } - - void remove(iterator it, ResourceManager* resources) { - CollectionData::removePair(it, resources); - } - - static void remove(ObjectData* obj, ObjectData::iterator it, - ResourceManager* resources) { - if (!obj) - return; - obj->remove(it, resources); - } - - size_t size(const ResourceManager* resources) const { - return CollectionData::size(resources) / 2; - } - - static size_t size(const ObjectData* obj, const ResourceManager* resources) { - if (!obj) - return 0; - return obj->size(resources); + size_t size() const { + return CollectionImpl::size() / 2; } private: template - iterator findKey(TAdaptedString key, const ResourceManager* resources) const; + iterator findKey(TAdaptedString key) const; }; ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Object/ObjectImpl.hpp b/src/ArduinoJson/Object/ObjectImpl.hpp index ab9727c3..8ef3ddda 100644 --- a/src/ArduinoJson/Object/ObjectImpl.hpp +++ b/src/ArduinoJson/Object/ObjectImpl.hpp @@ -11,32 +11,29 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template -inline VariantData* ObjectData::getMember( - TAdaptedString key, const ResourceManager* resources) const { - auto it = findKey(key, resources); +inline VariantData* ObjectImpl::getMember(TAdaptedString key) const { + auto it = findKey(key); if (it.done()) return nullptr; - it.next(resources); + it.next(resources_); return it.data(); } template -VariantData* ObjectData::getOrAddMember(TAdaptedString key, - ResourceManager* resources) { - auto data = getMember(key, resources); +VariantData* ObjectImpl::getOrAddMember(TAdaptedString key) { + auto data = getMember(key); if (data) return data; - return addMember(key, resources); + return addMember(key); } template -inline ObjectData::iterator ObjectData::findKey( - TAdaptedString key, const ResourceManager* resources) const { +inline ObjectImpl::iterator ObjectImpl::findKey(TAdaptedString key) const { if (key.isNull()) return iterator(); bool isKey = true; - for (auto it = createIterator(resources); !it.done(); it.next(resources)) { - if (isKey && stringEquals(key, adaptString(it->asString(resources)))) + for (auto it = createIterator(); !it.done(); it.next(resources_)) { + if (isKey && stringEquals(key, adaptString(it->asString(resources_)))) return it; isKey = !isKey; } @@ -44,42 +41,47 @@ inline ObjectData::iterator ObjectData::findKey( } template -inline void ObjectData::removeMember(TAdaptedString key, - ResourceManager* resources) { - remove(findKey(key, resources), resources); +inline void ObjectImpl::removeMember(TAdaptedString key) { + remove(findKey(key)); } template -inline VariantData* ObjectData::addMember(TAdaptedString key, - ResourceManager* resources) { - auto keySlot = resources->allocVariant(); +inline VariantData* ObjectImpl::addMember(TAdaptedString key) { + if (!data_) + return nullptr; + ARDUINOJSON_ASSERT(resources_ != nullptr); + + auto keySlot = resources_->allocVariant(); if (!keySlot) return nullptr; - auto valueSlot = resources->allocVariant(); + auto valueSlot = resources_->allocVariant(); if (!valueSlot) return nullptr; - if (!keySlot->setString(key, resources)) + if (!keySlot->setString(key, resources_)) return nullptr; - CollectionData::appendPair(keySlot, valueSlot, resources); + CollectionImpl::appendPair(keySlot, valueSlot); return valueSlot.ptr(); } -inline VariantData* ObjectData::addPair(VariantData** value, - ResourceManager* resources) { - auto keySlot = resources->allocVariant(); +inline VariantData* ObjectImpl::addPair(VariantData** value) { + if (!data_) + return nullptr; + ARDUINOJSON_ASSERT(resources_ != nullptr); + + auto keySlot = resources_->allocVariant(); if (!keySlot) return nullptr; - auto valueSlot = resources->allocVariant(); + auto valueSlot = resources_->allocVariant(); if (!valueSlot) return nullptr; *value = valueSlot.ptr(); - CollectionData::appendPair(keySlot, valueSlot, resources); + CollectionImpl::appendPair(keySlot, valueSlot); return keySlot.ptr(); } diff --git a/src/ArduinoJson/Variant/JsonVariantConst.hpp b/src/ArduinoJson/Variant/JsonVariantConst.hpp index 4c960597..8d80d69f 100644 --- a/src/ArduinoJson/Variant/JsonVariantConst.hpp +++ b/src/ArduinoJson/Variant/JsonVariantConst.hpp @@ -38,8 +38,8 @@ class JsonVariantConst : public detail::VariantTag, JsonVariantConst() : data_(nullptr), resources_(nullptr) {} // INTERNAL USE ONLY - explicit JsonVariantConst(const detail::VariantData* data, - const detail::ResourceManager* resources) + explicit JsonVariantConst(detail::VariantData* data, + detail::ResourceManager* resources) : data_(data), resources_(resources) {} // Returns true if the value is null or the reference is unbound. @@ -181,17 +181,17 @@ class JsonVariantConst : public detail::VariantTag, } protected: - const detail::VariantData* getData() const { + detail::VariantData* getData() const { return data_; } - const detail::ResourceManager* getResourceManager() const { + detail::ResourceManager* getResourceManager() const { return resources_; } private: - const detail::VariantData* data_; - const detail::ResourceManager* resources_; + mutable detail::VariantData* data_; + mutable detail::ResourceManager* resources_; }; ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/src/ArduinoJson/Variant/JsonVariantVisitor.hpp b/src/ArduinoJson/Variant/JsonVariantVisitor.hpp index 5bf0fdf3..c9169f71 100644 --- a/src/ArduinoJson/Variant/JsonVariantVisitor.hpp +++ b/src/ArduinoJson/Variant/JsonVariantVisitor.hpp @@ -26,17 +26,14 @@ class VisitorAdapter { public: using result_type = typename TVisitor::result_type; - VisitorAdapter(TVisitor& visitor, const ResourceManager* resources) - : visitor_(&visitor), resources_(resources) {} + VisitorAdapter(TVisitor& visitor) : visitor_(&visitor) {} - result_type visit(const ArrayData& value) { - return visitor_->visit( - JsonArrayConst(collectionToVariant(&value), resources_)); + result_type visit(const ArrayImpl& array) { + return visitor_->visit(JsonArrayConst(array)); } - result_type visit(const ObjectData& value) { - return visitor_->visit( - JsonObjectConst(collectionToVariant(&value), resources_)); + result_type visit(const ObjectImpl& object) { + return visitor_->visit(JsonObjectConst(object)); } template @@ -46,7 +43,6 @@ class VisitorAdapter { private: TVisitor* visitor_; - const ResourceManager* resources_; }; template @@ -56,7 +52,7 @@ typename TVisitor::result_type accept(JsonVariantConst variant, if (!data) return visit.visit(nullptr); auto resources = VariantAttorney::getResourceManager(variant); - VisitorAdapter adapter(visit, resources); + VisitorAdapter adapter(visit); return data->accept(adapter, resources); } diff --git a/src/ArduinoJson/Variant/VariantContent.hpp b/src/ArduinoJson/Variant/VariantContent.hpp index 7b2994fb..d62ad6c3 100644 --- a/src/ArduinoJson/Variant/VariantContent.hpp +++ b/src/ArduinoJson/Variant/VariantContent.hpp @@ -57,8 +57,6 @@ union VariantContent { uint32_t asUint32; int32_t asInt32; SlotId asSlotId; - ArrayData asArray; - ObjectData asObject; CollectionData asCollection; struct StringNode* asOwnedString; char asTinyString[tinyStringMaxLength + 1]; diff --git a/src/ArduinoJson/Variant/VariantData.hpp b/src/ArduinoJson/Variant/VariantData.hpp index c38b3b1e..f2cb06b4 100644 --- a/src/ArduinoJson/Variant/VariantData.hpp +++ b/src/ArduinoJson/Variant/VariantData.hpp @@ -51,8 +51,8 @@ class VariantData { } template - typename TVisitor::result_type accept( - TVisitor& visit, const ResourceManager* resources) const { + typename TVisitor::result_type accept(TVisitor& visit, + ResourceManager* resources) { #if ARDUINOJSON_USE_8_BYTE_POOL auto eightByteValue = getEightByte(resources); #else @@ -68,10 +68,10 @@ class VariantData { #endif case VariantType::Array: - return visit.visit(content_.asArray); + return visit.visit(asArray(resources)); case VariantType::Object: - return visit.visit(content_.asObject); + return visit.visit(asObject(resources)); case VariantType::TinyString: return visit.visit(JsonString(content_.asTinyString)); @@ -110,8 +110,8 @@ class VariantData { } template - static typename TVisitor::result_type accept(const VariantData* var, - const ResourceManager* resources, + static typename TVisitor::result_type accept(VariantData* var, + ResourceManager* resources, TVisitor& visit) { if (var != 0) return var->accept(visit, resources); @@ -120,8 +120,8 @@ class VariantData { } VariantData* addElement(ResourceManager* resources) { - auto array = isNull() ? &toArray() : asArray(); - return detail::ArrayData::addElement(array, resources); + auto array = isNull() ? toArray(resources) : asArray(resources); + return array.addElement(); } static VariantData* addElement(VariantData* var, ResourceManager* resources) { @@ -132,8 +132,8 @@ class VariantData { template bool addValue(const T& value, ResourceManager* resources) { - auto array = isNull() ? &toArray() : asArray(); - return detail::ArrayData::addValue(array, value, resources); + auto array = isNull() ? toArray(resources) : asArray(resources); + return array.addValue(value); } template @@ -174,28 +174,19 @@ class VariantData { } } - ArrayData* asArray() { - return isArray() ? &content_.asArray : 0; + ArrayImpl asArray(ResourceManager* resources) { + return ArrayImpl(isArray() ? &content_.asCollection : nullptr, resources); } - const ArrayData* asArray() const { - return const_cast(this)->asArray(); + static ArrayImpl asArray(VariantData* var, ResourceManager* resources) { + return ArrayImpl( + var && var->isArray() ? &var->content_.asCollection : nullptr, + resources); } - static ArrayData* asArray(VariantData* var) { - return var ? var->asArray() : 0; - } - - static const ArrayData* asArray(const VariantData* var) { - return var ? var->asArray() : 0; - } - - CollectionData* asCollection() { - return isCollection() ? &content_.asCollection : 0; - } - - const CollectionData* asCollection() const { - return const_cast(this)->asCollection(); + CollectionImpl asCollection(ResourceManager* resources) { + return CollectionImpl(isCollection() ? &content_.asCollection : nullptr, + resources); } template @@ -288,20 +279,14 @@ class VariantData { return parseNumber(str); } - ObjectData* asObject() { - return isObject() ? &content_.asObject : 0; + ObjectImpl asObject(ResourceManager* resources) { + return ObjectImpl(isObject() ? &content_.asCollection : nullptr, resources); } - const ObjectData* asObject() const { - return const_cast(this)->asObject(); - } - - static ObjectData* asObject(VariantData* var) { - return var ? var->asObject() : 0; - } - - static const ObjectData* asObject(const VariantData* var) { - return var ? var->asObject() : 0; + static ObjectImpl asObject(VariantData* var, ResourceManager* resources) { + return ObjectImpl( + var && var->isObject() ? &var->content_.asCollection : nullptr, + resources); } JsonString asRawString() const { @@ -334,45 +319,41 @@ class VariantData { const EightByteValue* getEightByte(const ResourceManager* resources) const; #endif - VariantData* getElement(size_t index, - const ResourceManager* resources) const { - return ArrayData::getElement(asArray(), index, resources); + VariantData* getElement(size_t index, ResourceManager* resources) { + return asArray(resources).getElement(index); } - static VariantData* getElement(const VariantData* var, size_t index, - const ResourceManager* resources) { - return var != 0 ? var->getElement(index, resources) : 0; + static VariantData* getElement(VariantData* var, size_t index, + ResourceManager* resources) { + if (!var) + return nullptr; + return var->asArray(resources).getElement(index); } template - VariantData* getMember(TAdaptedString key, - const ResourceManager* resources) const { - return ObjectData::getMember(asObject(), key, resources); + VariantData* getMember(TAdaptedString key, ResourceManager* resources) { + return asObject(resources).getMember(key); } template - static VariantData* getMember(const VariantData* var, TAdaptedString key, - const ResourceManager* resources) { + static VariantData* getMember(VariantData* var, TAdaptedString key, + ResourceManager* resources) { if (!var) return 0; return var->getMember(key, resources); } VariantData* getOrAddElement(size_t index, ResourceManager* resources) { - auto array = isNull() ? &toArray() : asArray(); - if (!array) - return nullptr; - return array->getOrAddElement(index, resources); + auto array = isNull() ? toArray(resources) : asArray(resources); + return array.getOrAddElement(index); } template VariantData* getOrAddMember(TAdaptedString key, ResourceManager* resources) { if (key.isNull()) return nullptr; - auto obj = isNull() ? &toObject() : asObject(); - if (!obj) - return nullptr; - return obj->getOrAddMember(key, resources); + auto obj = isNull() ? toObject(resources) : asObject(resources); + return obj.getOrAddMember(key); } bool isArray() const { @@ -438,23 +419,18 @@ class VariantData { type_ == VariantType::TinyString; } - size_t nesting(const ResourceManager* resources) const { - auto collection = asCollection(); - if (collection) - return collection->nesting(resources); - else - return 0; + size_t nesting(ResourceManager* resources) { + return asCollection(resources).nesting(); } - static size_t nesting(const VariantData* var, - const ResourceManager* resources) { + static size_t nesting(VariantData* var, ResourceManager* resources) { if (!var) return 0; return var->nesting(resources); } void removeElement(size_t index, ResourceManager* resources) { - ArrayData::removeElement(asArray(), index, resources); + asArray(resources).removeElement(index); } static void removeElement(VariantData* var, size_t index, @@ -466,7 +442,7 @@ class VariantData { template void removeMember(TAdaptedString key, ResourceManager* resources) { - ObjectData::removeMember(asObject(), key, resources); + asObject(resources).removeMember(key); } template @@ -563,48 +539,44 @@ class VariantData { content_.asOwnedString = s; } - size_t size(const ResourceManager* resources) const { + size_t size(ResourceManager* resources) { if (isObject()) - return content_.asObject.size(resources); + return asObject(resources).size(); if (isArray()) - return content_.asArray.size(resources); + return asArray(resources).size(); return 0; } - static size_t size(const VariantData* var, const ResourceManager* resources) { + static size_t size(VariantData* var, ResourceManager* resources) { return var != 0 ? var->size(resources) : 0; } - ArrayData& toArray() { + ArrayImpl toArray(ResourceManager* resources) { ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first type_ = VariantType::Array; - new (&content_.asArray) ArrayData(); - return content_.asArray; + return ArrayImpl(new (&content_.asCollection) CollectionData(), resources); } - static VariantData* toArray(VariantData* var, ResourceManager* resources) { + static ArrayImpl toArray(VariantData* var, ResourceManager* resources) { if (!var) - return 0; + return ArrayImpl(nullptr, resources); var->clear(resources); - var->toArray(); - return var; + return var->toArray(resources); } - ObjectData& toObject() { + ObjectImpl toObject(ResourceManager* resources) { ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first type_ = VariantType::Object; - new (&content_.asObject) ObjectData(); - return content_.asObject; + return ObjectImpl(new (&content_.asCollection) CollectionData(), resources); } - static VariantData* toObject(VariantData* var, ResourceManager* resources) { + static ObjectImpl toObject(VariantData* var, ResourceManager* resources) { if (!var) - return 0; + return ObjectImpl(); var->clear(resources); - var->toObject(); - return var; + return var->toObject(resources); } VariantType type() const { diff --git a/src/ArduinoJson/Variant/VariantImpl.hpp b/src/ArduinoJson/Variant/VariantImpl.hpp index 7004cd00..1ad89b9d 100644 --- a/src/ArduinoJson/Variant/VariantImpl.hpp +++ b/src/ArduinoJson/Variant/VariantImpl.hpp @@ -66,9 +66,7 @@ inline void VariantData::clear(ResourceManager* resources) { resources->freeEightByte(content_.asSlotId); #endif - auto collection = asCollection(); - if (collection) - collection->clear(resources); + asCollection(resources).clear(); type_ = VariantType::Null; } diff --git a/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp b/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp index da1b1e6b..1d4bc2a5 100644 --- a/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp +++ b/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp @@ -151,16 +151,14 @@ template template ::value, int>> inline JsonArray VariantRefBase::to() const { return JsonArray( - VariantData::toArray(getOrCreateData(), getResourceManager()), - getResourceManager()); + VariantData::toArray(getOrCreateData(), getResourceManager())); } template template ::value, int>> JsonObject VariantRefBase::to() const { return JsonObject( - VariantData::toObject(getOrCreateData(), getResourceManager()), - getResourceManager()); + VariantData::toObject(getOrCreateData(), getResourceManager())); } template