diff --git a/src/ArduinoJson/Array/ArrayImpl.hpp b/src/ArduinoJson/Array/ArrayImpl.hpp index 5cd9752a..8ff01deb 100644 --- a/src/ArduinoJson/Array/ArrayImpl.hpp +++ b/src/ArduinoJson/Array/ArrayImpl.hpp @@ -5,7 +5,6 @@ #pragma once #include -#include #include ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE @@ -28,10 +27,23 @@ inline VariantData* VariantImpl::addElement() { auto slot = allocVariant(); if (!slot) return nullptr; - VariantImpl::appendOne(slot); + addElement(slot); return slot.ptr(); } +inline void VariantImpl::addElement(Slot slot) { + auto coll = getCollectionData(); + + if (coll->tail != NULL_SLOT) { + auto tail = getVariant(coll->tail); + tail->next = slot.id(); + coll->tail = slot.id(); + } else { + coll->head = slot.id(); + coll->tail = slot.id(); + } +} + inline VariantData* VariantImpl::getOrAddElement(size_t index) { auto it = createIterator(); while (!it.done() && index > 0) { @@ -64,22 +76,6 @@ inline void VariantImpl::removeElement(size_t index) { removeElement(at(index)); } -template -inline bool VariantImpl::addValue(const T& value) { - if (!isArray()) - return false; - auto slot = allocVariant(); - if (!slot) - return false; - JsonVariant variant(slot.ptr(), resources_); - if (!variant.set(value)) { - freeVariant(slot); - return false; - } - appendOne(slot); - return true; -} - // Returns the size (in bytes) of an array with n elements. constexpr size_t sizeofArray(size_t n) { return n * sizeof(VariantData); diff --git a/src/ArduinoJson/Array/JsonArray.hpp b/src/ArduinoJson/Array/JsonArray.hpp index ce2abaf2..7c2e8eb4 100644 --- a/src/ArduinoJson/Array/JsonArray.hpp +++ b/src/ArduinoJson/Array/JsonArray.hpp @@ -25,6 +25,10 @@ class JsonArray : public detail::VariantOperators { // INTERNAL USE ONLY JsonArray(detail::VariantImpl impl) : impl_(impl) {} + // INTERNAL USE ONLY + JsonArray(detail::VariantData* data, detail::ResourceManager* resources) + : impl_(data, resources) {} + // Returns a JsonVariant pointing to the array. // https://arduinojson.org/v7/api/jsonvariant/ operator JsonVariant() { @@ -59,7 +63,7 @@ class JsonArray : public detail::VariantOperators { // https://arduinojson.org/v7/api/jsonarray/add/ template bool add(const T& value) const { - return impl_.addValue(value); + return doAdd(value); } // Appends a value to the array. @@ -67,7 +71,7 @@ class JsonArray : public detail::VariantOperators { template ::value, int> = 0> bool add(T* value) const { - return impl_.addValue(value); + return doAdd(value); } // Returns an iterator to the first element of the array. @@ -203,6 +207,27 @@ class JsonArray : public detail::VariantOperators { return impl_; } + template + bool doAdd(const T& value) const { + if (!impl_.isArray()) + return false; + + auto resources = impl_.resources(); + ARDUINOJSON_ASSERT(resources != nullptr); + + auto slot = resources->allocVariant(); + if (!slot) + return false; + + if (!JsonVariant(slot.ptr(), resources).set(value)) { + detail::VariantImpl(slot.ptr(), resources).clear(); + resources->freeVariant(slot); + return false; + } + impl_.addElement(slot); + return true; + } + mutable detail::VariantImpl impl_; }; diff --git a/src/ArduinoJson/Collection/CollectionImpl.hpp b/src/ArduinoJson/Collection/CollectionImpl.hpp index 8eec1ae7..29cba09a 100644 --- a/src/ArduinoJson/Collection/CollectionImpl.hpp +++ b/src/ArduinoJson/Collection/CollectionImpl.hpp @@ -18,19 +18,6 @@ inline VariantImpl::iterator VariantImpl::createIterator() const { return iterator(coll->head, resources_); } -inline void VariantImpl::appendOne(Slot slot) { - auto coll = getCollectionData(); - - if (coll->tail != NULL_SLOT) { - auto tail = getVariant(coll->tail); - tail->next = slot.id(); - coll->tail = slot.id(); - } else { - coll->head = slot.id(); - coll->tail = slot.id(); - } -} - inline void VariantImpl::appendPair(Slot key, Slot value) { auto coll = getCollectionData(); diff --git a/src/ArduinoJson/Document/JsonDocument.hpp b/src/ArduinoJson/Document/JsonDocument.hpp index ced13519..1e6c4783 100644 --- a/src/ArduinoJson/Document/JsonDocument.hpp +++ b/src/ArduinoJson/Document/JsonDocument.hpp @@ -267,14 +267,14 @@ class JsonDocument : public detail::VariantOperators { template ::value, int> = 0> JsonVariant add() { - return JsonVariant(getOrCreateArray().addElement(), &resources_); + return getOrCreateArray().add(); } // Appends a value to the root array. // https://arduinojson.org/v7/api/jsondocument/add/ template bool add(const TValue& value) { - return getOrCreateArray().addValue(value); + return getOrCreateArray().add(value); } // Appends a value to the root array. @@ -282,7 +282,7 @@ class JsonDocument : public detail::VariantOperators { template ::value, int> = 0> bool add(TChar* value) { - return getOrCreateArray().addValue(value); + return getOrCreateArray().add(value); } // Removes an element of the root array. @@ -396,8 +396,8 @@ class JsonDocument : public detail::VariantOperators { return {&data_, &resources_}; } - detail::VariantImpl getOrCreateArray() { - return detail::VariantImpl(data_.getOrCreateArray(), &resources_); + JsonArray getOrCreateArray() { + return JsonArray(data_.getOrCreateArray(), &resources_); } JsonVariant getVariant() { diff --git a/src/ArduinoJson/Variant/VariantImpl.hpp b/src/ArduinoJson/Variant/VariantImpl.hpp index 70268f3a..aa2e9fbe 100644 --- a/src/ArduinoJson/Variant/VariantImpl.hpp +++ b/src/ArduinoJson/Variant/VariantImpl.hpp @@ -97,9 +97,7 @@ class VariantImpl { } VariantData* addElement(); - - template - bool addValue(const T& value); + void addElement(Slot slot); bool asBoolean() const { if (!data_) @@ -550,7 +548,6 @@ class VariantImpl { iterator at(size_t index) const; - void appendOne(Slot slot); void appendPair(Slot key, Slot value); void removeOne(iterator it); diff --git a/src/ArduinoJson/Variant/VariantRefBase.hpp b/src/ArduinoJson/Variant/VariantRefBase.hpp index 81ab82b1..f28723f6 100644 --- a/src/ArduinoJson/Variant/VariantRefBase.hpp +++ b/src/ArduinoJson/Variant/VariantRefBase.hpp @@ -120,14 +120,14 @@ class VariantRefBase : public VariantTag { // https://arduinojson.org/v7/api/jsonvariant/add/ template bool add(const T& value) const { - return getOrCreateArray().addValue(value); + return getOrCreateArray().add(value); } // Appends a value to the array. // https://arduinojson.org/v7/api/jsonvariant/add/ template ::value, int> = 0> bool add(T* value) const { - return getOrCreateArray().addValue(value); + return getOrCreateArray().add(value); } // Removes an element of the array. @@ -267,13 +267,7 @@ class VariantRefBase : public VariantTag { return VariantAttorney::getOrCreateImpl(derived()); } - VariantImpl getOrCreateArray() const { - auto impl = getOrCreateImpl(); - auto data = impl.data(); - if (data) - data->getOrCreateArray(); - return impl; - } + JsonArray getOrCreateArray() const; FORCE_INLINE ArduinoJson::JsonVariant getVariant() const; diff --git a/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp b/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp index 6a6bafdc..709c5fc1 100644 --- a/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp +++ b/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp @@ -69,8 +69,7 @@ inline bool convertToJson(const VariantRefBase& src, template template ::value, int>> inline T VariantRefBase::add() const { - auto impl = getOrCreateArray(); - return JsonVariant(impl.addElement(), impl.resources()); + return getOrCreateArray().template add(); } template @@ -141,6 +140,15 @@ inline bool VariantRefBase::doSet(const T& value, true_type) const { return TConverter::toJson(value, JsonVariant(impl)); } +template +inline JsonArray VariantRefBase::getOrCreateArray() const { + auto impl = getOrCreateImpl(); + auto data = impl.data(); + if (data) + data->getOrCreateArray(); + return JsonArray(impl); +} + template template ::value, int>> inline JsonArray VariantRefBase::to() const {