VariantImpl: remove addValue()

This removes the two-way dependency between `JsonVariant` and `VariantImpl`
This commit is contained in:
Benoit Blanchon
2025-07-20 14:56:06 +02:00
parent e86c6acf2e
commit f680598a2f
7 changed files with 60 additions and 53 deletions

View File

@ -5,7 +5,6 @@
#pragma once
#include <ArduinoJson/Collection/CollectionIterator.hpp>
#include <ArduinoJson/Variant/VariantCompare.hpp>
#include <ArduinoJson/Variant/VariantImpl.hpp>
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<VariantData> 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 <typename T>
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);

View File

@ -25,6 +25,10 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// 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<JsonArray> {
// https://arduinojson.org/v7/api/jsonarray/add/
template <typename T>
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<JsonArray> {
template <typename T,
detail::enable_if_t<!detail::is_const<T>::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<JsonArray> {
return impl_;
}
template <typename T>
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_;
};

View File

@ -18,19 +18,6 @@ inline VariantImpl::iterator VariantImpl::createIterator() const {
return iterator(coll->head, resources_);
}
inline void VariantImpl::appendOne(Slot<VariantData> 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<VariantData> key,
Slot<VariantData> value) {
auto coll = getCollectionData();

View File

@ -267,14 +267,14 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
template <typename T, detail::enable_if_t<
detail::is_same<T, JsonVariant>::value, int> = 0>
JsonVariant add() {
return JsonVariant(getOrCreateArray().addElement(), &resources_);
return getOrCreateArray().add<T>();
}
// Appends a value to the root array.
// https://arduinojson.org/v7/api/jsondocument/add/
template <typename TValue>
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<const JsonDocument&> {
template <typename TChar,
detail::enable_if_t<!detail::is_const<TChar>::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<const JsonDocument&> {
return {&data_, &resources_};
}
detail::VariantImpl getOrCreateArray() {
return detail::VariantImpl(data_.getOrCreateArray(), &resources_);
JsonArray getOrCreateArray() {
return JsonArray(data_.getOrCreateArray(), &resources_);
}
JsonVariant getVariant() {

View File

@ -97,9 +97,7 @@ class VariantImpl {
}
VariantData* addElement();
template <typename T>
bool addValue(const T& value);
void addElement(Slot<VariantData> slot);
bool asBoolean() const {
if (!data_)
@ -550,7 +548,6 @@ class VariantImpl {
iterator at(size_t index) const;
void appendOne(Slot<VariantData> slot);
void appendPair(Slot<VariantData> key, Slot<VariantData> value);
void removeOne(iterator it);

View File

@ -120,14 +120,14 @@ class VariantRefBase : public VariantTag {
// https://arduinojson.org/v7/api/jsonvariant/add/
template <typename T>
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 <typename T, enable_if_t<!is_const<T>::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;

View File

@ -69,8 +69,7 @@ inline bool convertToJson(const VariantRefBase<TDerived>& src,
template <typename TDerived>
template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int>>
inline T VariantRefBase<TDerived>::add() const {
auto impl = getOrCreateArray();
return JsonVariant(impl.addElement(), impl.resources());
return getOrCreateArray().template add<T>();
}
template <typename TDerived>
@ -141,6 +140,15 @@ inline bool VariantRefBase<TDerived>::doSet(const T& value, true_type) const {
return TConverter::toJson(value, JsonVariant(impl));
}
template <typename TDerived>
inline JsonArray VariantRefBase<TDerived>::getOrCreateArray() const {
auto impl = getOrCreateImpl();
auto data = impl.data();
if (data)
data->getOrCreateArray();
return JsonArray(impl);
}
template <typename TDerived>
template <typename T, enable_if_t<is_same<T, JsonArray>::value, int>>
inline JsonArray VariantRefBase<TDerived>::to() const {