mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-29 10:17:39 +02:00
VariantImpl: add copy functions
This commit is contained in:
@ -48,7 +48,6 @@
|
||||
#include "ArduinoJson/Object/MemberProxy.hpp"
|
||||
#include "ArduinoJson/Object/ObjectImpl.hpp"
|
||||
#include "ArduinoJson/Variant/ConverterImpl.hpp"
|
||||
#include "ArduinoJson/Variant/JsonVariantCopier.hpp"
|
||||
#include "ArduinoJson/Variant/VariantCompare.hpp"
|
||||
#include "ArduinoJson/Variant/VariantRefBaseImpl.hpp"
|
||||
|
||||
|
@ -76,6 +76,31 @@ inline void VariantImpl::removeElement(size_t index) {
|
||||
removeElement(at(index));
|
||||
}
|
||||
|
||||
inline bool VariantImpl::copyArray(const VariantImpl& src) {
|
||||
ARDUINOJSON_ASSERT(isNull());
|
||||
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
data_->toArray();
|
||||
|
||||
for (auto it = src.createIterator(); !it.done(); it.move()) {
|
||||
auto slot = allocVariant();
|
||||
if (!slot)
|
||||
return false;
|
||||
|
||||
VariantImpl element(slot.ptr(), resources_);
|
||||
if (!element.copyVariant(*it)) {
|
||||
freeVariant(slot);
|
||||
return false;
|
||||
}
|
||||
|
||||
addElement(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);
|
||||
|
@ -89,16 +89,8 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
||||
// Copies an array.
|
||||
// https://arduinojson.org/v7/api/jsonarray/set/
|
||||
bool set(JsonArrayConst src) const {
|
||||
if (isNull())
|
||||
return false;
|
||||
|
||||
clear();
|
||||
for (auto element : src) {
|
||||
if (!add(element))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
impl_.clear();
|
||||
return impl_.copyArray(detail::VariantAttorney::getImpl(src));
|
||||
}
|
||||
|
||||
// Removes the element at the specified iterator.
|
||||
|
@ -18,8 +18,12 @@ inline VariantImpl::iterator VariantImpl::createIterator() const {
|
||||
return iterator(coll->head, resources_);
|
||||
}
|
||||
|
||||
inline void VariantImpl::appendPair(Slot<VariantData> key,
|
||||
Slot<VariantData> value) {
|
||||
inline void VariantImpl::addMember(Slot<VariantData> key,
|
||||
Slot<VariantData> value) {
|
||||
ARDUINOJSON_ASSERT(isObject());
|
||||
ARDUINOJSON_ASSERT(key);
|
||||
ARDUINOJSON_ASSERT(value);
|
||||
|
||||
auto coll = getCollectionData();
|
||||
|
||||
key->next = value.id();
|
||||
|
@ -280,11 +280,18 @@ class JsonDeserializer {
|
||||
VariantImpl object(objectData, resources_);
|
||||
auto member = object.getMember(adaptString(key));
|
||||
if (!member) {
|
||||
auto keyVariant = object.addPair(&member);
|
||||
if (!keyVariant)
|
||||
auto keySlot = resources_->allocVariant();
|
||||
if (!keySlot)
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
stringBuilder_.save(keyVariant);
|
||||
auto valueSlot = resources_->allocVariant();
|
||||
if (!valueSlot)
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
object.addMember(keySlot, valueSlot);
|
||||
|
||||
stringBuilder_.save(keySlot.ptr());
|
||||
member = valueSlot.ptr();
|
||||
} else {
|
||||
VariantImpl(member, resources_).clear();
|
||||
}
|
||||
|
@ -401,11 +401,18 @@ class MsgPackDeserializer {
|
||||
VariantData* member = 0;
|
||||
|
||||
if (memberFilter.allow()) {
|
||||
auto keyVariant = object.addPair(&member);
|
||||
if (!keyVariant)
|
||||
auto keySlot = resources_->allocVariant();
|
||||
if (!keySlot)
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
stringBuffer_.save(keyVariant);
|
||||
auto valueSlot = resources_->allocVariant();
|
||||
if (!valueSlot)
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
object.addMember(keySlot, valueSlot);
|
||||
|
||||
member = valueSlot.ptr();
|
||||
stringBuffer_.save(keySlot.ptr());
|
||||
}
|
||||
|
||||
err = parseVariant(member, memberFilter, nestingLimit.decrement());
|
||||
|
@ -83,16 +83,11 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
|
||||
// Copies an object.
|
||||
// https://arduinojson.org/v7/api/jsonobject/set/
|
||||
bool set(JsonObjectConst src) {
|
||||
if (isNull() || src.isNull())
|
||||
if (isNull() ||
|
||||
src.isNull()) // TODO: this check is not consistent with JsonArray
|
||||
return false;
|
||||
|
||||
clear();
|
||||
for (auto kvp : src) {
|
||||
if (!operator[](kvp.key()).set(kvp.value()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
impl_.clear();
|
||||
return impl_.copyObject(detail::VariantAttorney::getImpl(src));
|
||||
}
|
||||
|
||||
// Gets or sets the member with specified key.
|
||||
|
@ -9,6 +9,46 @@
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
inline bool VariantImpl::copyObject(const VariantImpl& src) {
|
||||
ARDUINOJSON_ASSERT(isNull());
|
||||
|
||||
if (!data_)
|
||||
return false;
|
||||
|
||||
data_->toObject();
|
||||
|
||||
for (auto it = src.createIterator(); !it.done(); it.move()) {
|
||||
auto keySlot = allocVariant();
|
||||
if (!keySlot)
|
||||
return false;
|
||||
|
||||
auto key = VariantImpl(keySlot.ptr(), resources_);
|
||||
if (!key.copyVariant(*it)) {
|
||||
freeVariant(keySlot);
|
||||
return false;
|
||||
}
|
||||
|
||||
it.move(); // move to value
|
||||
ARDUINOJSON_ASSERT(!it.done());
|
||||
|
||||
auto valueSlot = allocVariant();
|
||||
if (!valueSlot) {
|
||||
freeVariant(keySlot);
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: we add the pair before copying the value to be keep the old
|
||||
// behavior but this is not consistent with issue #2081
|
||||
addMember(keySlot, valueSlot);
|
||||
|
||||
auto value = VariantImpl(valueSlot.ptr(), resources_);
|
||||
if (!value.copyVariant(*it))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
inline VariantData* VariantImpl::getMember(TAdaptedString key) const {
|
||||
auto it = findKey(key);
|
||||
@ -70,28 +110,11 @@ inline VariantData* VariantImpl::addMember(TAdaptedString key) {
|
||||
if (!keyImpl.setString(key))
|
||||
return nullptr;
|
||||
|
||||
VariantImpl::appendPair(keySlot, valueSlot);
|
||||
addMember(keySlot, valueSlot);
|
||||
|
||||
return valueSlot.ptr();
|
||||
}
|
||||
|
||||
inline VariantData* VariantImpl::addPair(VariantData** value) {
|
||||
ARDUINOJSON_ASSERT(isObject());
|
||||
|
||||
auto keySlot = allocVariant();
|
||||
if (!keySlot)
|
||||
return nullptr;
|
||||
|
||||
auto valueSlot = allocVariant();
|
||||
if (!valueSlot)
|
||||
return nullptr;
|
||||
*value = valueSlot.ptr();
|
||||
|
||||
VariantImpl::appendPair(keySlot, valueSlot);
|
||||
|
||||
return keySlot.ptr();
|
||||
}
|
||||
|
||||
// Returns the size (in bytes) of an object with n members.
|
||||
constexpr size_t sizeofObject(size_t n) {
|
||||
return 2 * n * sizeof(VariantData);
|
||||
|
@ -37,14 +37,12 @@ class JsonVariant : public detail::VariantRefBase<JsonVariant>,
|
||||
mutable detail::VariantImpl impl_;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
bool copyVariant(JsonVariant dst, JsonVariantConst src);
|
||||
}
|
||||
|
||||
template <>
|
||||
struct Converter<JsonVariant> : private detail::VariantAttorney {
|
||||
static bool toJson(JsonVariantConst src, JsonVariant dst) {
|
||||
return copyVariant(dst, src);
|
||||
auto impl = getImpl(dst);
|
||||
impl.clear();
|
||||
return impl.copyVariant(getImpl(src));
|
||||
}
|
||||
|
||||
static JsonVariant fromJson(JsonVariant src) {
|
||||
@ -59,7 +57,9 @@ struct Converter<JsonVariant> : private detail::VariantAttorney {
|
||||
template <>
|
||||
struct Converter<JsonVariantConst> : private detail::VariantAttorney {
|
||||
static bool toJson(JsonVariantConst src, JsonVariant dst) {
|
||||
return copyVariant(dst, src);
|
||||
auto impl = getImpl(dst);
|
||||
impl.clear();
|
||||
return impl.copyVariant(getImpl(src));
|
||||
}
|
||||
|
||||
static JsonVariantConst fromJson(JsonVariantConst src) {
|
||||
|
@ -1,34 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2025, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Variant/JsonVariant.hpp>
|
||||
#include <ArduinoJson/Variant/JsonVariantVisitor.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
class JsonVariantCopier {
|
||||
public:
|
||||
using result_type = bool;
|
||||
|
||||
JsonVariantCopier(JsonVariant dst) : dst_(dst) {}
|
||||
|
||||
template <typename T>
|
||||
bool visit(T src) {
|
||||
return dst_.set(src);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonVariant dst_;
|
||||
};
|
||||
|
||||
inline bool copyVariant(JsonVariant dst, JsonVariantConst src) {
|
||||
if (dst.isUnbound())
|
||||
return false;
|
||||
JsonVariantCopier copier(dst);
|
||||
return accept(src, copier);
|
||||
}
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
@ -85,17 +85,19 @@ struct VariantData {
|
||||
}
|
||||
|
||||
VariantData* toArray() {
|
||||
return toCollection(VariantType::Array);
|
||||
}
|
||||
|
||||
VariantData* toCollection(VariantType collectionType) {
|
||||
ARDUINOJSON_ASSERT(type == VariantType::Null);
|
||||
type = VariantType::Array;
|
||||
ARDUINOJSON_ASSERT(collectionType & VariantTypeBits::CollectionMask);
|
||||
type = collectionType;
|
||||
new (&content.asCollection) CollectionData();
|
||||
return this;
|
||||
}
|
||||
|
||||
VariantData* toObject() {
|
||||
ARDUINOJSON_ASSERT(type == VariantType::Null);
|
||||
type = VariantType::Object;
|
||||
new (&content.asCollection) CollectionData();
|
||||
return this;
|
||||
return toCollection(VariantType::Object);
|
||||
}
|
||||
|
||||
VariantData* getOrCreateArray() {
|
||||
|
@ -276,7 +276,7 @@ class VariantImpl {
|
||||
|
||||
VariantData* getOrAddElement(size_t index);
|
||||
|
||||
VariantData* addPair(VariantData** value);
|
||||
void addMember(Slot<VariantData> key, Slot<VariantData> value);
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData* addMember(TAdaptedString key);
|
||||
@ -354,6 +354,36 @@ class VariantImpl {
|
||||
|
||||
void removeMember(iterator it);
|
||||
|
||||
bool copyVariant(const VariantImpl& src) {
|
||||
switch (src.type()) {
|
||||
case VariantType::Null:
|
||||
return true;
|
||||
|
||||
case VariantType::Array:
|
||||
return copyArray(src);
|
||||
|
||||
case VariantType::Object:
|
||||
return copyObject(src);
|
||||
|
||||
case VariantType::RawString:
|
||||
return setRawString(adaptString(src.asRawString()));
|
||||
|
||||
case VariantType::LinkedString:
|
||||
return setLinkedString(src.asLinkedString());
|
||||
|
||||
case VariantType::OwnedString:
|
||||
return setOwnedString(adaptString(src.asString()));
|
||||
|
||||
default:
|
||||
data_->content = src.data_->content;
|
||||
data_->type = src.data_->type;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool copyArray(const VariantImpl& src);
|
||||
bool copyObject(const VariantImpl& src);
|
||||
|
||||
bool setBoolean(bool value) {
|
||||
if (!data_)
|
||||
return false;
|
||||
@ -548,8 +578,6 @@ class VariantImpl {
|
||||
|
||||
iterator at(size_t index) const;
|
||||
|
||||
void appendPair(Slot<VariantData> key, Slot<VariantData> value);
|
||||
|
||||
void removeOne(iterator it);
|
||||
void removePair(iterator it);
|
||||
|
||||
|
Reference in New Issue
Block a user