diff --git a/extras/tests/JsonObject/remove.cpp b/extras/tests/JsonObject/remove.cpp index eda17992..fbd3e76a 100644 --- a/extras/tests/JsonObject/remove.cpp +++ b/extras/tests/JsonObject/remove.cpp @@ -51,7 +51,8 @@ TEST_CASE("JsonObject::remove()") { } SECTION("Remove last") { - it += 2; + ++it; + ++it; obj.remove(it); serializeJson(obj, result); REQUIRE("{\"a\":0,\"b\":1}" == result); diff --git a/src/ArduinoJson/Array/ArrayData.hpp b/src/ArduinoJson/Array/ArrayData.hpp index 62b84ea8..acec3e4e 100644 --- a/src/ArduinoJson/Array/ArrayData.hpp +++ b/src/ArduinoJson/Array/ArrayData.hpp @@ -59,7 +59,7 @@ class ArrayData : public CollectionData { } private: - VariantSlot* getSlot(size_t index) 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 0f9990f6..31f2e139 100644 --- a/src/ArduinoJson/Array/ArrayImpl.hpp +++ b/src/ArduinoJson/Array/ArrayImpl.hpp @@ -9,6 +9,15 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE +inline ArrayData::iterator ArrayData::at(size_t index) const { + auto it = begin(); + while (it && index) { + ++it; + --index; + } + return it; +} + inline VariantData* ArrayData::addElement(ResourceManager* resources) { auto slot = resources->allocVariant(); if (!slot) @@ -21,63 +30,57 @@ inline bool ArrayData::copyFrom(const ArrayData& src, ResourceManager* resources) { clear(resources); - for (VariantSlot* s = src.head(); s; s = s->next()) { + for (auto it = src.begin(); it; ++it) { auto var = addElement(resources); if (!var) return false; - if (!var->copyFrom(s->data(), resources)) + if (!var->copyFrom(*it, resources)) return false; } return true; } inline bool ArrayData::equals(const ArrayData& other) const { - auto a = head(); - auto b = other.head(); + auto a = begin(); + auto b = other.begin(); for (;;) { if (!a && !b) // both ended return true; if (!a || !b) // one ended return false; - if (compare(a->data(), b->data()) != COMPARE_RESULT_EQUAL) + if (compare(a.data(), b.data()) != COMPARE_RESULT_EQUAL) return false; - a = a->next(); - b = b->next(); + ++a; + ++b; } } inline VariantData* ArrayData::getOrAddElement(size_t index, ResourceManager* resources) { - VariantSlot* slot = head(); - while (slot && index > 0) { - slot = slot->next(); + auto it = begin(); + while (it && index > 0) { + ++it; index--; } - if (!slot) + if (!it) index++; + VariantData* element = it.data(); while (index > 0) { - slot = resources->allocVariant(); - if (!slot) + element = addElement(resources); + if (!element) return nullptr; - addSlot(slot); index--; } - return slot->data(); + return element; } inline VariantData* ArrayData::getElement(size_t index) const { - return slotData(getSlot(index)); -} - -inline VariantSlot* ArrayData::getSlot(size_t index) const { - if (!head()) - return 0; - return head()->next(index); + return at(index).data(); } inline void ArrayData::removeElement(size_t index, ResourceManager* resources) { - removeSlot(getSlot(index), resources); + remove(at(index), resources); } ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Array/JsonArray.hpp b/src/ArduinoJson/Array/JsonArray.hpp index d1675fba..46f705cd 100644 --- a/src/ArduinoJson/Array/JsonArray.hpp +++ b/src/ArduinoJson/Array/JsonArray.hpp @@ -68,7 +68,7 @@ class JsonArray : public detail::VariantOperators { FORCE_INLINE iterator begin() const { if (!data_) return iterator(); - return iterator(resources_, data_->head()); + return iterator(data_->begin(), resources_); } // Returns an iterator following the last element of the array. @@ -92,7 +92,7 @@ class JsonArray : public detail::VariantOperators { // ⚠️ Doesn't release the memory associated with the removed element. // https://arduinojson.org/v6/api/jsonarray/remove/ FORCE_INLINE void remove(iterator it) const { - detail::ArrayData::removeSlot(data_, it.slot_, resources_); + detail::ArrayData::remove(data_, it.iterator_, resources_); } // Removes the element at the specified index. diff --git a/src/ArduinoJson/Array/JsonArrayConst.hpp b/src/ArduinoJson/Array/JsonArrayConst.hpp index 063dc04b..0a0f72e1 100644 --- a/src/ArduinoJson/Array/JsonArrayConst.hpp +++ b/src/ArduinoJson/Array/JsonArrayConst.hpp @@ -26,7 +26,7 @@ class JsonArrayConst : public detail::VariantOperators { FORCE_INLINE iterator begin() const { if (!data_) return iterator(); - return iterator(data_->head()); + return iterator(data_->begin()); } // Returns an iterator to the element following the last element of the array. diff --git a/src/ArduinoJson/Array/JsonArrayIterator.hpp b/src/ArduinoJson/Array/JsonArrayIterator.hpp index d4c37175..74d5bed7 100644 --- a/src/ArduinoJson/Array/JsonArrayIterator.hpp +++ b/src/ArduinoJson/Array/JsonArrayIterator.hpp @@ -30,76 +30,66 @@ class JsonArrayIterator { friend class JsonArray; public: - JsonArrayIterator() : slot_(0) {} - explicit JsonArrayIterator(detail::ResourceManager* resources, - detail::VariantSlot* slot) - : resources_(resources), slot_(slot) {} + JsonArrayIterator() {} + explicit JsonArrayIterator(detail::ArrayData::iterator iterator, + detail::ResourceManager* resources) + : iterator_(iterator), resources_(resources) {} - JsonVariant operator*() const { - return JsonVariant(slot_->data(), resources_); + JsonVariant operator*() { + return JsonVariant(iterator_.data(), resources_); } Ptr operator->() { return operator*(); } bool operator==(const JsonArrayIterator& other) const { - return slot_ == other.slot_; + return iterator_ == other.iterator_; } bool operator!=(const JsonArrayIterator& other) const { - return slot_ != other.slot_; + return iterator_ != other.iterator_; } JsonArrayIterator& operator++() { - slot_ = slot_->next(); - return *this; - } - - JsonArrayIterator& operator+=(size_t distance) { - slot_ = slot_->next(distance); + ++iterator_; return *this; } private: + detail::ArrayData::iterator iterator_; detail::ResourceManager* resources_; - detail::VariantSlot* slot_; }; class JsonArrayConstIterator { friend class JsonArray; public: - JsonArrayConstIterator() : slot_(0) {} - explicit JsonArrayConstIterator(const detail::VariantSlot* slot) - : slot_(slot) {} + JsonArrayConstIterator() {} + explicit JsonArrayConstIterator(detail::ArrayData::iterator iterator) + : iterator_(iterator) {} JsonVariantConst operator*() const { - return JsonVariantConst(slot_->data()); + return JsonVariantConst(iterator_.data()); } Ptr operator->() { return operator*(); } bool operator==(const JsonArrayConstIterator& other) const { - return slot_ == other.slot_; + return iterator_ == other.iterator_; } bool operator!=(const JsonArrayConstIterator& other) const { - return slot_ != other.slot_; + return iterator_ != other.iterator_; } JsonArrayConstIterator& operator++() { - slot_ = slot_->next(); - return *this; - } - - JsonArrayConstIterator& operator+=(size_t distance) { - slot_ = slot_->next(distance); + ++iterator_; return *this; } private: - const detail::VariantSlot* slot_; + detail::ArrayData::iterator iterator_; }; ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/src/ArduinoJson/Collection/CollectionData.hpp b/src/ArduinoJson/Collection/CollectionData.hpp index f87ec5e4..6aa71a06 100644 --- a/src/ArduinoJson/Collection/CollectionData.hpp +++ b/src/ArduinoJson/Collection/CollectionData.hpp @@ -14,6 +14,58 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE class VariantData; class VariantSlot; +class CollectionIterator { + friend class CollectionData; + + public: + CollectionIterator() : slot_(nullptr) {} + + CollectionIterator& operator++(); + + operator bool() const { + return slot_ != nullptr; + } + + bool operator==(const CollectionIterator& other) const { + return slot_ == other.slot_; + } + + bool operator!=(const CollectionIterator& other) const { + return slot_ != other.slot_; + } + + VariantData* operator->() { + ARDUINOJSON_ASSERT(slot_ != nullptr); + return data(); + } + + VariantData& operator*() { + ARDUINOJSON_ASSERT(slot_ != nullptr); + return *data(); + } + + const VariantData& operator*() const { + ARDUINOJSON_ASSERT(slot_ != nullptr); + return *data(); + } + + const char* key() const; + bool ownsKey() const; + + VariantData* data() { + return reinterpret_cast(slot_); + } + + const VariantData* data() const { + return reinterpret_cast(slot_); + } + + private: + CollectionIterator(VariantSlot* slot) : slot_(slot) {} + + VariantSlot* slot_; +}; + class CollectionData { VariantSlot* head_ = 0; VariantSlot* tail_ = 0; @@ -26,8 +78,19 @@ class CollectionData { static void operator delete(void*, void*) noexcept {} + using iterator = CollectionIterator; + + iterator begin() const { + return iterator(head_); + } + + iterator end() const { + return iterator(nullptr); + } + size_t memoryUsage() const; size_t size() const; + size_t nesting() const; void clear(ResourceManager* resources); @@ -37,21 +100,16 @@ class CollectionData { collection->clear(resources); } - void removeSlot(VariantSlot* slot, ResourceManager* resources); - - static void removeSlot(CollectionData* collection, VariantSlot* slot, - ResourceManager* resources) { - if (!collection) - return; - collection->removeSlot(slot, resources); - } - - VariantSlot* head() const { - return head_; - } - void movePointers(ptrdiff_t variantDistance); + void remove(iterator it, ResourceManager* resources); + + static void remove(CollectionData* collection, iterator it, + ResourceManager* resources) { + if (collection) + return collection->remove(it, resources); + } + protected: void addSlot(VariantSlot*); diff --git a/src/ArduinoJson/Collection/CollectionImpl.hpp b/src/ArduinoJson/Collection/CollectionImpl.hpp index d1285d70..19d923d3 100644 --- a/src/ArduinoJson/Collection/CollectionImpl.hpp +++ b/src/ArduinoJson/Collection/CollectionImpl.hpp @@ -11,6 +11,22 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE +inline const char* CollectionIterator::key() const { + ARDUINOJSON_ASSERT(slot_ != nullptr); + return slot_->key(); +} + +inline bool CollectionIterator::ownsKey() const { + ARDUINOJSON_ASSERT(slot_ != nullptr); + return slot_->ownsKey(); +} + +inline CollectionIterator& CollectionIterator::operator++() { + ARDUINOJSON_ASSERT(slot_ != nullptr); + slot_ = slot_->next(); + return *this; +} + inline void CollectionData::addSlot(VariantSlot* slot) { ARDUINOJSON_ASSERT(slot != nullptr); @@ -41,19 +57,19 @@ inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const { return 0; } -inline void CollectionData::removeSlot(VariantSlot* slot, - ResourceManager* resources) { - if (!slot) +inline void CollectionData::remove(iterator it, ResourceManager* resources) { + if (!it) return; - VariantSlot* prev = getPreviousSlot(slot); - VariantSlot* next = slot->next(); + auto curr = it.slot_; + auto prev = getPreviousSlot(curr); + auto next = curr->next(); if (prev) prev->setNext(next); else head_ = next; if (!next) tail_ = prev; - slotRelease(slot, resources); + slotRelease(curr, resources); } inline size_t CollectionData::memoryUsage() const { @@ -66,6 +82,16 @@ inline size_t CollectionData::memoryUsage() const { return total; } +inline size_t CollectionData::nesting() const { + size_t maxChildNesting = 0; + for (const VariantSlot* s = head_; s; s = s->next()) { + size_t childNesting = s->data()->nesting(); + if (childNesting > maxChildNesting) + maxChildNesting = childNesting; + } + return maxChildNesting + 1; +} + inline size_t CollectionData::size() const { return slotSize(head_); } diff --git a/src/ArduinoJson/Json/JsonSerializer.hpp b/src/ArduinoJson/Json/JsonSerializer.hpp index d75863d0..d1dc121b 100644 --- a/src/ArduinoJson/Json/JsonSerializer.hpp +++ b/src/ArduinoJson/Json/JsonSerializer.hpp @@ -21,13 +21,13 @@ class JsonSerializer : public Visitor { FORCE_INLINE size_t visitArray(const ArrayData& array) { write('['); - const VariantSlot* slot = array.head(); + auto it = array.begin(); - while (slot != 0) { - slot->data()->accept(*this); + while (it) { + it->accept(*this); - slot = slot->next(); - if (slot == 0) + ++it; + if (!it) break; write(','); @@ -40,15 +40,15 @@ class JsonSerializer : public Visitor { size_t visitObject(const ObjectData& object) { write('{'); - const VariantSlot* slot = object.head(); + auto it = object.begin(); - while (slot != 0) { - formatter_.writeString(slot->key()); + while (it) { + formatter_.writeString(it.key()); write(':'); - slot->data()->accept(*this); + it->accept(*this); - slot = slot->next(); - if (slot == 0) + ++it; + if (!it) break; write(','); diff --git a/src/ArduinoJson/Json/PrettyJsonSerializer.hpp b/src/ArduinoJson/Json/PrettyJsonSerializer.hpp index 13c69b38..52e9581d 100644 --- a/src/ArduinoJson/Json/PrettyJsonSerializer.hpp +++ b/src/ArduinoJson/Json/PrettyJsonSerializer.hpp @@ -19,16 +19,16 @@ class PrettyJsonSerializer : public JsonSerializer { PrettyJsonSerializer(TWriter writer) : base(writer), nesting_(0) {} size_t visitArray(const ArrayData& array) { - const VariantSlot* slot = array.head(); - if (slot) { + auto it = array.begin(); + if (it) { base::write("[\r\n"); nesting_++; - while (slot != 0) { + while (it) { indent(); - slot->data()->accept(*this); + it->accept(*this); - slot = slot->next(); - base::write(slot ? ",\r\n" : "\r\n"); + ++it; + base::write(it ? ",\r\n" : "\r\n"); } nesting_--; indent(); @@ -40,18 +40,18 @@ class PrettyJsonSerializer : public JsonSerializer { } size_t visitObject(const ObjectData& object) { - const VariantSlot* slot = object.head(); - if (slot) { + auto it = object.begin(); + if (it) { base::write("{\r\n"); nesting_++; - while (slot != 0) { + while (it) { indent(); - base::visitString(slot->key()); + base::visitString(it.key()); base::write(": "); - slot->data()->accept(*this); + it->accept(*this); - slot = slot->next(); - base::write(slot ? ",\r\n" : "\r\n"); + ++it; + base::write(it ? ",\r\n" : "\r\n"); } nesting_--; indent(); diff --git a/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp b/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp index ec4373b9..0b727ee8 100644 --- a/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp @@ -55,8 +55,8 @@ class MsgPackSerializer : public Visitor { writeByte(0xDD); writeInteger(uint32_t(n)); } - for (const VariantSlot* slot = array.head(); slot; slot = slot->next()) { - slot->data()->accept(*this); + for (auto it = array.begin(); it; ++it) { + it->accept(*this); } return bytesWritten(); } @@ -72,9 +72,9 @@ class MsgPackSerializer : public Visitor { writeByte(0xDF); writeInteger(uint32_t(n)); } - for (const VariantSlot* slot = object.head(); slot; slot = slot->next()) { - visitString(slot->key()); - slot->data()->accept(*this); + for (auto it = object.begin(); it; ++it) { + visitString(it.key()); + it->accept(*this); } return bytesWritten(); } diff --git a/src/ArduinoJson/Object/JsonObject.hpp b/src/ArduinoJson/Object/JsonObject.hpp index aa8ab6bf..06050197 100644 --- a/src/ArduinoJson/Object/JsonObject.hpp +++ b/src/ArduinoJson/Object/JsonObject.hpp @@ -76,7 +76,7 @@ class JsonObject : public detail::VariantOperators { FORCE_INLINE iterator begin() const { if (!data_) return iterator(); - return iterator(resources_, data_->head()); + return iterator(data_->begin(), resources_); } // Returns an iterator following the last key-value pair of the object. @@ -127,7 +127,7 @@ class JsonObject : public detail::VariantOperators { // ⚠️ Doesn't release the memory associated with the removed member. // https://arduinojson.org/v6/api/jsonobject/remove/ FORCE_INLINE void remove(iterator it) const { - detail::ObjectData::removeSlot(data_, it.slot_, resources_); + detail::ObjectData::remove(data_, it.iterator_, resources_); } // Removes the member with the specified key. diff --git a/src/ArduinoJson/Object/JsonObjectConst.hpp b/src/ArduinoJson/Object/JsonObjectConst.hpp index fb4254c1..9bc974f3 100644 --- a/src/ArduinoJson/Object/JsonObjectConst.hpp +++ b/src/ArduinoJson/Object/JsonObjectConst.hpp @@ -63,7 +63,7 @@ class JsonObjectConst : public detail::VariantOperators { FORCE_INLINE iterator begin() const { if (!data_) return iterator(); - return iterator(data_->head()); + return iterator(data_->begin()); } // Returns an iterator following the last key-value pair of the object. diff --git a/src/ArduinoJson/Object/JsonObjectIterator.hpp b/src/ArduinoJson/Object/JsonObjectIterator.hpp index f98965c3..4bbd9ef8 100644 --- a/src/ArduinoJson/Object/JsonObjectIterator.hpp +++ b/src/ArduinoJson/Object/JsonObjectIterator.hpp @@ -13,78 +13,68 @@ class JsonObjectIterator { friend class JsonObject; public: - JsonObjectIterator() : slot_(0) {} + JsonObjectIterator() {} - explicit JsonObjectIterator(detail::ResourceManager* resources, - detail::VariantSlot* slot) - : resources_(resources), slot_(slot) {} + explicit JsonObjectIterator(detail::ObjectData::iterator iterator, + detail::ResourceManager* resources) + : iterator_(iterator), resources_(resources) {} JsonPair operator*() const { - return JsonPair(resources_, slot_); + return JsonPair(iterator_, resources_); } Ptr operator->() { return operator*(); } bool operator==(const JsonObjectIterator& other) const { - return slot_ == other.slot_; + return iterator_ == other.iterator_; } bool operator!=(const JsonObjectIterator& other) const { - return slot_ != other.slot_; + return iterator_ != other.iterator_; } JsonObjectIterator& operator++() { - slot_ = slot_->next(); - return *this; - } - - JsonObjectIterator& operator+=(size_t distance) { - slot_ = slot_->next(distance); + ++iterator_; return *this; } private: + detail::ObjectData::iterator iterator_; detail::ResourceManager* resources_; - detail::VariantSlot* slot_; }; class JsonObjectConstIterator { friend class JsonObject; public: - JsonObjectConstIterator() : slot_(0) {} + JsonObjectConstIterator() {} - explicit JsonObjectConstIterator(const detail::VariantSlot* slot) - : slot_(slot) {} + explicit JsonObjectConstIterator(detail::ObjectData::iterator iterator) + : iterator_(iterator) {} JsonPairConst operator*() const { - return JsonPairConst(slot_); + return JsonPairConst(iterator_); } Ptr operator->() { return operator*(); } bool operator==(const JsonObjectConstIterator& other) const { - return slot_ == other.slot_; + return iterator_ == other.iterator_; } bool operator!=(const JsonObjectConstIterator& other) const { - return slot_ != other.slot_; + return iterator_ != other.iterator_; } JsonObjectConstIterator& operator++() { - slot_ = slot_->next(); - return *this; - } - - JsonObjectConstIterator& operator+=(size_t distance) { - slot_ = slot_->next(distance); + ++iterator_; return *this; } private: - const detail::VariantSlot* slot_; + detail::ObjectData::iterator iterator_; }; ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/src/ArduinoJson/Object/JsonPair.hpp b/src/ArduinoJson/Object/JsonPair.hpp index 252e9612..19548eb7 100644 --- a/src/ArduinoJson/Object/JsonPair.hpp +++ b/src/ArduinoJson/Object/JsonPair.hpp @@ -15,54 +15,53 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE class JsonPair { public: // INTERNAL USE ONLY - JsonPair(detail::ResourceManager* resources, detail::VariantSlot* slot) { - if (slot) { - key_ = JsonString(slot->key(), slot->ownsKey() ? JsonString::Copied - : JsonString::Linked); - value_ = JsonVariant(slot->data(), resources); - } - } + JsonPair(detail::ObjectData::iterator iterator, + detail::ResourceManager* resources) + : iterator_(iterator), resources_(resources) {} // Returns the key. JsonString key() const { - return key_; + if (iterator_) + return JsonString(iterator_.key(), iterator_.ownsKey() + ? JsonString::Copied + : JsonString::Linked); + else + return JsonString(); } // Returns the value. - JsonVariant value() const { - return value_; + JsonVariant value() { + return JsonVariant(iterator_.data(), resources_); } private: - JsonString key_; - JsonVariant value_; + detail::ObjectData::iterator iterator_; + detail::ResourceManager* resources_; }; // A read-only key-value pair. // https://arduinojson.org/v6/api/jsonobjectconst/begin_end/ class JsonPairConst { public: - JsonPairConst(const detail::VariantSlot* slot) { - if (slot) { - key_ = JsonString(slot->key(), slot->ownsKey() ? JsonString::Copied - : JsonString::Linked); - value_ = JsonVariantConst(slot->data()); - } - } + JsonPairConst(detail::ObjectData::iterator iterator) : iterator_(iterator) {} // Returns the key. JsonString key() const { - return key_; + if (iterator_) + return JsonString(iterator_.key(), iterator_.ownsKey() + ? JsonString::Copied + : JsonString::Linked); + else + return JsonString(); } // Returns the value. JsonVariantConst value() const { - return value_; + return JsonVariantConst(iterator_.data()); } private: - JsonString key_; - JsonVariantConst value_; + detail::ObjectData::iterator iterator_; }; ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/src/ArduinoJson/Object/ObjectData.hpp b/src/ArduinoJson/Object/ObjectData.hpp index ef9267b6..29bfdb4a 100644 --- a/src/ArduinoJson/Object/ObjectData.hpp +++ b/src/ArduinoJson/Object/ObjectData.hpp @@ -63,7 +63,7 @@ class ObjectData : public CollectionData { private: template - VariantSlot* getSlot(TAdaptedString key) 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 db4450f5..f1964dae 100644 --- a/src/ArduinoJson/Object/ObjectImpl.hpp +++ b/src/ArduinoJson/Object/ObjectImpl.hpp @@ -44,14 +44,14 @@ inline bool ObjectData::copyFrom(const ObjectData& src, ResourceManager* resources) { clear(resources); - for (VariantSlot* s = src.head(); s; s = s->next()) { - ARDUINOJSON_ASSERT(s->key() != 0); - JsonString key(s->key(), - s->ownsKey() ? JsonString::Copied : JsonString::Linked); + for (auto it = src.begin(); it; ++it) { + ARDUINOJSON_ASSERT(it.key() != 0); + JsonString key(it.key(), + it.ownsKey() ? JsonString::Copied : JsonString::Linked); auto var = addMember(adaptString(key), resources); if (!var) return false; - if (!var->copyFrom(s->data(), resources)) + if (!var->copyFrom(*it, resources)) return false; } return true; @@ -59,11 +59,12 @@ inline bool ObjectData::copyFrom(const ObjectData& src, inline bool ObjectData::equals(const ObjectData& other) const { size_t count = 0; - for (auto a = head(); a; a = a->next()) { - auto b = other.getMember(adaptString(a->key())); + for (auto it = begin(); it; ++it) { + auto a = it.data(); + auto b = other.getMember(adaptString(it.key())); if (!b) return false; - if (compare(a->data(), b) != COMPARE_RESULT_EQUAL) + if (compare(a, b) != COMPARE_RESULT_EQUAL) return false; count++; } @@ -72,35 +73,33 @@ inline bool ObjectData::equals(const ObjectData& other) const { template inline VariantData* ObjectData::getMember(TAdaptedString key) const { - return slotData(getSlot(key)); + return findKey(key).data(); } template VariantData* ObjectData::getOrAddMember(TAdaptedString key, ResourceManager* resources) { - auto slot = getSlot(key); - if (slot) - return slot->data(); + auto it = findKey(key); + if (it) + return it.data(); return addMember(key, resources); } template -inline VariantSlot* ObjectData::getSlot(TAdaptedString key) const { +inline ObjectData::iterator ObjectData::findKey(TAdaptedString key) const { if (key.isNull()) - return 0; - VariantSlot* slot = head(); - while (slot) { - if (stringEquals(key, adaptString(slot->key()))) - break; - slot = slot->next(); + return end(); + for (auto it = begin(); it; ++it) { + if (stringEquals(key, adaptString(it.key()))) + return it; } - return slot; + return end(); } template inline void ObjectData::removeMember(TAdaptedString key, ResourceManager* resources) { - removeSlot(getSlot(key), resources); + remove(findKey(key), resources); } ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Variant/VariantData.hpp b/src/ArduinoJson/Variant/VariantData.hpp index ccf0ab60..79719c14 100644 --- a/src/ArduinoJson/Variant/VariantData.hpp +++ b/src/ArduinoJson/Variant/VariantData.hpp @@ -107,10 +107,14 @@ class VariantData { return const_cast(this)->asArray(); } - const CollectionData* asCollection() const { + CollectionData* asCollection() { return isCollection() ? &content_.asCollection : 0; } + const CollectionData* asCollection() const { + return const_cast(this)->asCollection(); + } + template T asFloat() const { static_assert(is_floating_point::value, "T must be a floating point"); @@ -182,19 +186,15 @@ class VariantData { } } - bool copyFrom(const VariantData* src, ResourceManager* resources) { + bool copyFrom(const VariantData& src, ResourceManager* resources) { release(resources); - if (!src) { - setNull(); - return true; - } - switch (src->type()) { + switch (src.type()) { case VALUE_IS_ARRAY: - return toArray().copyFrom(*src->asArray(), resources); + return toArray().copyFrom(src.content_.asArray, resources); case VALUE_IS_OBJECT: - return toObject().copyFrom(*src->asObject(), resources); + return toObject().copyFrom(src.content_.asObject, resources); case VALUE_IS_OWNED_STRING: { - auto str = adaptString(src->asString()); + auto str = adaptString(src.asString()); auto dup = resources->saveString(str); if (!dup) return false; @@ -202,7 +202,7 @@ class VariantData { return true; } case VALUE_IS_RAW_STRING: { - auto str = adaptString(src->asRawString()); + auto str = adaptString(src.asRawString()); auto dup = resources->saveString(str); if (!dup) return false; @@ -210,8 +210,8 @@ class VariantData { return true; } default: - content_ = src->content_; - flags_ = src->flags_; + content_ = src.content_; + flags_ = src.flags_; return true; } } @@ -220,7 +220,11 @@ class VariantData { ResourceManager* resources) { if (!dst) return false; - return dst->copyFrom(src, resources); + if (!src) { + dst->setNull(); + return true; + } + return dst->copyFrom(*src, resources); } VariantData* getElement(size_t index) const { @@ -334,16 +338,10 @@ class VariantData { size_t nesting() const { auto collection = asCollection(); - if (!collection) + if (collection) + return collection->nesting(); + else return 0; - - size_t maxChildNesting = 0; - for (const VariantSlot* s = collection->head(); s; s = s->next()) { - size_t childNesting = s->data()->nesting(); - if (childNesting > maxChildNesting) - maxChildNesting = childNesting; - } - return maxChildNesting + 1; } static size_t nesting(const VariantData* var) { @@ -550,11 +548,9 @@ class VariantData { if (flags_ & OWNED_VALUE_BIT) resources->dereferenceString(content_.asOwnedString->data); - auto c = asCollection(); - if (c) { - for (auto slot = c->head(); slot; slot = slot->next()) - slotRelease(slot, resources); - } + auto collection = asCollection(); + if (collection) + collection->clear(resources); } void setType(uint8_t t) { diff --git a/src/ArduinoJson/Variant/VariantSlot.hpp b/src/ArduinoJson/Variant/VariantSlot.hpp index 6b0bb520..70835427 100644 --- a/src/ArduinoJson/Variant/VariantSlot.hpp +++ b/src/ArduinoJson/Variant/VariantSlot.hpp @@ -51,20 +51,6 @@ class VariantSlot { return const_cast(this)->next(); } - VariantSlot* next(size_t distance) { - VariantSlot* slot = this; - while (distance--) { - if (!slot->next_) - return 0; - slot += slot->next_; - } - return slot; - } - - const VariantSlot* next(size_t distance) const { - return const_cast(this)->next(distance); - } - void setNext(VariantSlot* slot) { ARDUINOJSON_ASSERT(!slot || slot - this >= numeric_limits::lowest());