From 57e9134540ac48e5f489360747f7a1d38e661b5a Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Mon, 10 Jul 2023 18:26:45 +0200 Subject: [PATCH] Implement variant copy at the `JsonVariant` level --- src/ArduinoJson.hpp | 1 + src/ArduinoJson/Array/ArrayImpl.hpp | 5 +-- src/ArduinoJson/Object/ObjectImpl.hpp | 5 +-- src/ArduinoJson/Variant/ConverterImpl.hpp | 26 ++++++++---- src/ArduinoJson/Variant/JsonVariant.hpp | 10 +++-- src/ArduinoJson/Variant/JsonVariantCopier.hpp | 34 +++++++++++++++ src/ArduinoJson/Variant/VariantData.hpp | 41 ------------------- 7 files changed, 62 insertions(+), 60 deletions(-) create mode 100644 src/ArduinoJson/Variant/JsonVariantCopier.hpp diff --git a/src/ArduinoJson.hpp b/src/ArduinoJson.hpp index da628d5e..5cc06db4 100644 --- a/src/ArduinoJson.hpp +++ b/src/ArduinoJson.hpp @@ -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" diff --git a/src/ArduinoJson/Array/ArrayImpl.hpp b/src/ArduinoJson/Array/ArrayImpl.hpp index 36aae4ff..0183a14b 100644 --- a/src/ArduinoJson/Array/ArrayImpl.hpp +++ b/src/ArduinoJson/Array/ArrayImpl.hpp @@ -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; diff --git a/src/ArduinoJson/Object/ObjectImpl.hpp b/src/ArduinoJson/Object/ObjectImpl.hpp index d13ebae0..fdb97330 100644 --- a/src/ArduinoJson/Object/ObjectImpl.hpp +++ b/src/ArduinoJson/Object/ObjectImpl.hpp @@ -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; diff --git a/src/ArduinoJson/Variant/ConverterImpl.hpp b/src/ArduinoJson/Variant/ConverterImpl.hpp index 3f80b244..4e6ed951 100644 --- a/src/ArduinoJson/Variant/ConverterImpl.hpp +++ b/src/ArduinoJson/Variant/ConverterImpl.hpp @@ -302,9 +302,11 @@ struct ConverterNeedsWriteableRef { template <> struct Converter : 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().set(src); } static JsonArrayConst fromJson(JsonVariantConst src) { @@ -322,8 +324,10 @@ struct Converter : private detail::VariantAttorney { template <> struct Converter : 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().set(src); } static JsonArray fromJson(JsonVariant src) { @@ -348,8 +352,10 @@ struct Converter : private detail::VariantAttorney { template <> struct Converter : 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().set(src); } static JsonObjectConst fromJson(JsonVariantConst src) { @@ -367,8 +373,10 @@ struct Converter : private detail::VariantAttorney { template <> struct Converter : 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().set(src); } static JsonObject fromJson(JsonVariant src) { diff --git a/src/ArduinoJson/Variant/JsonVariant.hpp b/src/ArduinoJson/Variant/JsonVariant.hpp index 4991b5da..637148ec 100644 --- a/src/ArduinoJson/Variant/JsonVariant.hpp +++ b/src/ArduinoJson/Variant/JsonVariant.hpp @@ -39,11 +39,14 @@ class JsonVariant : public detail::VariantRefBase, detail::ResourceManager* resources_; }; +namespace detail { +bool copyVariant(JsonVariant dst, JsonVariantConst src); +} + template <> struct Converter : 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 : private detail::VariantAttorney { template <> struct Converter : 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) { diff --git a/src/ArduinoJson/Variant/JsonVariantCopier.hpp b/src/ArduinoJson/Variant/JsonVariantCopier.hpp new file mode 100644 index 00000000..176b5f3e --- /dev/null +++ b/src/ArduinoJson/Variant/JsonVariantCopier.hpp @@ -0,0 +1,34 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2023, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +class JsonVariantCopier { + public: + typedef bool result_type; + + JsonVariantCopier(JsonVariant dst) : dst_(dst) {} + + template + 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 diff --git a/src/ArduinoJson/Variant/VariantData.hpp b/src/ArduinoJson/Variant/VariantData.hpp index baa2435b..2035fe2f 100644 --- a/src/ArduinoJson/Variant/VariantData.hpp +++ b/src/ArduinoJson/Variant/VariantData.hpp @@ -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)