Преглед на файлове

Add `CollectionIterator`

Benoit Blanchon преди 2 години
родител
ревизия
688e21e75f

+ 2 - 1
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);

+ 1 - 1
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

+ 26 - 23
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

+ 2 - 2
src/ArduinoJson/Array/JsonArray.hpp

@@ -68,7 +68,7 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
   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<JsonArray> {
   // ⚠️ 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.

+ 1 - 1
src/ArduinoJson/Array/JsonArrayConst.hpp

@@ -26,7 +26,7 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
   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.

+ 18 - 28
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<JsonVariant> 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<JsonVariantConst> 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

+ 69 - 11
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<VariantData*>(slot_);
+  }
+
+  const VariantData* data() const {
+    return reinterpret_cast<const VariantData*>(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);
+  void movePointers(ptrdiff_t variantDistance);
 
-  static void removeSlot(CollectionData* collection, VariantSlot* slot,
-                         ResourceManager* resources) {
-    if (!collection)
-      return;
-    collection->removeSlot(slot, resources);
-  }
+  void remove(iterator it, ResourceManager* resources);
 
-  VariantSlot* head() const {
-    return head_;
+  static void remove(CollectionData* collection, iterator it,
+                     ResourceManager* resources) {
+    if (collection)
+      return collection->remove(it, resources);
   }
 
-  void movePointers(ptrdiff_t variantDistance);
-
  protected:
   void addSlot(VariantSlot*);
 

+ 32 - 6
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_);
 }

+ 11 - 11
src/ArduinoJson/Json/JsonSerializer.hpp

@@ -21,13 +21,13 @@ class JsonSerializer : public Visitor<size_t> {
   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> {
   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(',');

+ 13 - 13
src/ArduinoJson/Json/PrettyJsonSerializer.hpp

@@ -19,16 +19,16 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
   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<TWriter> {
   }
 
   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();

+ 5 - 5
src/ArduinoJson/MsgPack/MsgPackSerializer.hpp

@@ -55,8 +55,8 @@ class MsgPackSerializer : public Visitor<size_t> {
       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<size_t> {
       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();
   }

+ 2 - 2
src/ArduinoJson/Object/JsonObject.hpp

@@ -76,7 +76,7 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
   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<JsonObject> {
   // ⚠️ 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.

+ 1 - 1
src/ArduinoJson/Object/JsonObjectConst.hpp

@@ -63,7 +63,7 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
   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.

+ 17 - 27
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<JsonPair> 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<JsonPairConst> 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

+ 22 - 23
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

+ 1 - 1
src/ArduinoJson/Object/ObjectData.hpp

@@ -63,7 +63,7 @@ class ObjectData : public CollectionData {
 
  private:
   template <typename TAdaptedString>
-  VariantSlot* getSlot(TAdaptedString key) const;
+  iterator findKey(TAdaptedString key) const;
 };
 
 ARDUINOJSON_END_PRIVATE_NAMESPACE

+ 20 - 21
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 <typename TAdaptedString>
 inline VariantData* ObjectData::getMember(TAdaptedString key) const {
-  return slotData(getSlot(key));
+  return findKey(key).data();
 }
 
 template <typename TAdaptedString>
 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 <typename TAdaptedString>
-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 <typename TAdaptedString>
 inline void ObjectData::removeMember(TAdaptedString key,
                                      ResourceManager* resources) {
-  removeSlot(getSlot(key), resources);
+  remove(findKey(key), resources);
 }
 
 ARDUINOJSON_END_PRIVATE_NAMESPACE

+ 24 - 28
src/ArduinoJson/Variant/VariantData.hpp

@@ -107,10 +107,14 @@ class VariantData {
     return const_cast<VariantData*>(this)->asArray();
   }
 
-  const CollectionData* asCollection() const {
+  CollectionData* asCollection() {
     return isCollection() ? &content_.asCollection : 0;
   }
 
+  const CollectionData* asCollection() const {
+    return const_cast<VariantData*>(this)->asCollection();
+  }
+
   template <typename T>
   T asFloat() const {
     static_assert(is_floating_point<T>::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) {

+ 0 - 14
src/ArduinoJson/Variant/VariantSlot.hpp

@@ -51,20 +51,6 @@ class VariantSlot {
     return const_cast<VariantSlot*>(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<VariantSlot*>(this)->next(distance);
-  }
-
   void setNext(VariantSlot* slot) {
     ARDUINOJSON_ASSERT(!slot || slot - this >=
                                     numeric_limits<VariantSlotDiff>::lowest());