Implement variant copy at the JsonVariant level

This commit is contained in:
Benoit Blanchon
2023-07-10 18:26:45 +02:00
parent fb4cb96c6c
commit 57e9134540
7 changed files with 62 additions and 60 deletions

View File

@ -42,6 +42,7 @@
#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/Json/JsonDeserializer.hpp"

View File

@ -24,9 +24,8 @@ inline bool ArrayData::copyFrom(const ArrayData& src,
for (auto it = src.createIterator(); !it.done(); it.next()) {
auto var = addElement(resources);
if (!var)
return false;
if (!var->copyFrom(*it, resources))
if (!copyVariant(JsonVariant(var, resources),
JsonVariantConst(it.data(), resources)))
return false;
}
return true;

View File

@ -18,9 +18,8 @@ inline bool ObjectData::copyFrom(const ObjectData& src,
JsonString key(it.key(),
it.ownsKey() ? JsonString::Copied : JsonString::Linked);
auto var = addMember(adaptString(key), resources);
if (!var)
return false;
if (!var->copyFrom(*it, resources))
if (!copyVariant(JsonVariant(var, resources),
JsonVariantConst(it.data(), resources)))
return false;
}
return true;

View File

@ -302,9 +302,11 @@ struct ConverterNeedsWriteableRef {
template <>
struct Converter<JsonArrayConst> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) {
detail::VariantData::copy(getData(dst), getData(src),
getResourceManager(dst));
static void toJson(JsonArrayConst src, JsonVariant dst) {
if (src.isNull())
dst.set(nullptr);
else
dst.to<JsonArray>().set(src);
}
static JsonArrayConst fromJson(JsonVariantConst src) {
@ -322,8 +324,10 @@ struct Converter<JsonArrayConst> : private detail::VariantAttorney {
template <>
struct Converter<JsonArray> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) {
detail::VariantData::copy(getData(dst), getData(src),
getResourceManager(dst));
if (src.isNull())
dst.set(nullptr);
else
dst.to<JsonArray>().set(src);
}
static JsonArray fromJson(JsonVariant src) {
@ -348,8 +352,10 @@ struct Converter<JsonArray> : private detail::VariantAttorney {
template <>
struct Converter<JsonObjectConst> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) {
detail::VariantData::copy(getData(dst), getData(src),
getResourceManager(dst));
if (src.isNull())
dst.set(nullptr);
else
dst.to<JsonObject>().set(src);
}
static JsonObjectConst fromJson(JsonVariantConst src) {
@ -367,8 +373,10 @@ struct Converter<JsonObjectConst> : private detail::VariantAttorney {
template <>
struct Converter<JsonObject> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) {
detail::VariantData::copy(getData(dst), getData(src),
getResourceManager(dst));
if (src.isNull())
dst.set(nullptr);
else
dst.to<JsonObject>().set(src);
}
static JsonObject fromJson(JsonVariant src) {

View File

@ -39,11 +39,14 @@ class JsonVariant : public detail::VariantRefBase<JsonVariant>,
detail::ResourceManager* resources_;
};
namespace detail {
bool copyVariant(JsonVariant dst, JsonVariantConst src);
}
template <>
struct Converter<JsonVariant> : private detail::VariantAttorney {
static void toJson(JsonVariant src, JsonVariant dst) {
detail::VariantData::copy(getData(dst), getData(src),
getResourceManager(dst));
copyVariant(dst, src);
}
static JsonVariant fromJson(JsonVariant src) {
@ -66,8 +69,7 @@ struct Converter<JsonVariant> : private detail::VariantAttorney {
template <>
struct Converter<JsonVariantConst> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) {
detail::VariantData::copy(getData(dst), getData(src),
getResourceManager(dst));
copyVariant(dst, src);
}
static JsonVariantConst fromJson(JsonVariantConst src) {

View File

@ -0,0 +1,34 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Variant/JsonVariant.hpp>
#include <ArduinoJson/Variant/JsonVariantVisitor.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class JsonVariantCopier {
public:
typedef bool result_type;
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

View File

@ -185,47 +185,6 @@ class VariantData {
}
}
bool copyFrom(const VariantData& src, ResourceManager* resources) {
release(resources);
switch (src.type()) {
case VALUE_IS_ARRAY:
return toArray().copyFrom(src.content_.asArray, resources);
case VALUE_IS_OBJECT:
return toObject().copyFrom(src.content_.asObject, resources);
case VALUE_IS_OWNED_STRING: {
auto str = adaptString(src.asString());
auto dup = resources->saveString(str);
if (!dup)
return false;
setOwnedString(dup);
return true;
}
case VALUE_IS_RAW_STRING: {
auto str = adaptString(src.asRawString());
auto dup = resources->saveString(str);
if (!dup)
return false;
setRawString(dup);
return true;
}
default:
content_ = src.content_;
flags_ = src.flags_;
return true;
}
}
static bool copy(VariantData* dst, const VariantData* src,
ResourceManager* resources) {
if (!dst)
return false;
if (!src) {
dst->setNull();
return true;
}
return dst->copyFrom(*src, resources);
}
VariantData* getElement(size_t index) const {
auto array = asArray();
if (!array)