Extract VariantProxy from ElementProxy and MemberProxy

This commit is contained in:
Benoit Blanchon
2022-08-30 10:18:08 +02:00
parent 2b6bb78a09
commit cf4436e581
14 changed files with 278 additions and 375 deletions

View File

@ -9,6 +9,7 @@ HEAD
* Fix comparison operators for `JsonArray`, `JsonArrayConst`, `JsonObject`, and `JsonObjectConst` * Fix comparison operators for `JsonArray`, `JsonArrayConst`, `JsonObject`, and `JsonObjectConst`
* Fix lax parsing of `true`, `false`, and `null` (issue #1781) * Fix lax parsing of `true`, `false`, and `null` (issue #1781)
* Remove undocumented `accept()` functions * Remove undocumented `accept()` functions
* Remove undocumented `ElementProxy` and `MemberProxy` classes
* Rename `addElement()` to `add()` * Rename `addElement()` to `add()`
* Remove `getElement()`, `getOrAddElement()`, `getMember()`, and `getOrAddMember()` * Remove `getElement()`, `getOrAddElement()`, `getMember()`, and `getOrAddMember()`
* Remove `JsonDocument::data()` and `JsonDocument::memoryPool()` * Remove `JsonDocument::data()` and `JsonDocument::memoryPool()`

View File

@ -7,10 +7,12 @@
using namespace ARDUINOJSON_NAMESPACE; using namespace ARDUINOJSON_NAMESPACE;
typedef VariantProxy<ElementDataSource<JsonDocument&> > ElementProxy;
TEST_CASE("ElementProxy::add()") { TEST_CASE("ElementProxy::add()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
doc.add(); doc.add();
ElementProxy<JsonDocument&> ep = doc[0]; ElementProxy ep = doc[0];
SECTION("add(int)") { SECTION("add(int)") {
ep.add(42); ep.add(42);
@ -36,7 +38,7 @@ TEST_CASE("ElementProxy::add()") {
TEST_CASE("ElementProxy::clear()") { TEST_CASE("ElementProxy::clear()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
doc.add(); doc.add();
ElementProxy<JsonDocument&> ep = doc[0]; ElementProxy ep = doc[0];
SECTION("size goes back to zero") { SECTION("size goes back to zero") {
ep.add(42); ep.add(42);
@ -96,7 +98,7 @@ TEST_CASE("ElementProxy::operator==()") {
TEST_CASE("ElementProxy::remove()") { TEST_CASE("ElementProxy::remove()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
doc.add(); doc.add();
ElementProxy<JsonDocument&> ep = doc[0]; ElementProxy ep = doc[0];
SECTION("remove(int)") { SECTION("remove(int)") {
ep.add(1); ep.add(1);
@ -143,7 +145,7 @@ TEST_CASE("ElementProxy::remove()") {
TEST_CASE("ElementProxy::set()") { TEST_CASE("ElementProxy::set()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
ElementProxy<JsonDocument&> ep = doc[0]; ElementProxy ep = doc[0];
SECTION("set(int)") { SECTION("set(int)") {
ep.set(42); ep.set(42);
@ -169,7 +171,7 @@ TEST_CASE("ElementProxy::set()") {
TEST_CASE("ElementProxy::size()") { TEST_CASE("ElementProxy::size()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
doc.add(); doc.add();
ElementProxy<JsonDocument&> ep = doc[0]; ElementProxy ep = doc[0];
SECTION("returns 0") { SECTION("returns 0") {
REQUIRE(ep.size() == 0); REQUIRE(ep.size() == 0);
@ -191,7 +193,7 @@ TEST_CASE("ElementProxy::size()") {
TEST_CASE("ElementProxy::memoryUsage()") { TEST_CASE("ElementProxy::memoryUsage()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
doc.add(); doc.add();
ElementProxy<JsonDocument&> ep = doc[0]; ElementProxy ep = doc[0];
SECTION("returns 0 for null") { SECTION("returns 0 for null") {
REQUIRE(ep.memoryUsage() == 0); REQUIRE(ep.memoryUsage() == 0);
@ -205,7 +207,7 @@ TEST_CASE("ElementProxy::memoryUsage()") {
TEST_CASE("ElementProxy::operator[]") { TEST_CASE("ElementProxy::operator[]") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
ElementProxy<JsonDocument&> ep = doc[1]; ElementProxy ep = doc[1];
SECTION("set member") { SECTION("set member") {
ep["world"] = 42; ep["world"] = 42;
@ -224,7 +226,7 @@ TEST_CASE("ElementProxy cast to JsonVariantConst") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
doc[0] = "world"; doc[0] = "world";
const ElementProxy<JsonDocument&> ep = doc[0]; const ElementProxy ep = doc[0];
JsonVariantConst var = ep; JsonVariantConst var = ep;
@ -235,7 +237,7 @@ TEST_CASE("ElementProxy cast to JsonVariant") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
doc[0] = "world"; doc[0] = "world";
ElementProxy<JsonDocument&> ep = doc[0]; ElementProxy ep = doc[0];
JsonVariant var = ep; JsonVariant var = ep;

View File

@ -7,9 +7,11 @@
using namespace ARDUINOJSON_NAMESPACE; using namespace ARDUINOJSON_NAMESPACE;
typedef VariantProxy<MemberDataSource<JsonDocument&, const char*> > MemberProxy;
TEST_CASE("MemberProxy::add()") { TEST_CASE("MemberProxy::add()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; MemberProxy mp = doc["hello"];
SECTION("add(int)") { SECTION("add(int)") {
mp.add(42); mp.add(42);
@ -26,7 +28,7 @@ TEST_CASE("MemberProxy::add()") {
TEST_CASE("MemberProxy::clear()") { TEST_CASE("MemberProxy::clear()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; MemberProxy mp = doc["hello"];
SECTION("size goes back to zero") { SECTION("size goes back to zero") {
mp.add(42); mp.add(42);
@ -85,7 +87,7 @@ TEST_CASE("MemberProxy::operator==()") {
TEST_CASE("MemberProxy::containsKey()") { TEST_CASE("MemberProxy::containsKey()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; MemberProxy mp = doc["hello"];
SECTION("containsKey(const char*)") { SECTION("containsKey(const char*)") {
mp["key"] = "value"; mp["key"] = "value";
@ -136,7 +138,7 @@ TEST_CASE("MemberProxy::operator|()") {
TEST_CASE("MemberProxy::remove()") { TEST_CASE("MemberProxy::remove()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; MemberProxy mp = doc["hello"];
SECTION("remove(int)") { SECTION("remove(int)") {
mp.add(1); mp.add(1);
@ -183,7 +185,7 @@ TEST_CASE("MemberProxy::remove()") {
TEST_CASE("MemberProxy::set()") { TEST_CASE("MemberProxy::set()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; MemberProxy mp = doc["hello"];
SECTION("set(int)") { SECTION("set(int)") {
mp.set(42); mp.set(42);
@ -208,7 +210,7 @@ TEST_CASE("MemberProxy::set()") {
TEST_CASE("MemberProxy::size()") { TEST_CASE("MemberProxy::size()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; MemberProxy mp = doc["hello"];
SECTION("returns 0") { SECTION("returns 0") {
REQUIRE(mp.size() == 0); REQUIRE(mp.size() == 0);
@ -231,7 +233,7 @@ TEST_CASE("MemberProxy::size()") {
TEST_CASE("MemberProxy::memoryUsage()") { TEST_CASE("MemberProxy::memoryUsage()") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; MemberProxy mp = doc["hello"];
SECTION("returns 0 when null") { SECTION("returns 0 when null") {
REQUIRE(mp.memoryUsage() == 0); REQUIRE(mp.memoryUsage() == 0);
@ -245,7 +247,7 @@ TEST_CASE("MemberProxy::memoryUsage()") {
TEST_CASE("MemberProxy::operator[]") { TEST_CASE("MemberProxy::operator[]") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; MemberProxy mp = doc["hello"];
SECTION("set member") { SECTION("set member") {
mp["world"] = 42; mp["world"] = 42;
@ -264,7 +266,7 @@ TEST_CASE("MemberProxy cast to JsonVariantConst") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
doc["hello"] = "world"; doc["hello"] = "world";
const MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; const MemberProxy mp = doc["hello"];
JsonVariantConst var = mp; JsonVariantConst var = mp;
@ -275,7 +277,7 @@ TEST_CASE("MemberProxy cast to JsonVariant") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
doc["hello"] = "world"; doc["hello"] = "world";
MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; MemberProxy mp = doc["hello"];
JsonVariant var = mp; JsonVariant var = mp;

View File

@ -184,11 +184,12 @@ TEST_CASE("Polyfills/type_traits") {
CHECK((is_convertible<VariantRef, JsonVariantConst>::value == true)); CHECK((is_convertible<VariantRef, JsonVariantConst>::value == true));
CHECK((is_convertible<VariantConstRef, JsonVariantConst>::value == true)); CHECK((is_convertible<VariantConstRef, JsonVariantConst>::value == true));
CHECK((is_convertible<ArrayRef, JsonVariantConst>::value == true)); CHECK((is_convertible<ArrayRef, JsonVariantConst>::value == true));
CHECK((is_convertible<ElementProxy<ArrayRef>, JsonVariantConst>::value == CHECK((is_convertible<VariantProxy<ElementDataSource<ArrayRef> >,
true)); JsonVariantConst>::value == true));
CHECK((is_convertible<ArrayConstRef, JsonVariantConst>::value == true)); CHECK((is_convertible<ArrayConstRef, JsonVariantConst>::value == true));
CHECK((is_convertible<ObjectRef, JsonVariantConst>::value == true)); CHECK((is_convertible<ObjectRef, JsonVariantConst>::value == true));
CHECK((is_convertible<MemberProxy<ObjectRef, const char*>, CHECK(
(is_convertible<VariantProxy<MemberDataSource<ObjectRef, const char*> >,
JsonVariantConst>::value == true)); JsonVariantConst>::value == true));
CHECK((is_convertible<ObjectConstRef, JsonVariantConst>::value == true)); CHECK((is_convertible<ObjectConstRef, JsonVariantConst>::value == true));
CHECK( CHECK(

View File

@ -20,9 +20,10 @@ inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
} }
template <typename TArray> template <typename TArray>
inline ElementProxy<TArray> ArrayShortcuts<TArray>::operator[]( inline VariantProxy<ElementDataSource<TArray> >
size_t index) const { ArrayShortcuts<TArray>::operator[](size_t index) const {
return ElementProxy<TArray>(*impl(), index); return VariantProxy<ElementDataSource<TArray> >(
ElementDataSource<TArray>(*impl(), index));
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@ -17,8 +17,6 @@
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class ObjectRef; class ObjectRef;
template <typename>
class ElementProxy;
template <typename TData> template <typename TData>
class ArrayRefBase { class ArrayRefBase {

View File

@ -11,14 +11,19 @@ namespace ARDUINOJSON_NAMESPACE {
// Forward declarations. // Forward declarations.
class ArrayRef; class ArrayRef;
class ObjectRef; class ObjectRef;
template <typename> template <typename>
class ElementProxy; class ElementDataSource;
template <typename>
class VariantProxy;
template <typename TArray> template <typename TArray>
class ArrayShortcuts { class ArrayShortcuts {
public: public:
// Returns the element at specified index if the variant is an array. // Returns the element at specified index if the variant is an array.
FORCE_INLINE ElementProxy<TArray> operator[](size_t index) const; FORCE_INLINE VariantProxy<ElementDataSource<TArray> > operator[](
size_t index) const;
FORCE_INLINE ObjectRef createNestedObject() const; FORCE_INLINE ObjectRef createNestedObject() const;

View File

@ -4,150 +4,16 @@
#pragma once #pragma once
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Variant/VariantProxy.hpp>
#include <ArduinoJson/Variant/VariantOperators.hpp>
#include <ArduinoJson/Variant/VariantShortcuts.hpp>
#include <ArduinoJson/Variant/VariantTo.hpp>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable : 4522)
#endif
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TUpstream> template <typename TUpstream>
class ElementProxy // class ElementDataSource {
: public VariantOperators<ElementProxy<TUpstream> >,
public VariantShortcuts<ElementProxy<TUpstream> >,
public VariantTag {
friend class VariantAttorney;
public: public:
FORCE_INLINE ElementProxy(TUpstream upstream, size_t index) ElementDataSource(TUpstream upstream, size_t index)
: _upstream(upstream), _index(index) {} : _upstream(upstream), _index(index) {}
FORCE_INLINE ElementProxy(const ElementProxy& src)
: _upstream(src._upstream), _index(src._index) {}
FORCE_INLINE ElementProxy& operator=(const ElementProxy& src) {
getOrAddUpstreamVariant().set(src);
return *this;
}
template <typename T>
FORCE_INLINE ElementProxy& operator=(const T& src) {
getOrAddUpstreamVariant().set(src);
return *this;
}
template <typename T>
FORCE_INLINE ElementProxy& operator=(T* src) {
getOrAddUpstreamVariant().set(src);
return *this;
}
FORCE_INLINE void clear() const {
getUpstreamVariant().clear();
}
FORCE_INLINE bool isNull() const {
return getUpstreamVariantConst().isNull();
}
template <typename T>
FORCE_INLINE typename enable_if<!is_same<T, char*>::value &&
!ConverterNeedsWriteableRef<T>::value,
T>::type
as() const {
return getUpstreamVariantConst().template as<T>();
}
template <typename T>
FORCE_INLINE typename enable_if<ConverterNeedsWriteableRef<T>::value, T>::type
as() const {
return getUpstreamVariant().template as<T>();
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char*>::value, const char*>::type
ARDUINOJSON_DEPRECATED("Replace as<char*>() with as<const char*>()")
as() const {
return as<const char*>();
}
template <typename T>
FORCE_INLINE operator T() const {
return as<T>();
}
template <typename T>
FORCE_INLINE typename VariantTo<T>::type to() {
return getOrAddUpstreamVariant().template to<T>();
}
template <typename T>
FORCE_INLINE
typename enable_if<ConverterNeedsWriteableRef<T>::value, bool>::type
is() const {
return getUpstreamVariant().template is<T>();
}
template <typename T>
FORCE_INLINE
typename enable_if<!ConverterNeedsWriteableRef<T>::value, bool>::type
is() const {
return getUpstreamVariantConst().template is<T>();
}
FORCE_INLINE void shallowCopy(VariantConstRef value) {
getOrAddUpstreamVariant().shallowCopy(value);
}
template <typename T>
FORCE_INLINE bool set(const T& value) {
return getOrAddUpstreamVariant().set(value);
}
template <typename T>
FORCE_INLINE bool set(T* value) {
return getOrAddUpstreamVariant().set(value);
}
FORCE_INLINE size_t size() const {
return getUpstreamVariantConst().size();
}
FORCE_INLINE size_t memoryUsage() const {
return getUpstreamVariantConst().memoryUsage();
}
FORCE_INLINE VariantRef add() const {
return getOrAddUpstreamVariant().add();
}
using ArrayShortcuts<ElementProxy<TUpstream> >::add;
FORCE_INLINE void remove(size_t index) const {
getUpstreamVariant().remove(index);
}
// remove(char*) const
// remove(const char*) const
// remove(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
TChar* key) const {
getUpstreamVariant().remove(key);
}
// remove(const std::string&) const
// remove(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString& key) const {
getUpstreamVariant().remove(key);
}
protected:
FORCE_INLINE MemoryPool* getPool() const { FORCE_INLINE MemoryPool* getPool() const {
return VariantAttorney::getPool(_upstream); return VariantAttorney::getPool(_upstream);
} }
@ -162,28 +28,13 @@ class ElementProxy //
} }
private: private:
FORCE_INLINE VariantRef getUpstreamVariant() const { #if defined _MSC_VER && _MSC_VER <= 1800 // Visual Studio 2013 or below
return VariantRef(getPool(), getData()); // Prevent "assignment operator could not be generated"
} ElementDataSource& operator=(const ElementDataSource&);
#endif
FORCE_INLINE VariantConstRef getUpstreamVariantConst() const {
return VariantConstRef(getData());
}
FORCE_INLINE VariantRef getOrAddUpstreamVariant() const {
return VariantRef(getPool(), getOrCreateData());
}
friend void convertToJson(const ElementProxy& src, VariantRef dst) {
dst.set(src.getUpstreamVariantConst());
}
TUpstream _upstream; TUpstream _upstream;
const size_t _index; size_t _index;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@ -9,15 +9,9 @@
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TArray> template <typename TSource>
struct Reader<ElementProxy<TArray>, void> : Reader<char*, void> { struct Reader<VariantProxy<TSource>, void> : Reader<char*, void> {
explicit Reader(const ElementProxy<TArray>& x) explicit Reader(const VariantProxy<TSource>& x)
: Reader<char*, void>(x.template as<const char*>()) {}
};
template <typename TObject, typename TStringRef>
struct Reader<MemberProxy<TObject, TStringRef>, void> : Reader<char*, void> {
explicit Reader(const MemberProxy<TObject, TStringRef>& x)
: Reader<char*, void>(x.template as<const char*>()) {} : Reader<char*, void>(x.template as<const char*>()) {}
}; };

View File

@ -139,20 +139,24 @@ class JsonDocument : public VariantOperators<const JsonDocument&> {
// operator[](const std::string&) // operator[](const std::string&)
// operator[](const String&) // operator[](const String&)
template <typename TString> template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, FORCE_INLINE typename enable_if<
MemberProxy<JsonDocument&, TString> >::type IsString<TString>::value,
VariantProxy<MemberDataSource<JsonDocument&, TString> > >::type
operator[](const TString& key) { operator[](const TString& key) {
return MemberProxy<JsonDocument&, TString>(*this, key); return VariantProxy<MemberDataSource<JsonDocument&, TString> >(
MemberDataSource<JsonDocument&, TString>(*this, key));
} }
// operator[](char*) // operator[](char*)
// operator[](const char*) // operator[](const char*)
// operator[](const __FlashStringHelper*) // operator[](const __FlashStringHelper*)
template <typename TChar> template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value, FORCE_INLINE typename enable_if<
MemberProxy<JsonDocument&, TChar*> >::type IsString<TChar*>::value,
VariantProxy<MemberDataSource<JsonDocument&, TChar*> > >::type
operator[](TChar* key) { operator[](TChar* key) {
return MemberProxy<JsonDocument&, TChar*>(*this, key); return VariantProxy<MemberDataSource<JsonDocument&, TChar*> >(
MemberDataSource<JsonDocument&, TChar*>(*this, key));
} }
// operator[](const std::string&) const // operator[](const std::string&) const
@ -174,8 +178,10 @@ class JsonDocument : public VariantOperators<const JsonDocument&> {
return VariantConstRef(_data.getMember(adaptString(key))); return VariantConstRef(_data.getMember(adaptString(key)));
} }
FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) { FORCE_INLINE VariantProxy<ElementDataSource<JsonDocument&> > operator[](
return ElementProxy<JsonDocument&>(*this, index); size_t index) {
return VariantProxy<ElementDataSource<JsonDocument&> >(
ElementDataSource<JsonDocument&>(*this, index));
} }
FORCE_INLINE VariantConstRef operator[](size_t index) const { FORCE_INLINE VariantConstRef operator[](size_t index) const {

View File

@ -4,153 +4,16 @@
#pragma once #pragma once
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Variant/VariantProxy.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Variant/Converter.hpp>
#include <ArduinoJson/Variant/VariantOperators.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp>
#include <ArduinoJson/Variant/VariantShortcuts.hpp>
#include <ArduinoJson/Variant/VariantTo.hpp>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable : 4522)
#endif
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TUpstream, typename TStringRef> template <typename TUpstream, typename TStringRef>
class MemberProxy // class MemberDataSource {
: public VariantOperators<MemberProxy<TUpstream, TStringRef> >,
public VariantShortcuts<MemberProxy<TUpstream, TStringRef> >,
public VariantTag {
friend class VariantAttorney;
public: public:
FORCE_INLINE MemberProxy(TUpstream upstream, TStringRef key) FORCE_INLINE MemberDataSource(TUpstream upstream, TStringRef key)
: _upstream(upstream), _key(key) {} : _upstream(upstream), _key(key) {}
FORCE_INLINE MemberProxy(const MemberProxy& src)
: _upstream(src._upstream), _key(src._key) {}
FORCE_INLINE MemberProxy& operator=(const MemberProxy& src) {
getOrAddUpstreamVariant().set(src);
return *this;
}
template <typename T>
FORCE_INLINE MemberProxy& operator=(const T& src) {
getOrAddUpstreamVariant().set(src);
return *this;
}
template <typename T>
FORCE_INLINE MemberProxy& operator=(T* src) {
getOrAddUpstreamVariant().set(src);
return *this;
}
FORCE_INLINE void clear() const {
getUpstreamVariant().clear();
}
FORCE_INLINE bool isNull() const {
return getUpstreamVariantConst().isNull();
}
template <typename T>
FORCE_INLINE typename enable_if<!is_same<T, char*>::value &&
!ConverterNeedsWriteableRef<T>::value,
T>::type
as() const {
return getUpstreamVariantConst().template as<T>();
}
template <typename T>
FORCE_INLINE typename enable_if<ConverterNeedsWriteableRef<T>::value, T>::type
as() const {
return getUpstreamVariant().template as<T>();
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char*>::value, const char*>::type
ARDUINOJSON_DEPRECATED("Replace as<char*>() with as<const char*>()")
as() const {
return as<const char*>();
}
template <typename T>
FORCE_INLINE operator T() const {
return as<T>();
}
template <typename T>
FORCE_INLINE typename VariantTo<T>::type to() {
return getOrAddUpstreamVariant().template to<T>();
}
template <typename T>
FORCE_INLINE
typename enable_if<ConverterNeedsWriteableRef<T>::value, bool>::type
is() const {
return getUpstreamVariant().template is<T>();
}
template <typename T>
FORCE_INLINE
typename enable_if<!ConverterNeedsWriteableRef<T>::value, bool>::type
is() const {
return getUpstreamVariantConst().template is<T>();
}
FORCE_INLINE void shallowCopy(VariantConstRef value) {
getOrAddUpstreamVariant().shallowCopy(value);
}
template <typename T>
FORCE_INLINE bool set(const T& value) {
return getOrAddUpstreamVariant().set(value);
}
template <typename T>
FORCE_INLINE bool set(T* value) {
return getOrAddUpstreamVariant().set(value);
}
FORCE_INLINE size_t size() const {
return getUpstreamVariantConst().size();
}
FORCE_INLINE size_t memoryUsage() const {
return getUpstreamVariantConst().memoryUsage();
}
FORCE_INLINE VariantRef add() const {
return getOrAddUpstreamVariant().add();
}
using ArrayShortcuts<MemberProxy<TUpstream, TStringRef> >::add;
FORCE_INLINE void remove(size_t index) const {
getUpstreamVariant().remove(index);
}
// remove(char*) const
// remove(const char*) const
// remove(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
TChar* key) const {
getUpstreamVariant().remove(key);
}
// remove(const std::string&) const
// remove(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString& key) const {
getUpstreamVariant().remove(key);
}
protected:
FORCE_INLINE MemoryPool* getPool() const { FORCE_INLINE MemoryPool* getPool() const {
return VariantAttorney::getPool(_upstream); return VariantAttorney::getPool(_upstream);
} }
@ -166,28 +29,13 @@ class MemberProxy //
} }
private: private:
FORCE_INLINE VariantRef getUpstreamVariant() const { #if defined _MSC_VER && _MSC_VER <= 1800 // Visual Studio 2013 or below
return VariantRef(getPool(), getData()); // Prevent "assignment operator could not be generated"
} MemberDataSource& operator=(const MemberDataSource&);
#endif
FORCE_INLINE VariantConstRef getUpstreamVariantConst() const {
return VariantConstRef(getData());
}
FORCE_INLINE VariantRef getOrAddUpstreamVariant() const {
return VariantRef(getPool(), getOrCreateData());
}
friend void convertToJson(const MemberProxy& src, VariantRef dst) {
dst.set(src.getUpstreamVariantConst());
}
TUpstream _upstream; TUpstream _upstream;
TStringRef _key; TStringRef _key;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@ -54,18 +54,22 @@ ObjectShortcuts<TObject>::containsKey(TChar* key) const {
template <typename TObject> template <typename TObject>
template <typename TString> template <typename TString>
inline typename enable_if<IsString<TString*>::value, inline typename enable_if<
MemberProxy<TObject, TString*> >::type IsString<TString*>::value,
VariantProxy<MemberDataSource<TObject, TString*> > >::type
ObjectShortcuts<TObject>::operator[](TString* key) const { ObjectShortcuts<TObject>::operator[](TString* key) const {
return MemberProxy<TObject, TString*>(*impl(), key); return VariantProxy<MemberDataSource<TObject, TString*> >(
MemberDataSource<TObject, TString*>(*impl(), key));
} }
template <typename TObject> template <typename TObject>
template <typename TString> template <typename TString>
inline typename enable_if<IsString<TString>::value, inline
MemberProxy<TObject, TString> >::type typename enable_if<IsString<TString>::value,
VariantProxy<MemberDataSource<TObject, TString> > >::type
ObjectShortcuts<TObject>::operator[](const TString& key) const { ObjectShortcuts<TObject>::operator[](const TString& key) const {
return MemberProxy<TObject, TString>(*impl(), key); return VariantProxy<MemberDataSource<TObject, TString> >(
MemberDataSource<TObject, TString>(*impl(), key));
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@ -9,8 +9,11 @@
#include <ArduinoJson/Strings/StringAdapters.hpp> #include <ArduinoJson/Strings/StringAdapters.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TSource>
class VariantProxy;
template <typename TParent, typename TStringRef> template <typename TParent, typename TStringRef>
class MemberProxy; class MemberDataSource;
template <typename TObject> template <typename TObject>
class ObjectShortcuts { class ObjectShortcuts {
@ -31,16 +34,18 @@ class ObjectShortcuts {
// operator[](const std::string&) const // operator[](const std::string&) const
// operator[](const String&) const // operator[](const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, FORCE_INLINE typename enable_if<
MemberProxy<TObject, TString> >::type IsString<TString>::value,
VariantProxy<MemberDataSource<TObject, TString> > >::type
operator[](const TString& key) const; operator[](const TString& key) const;
// operator[](char*) const // operator[](char*) const
// operator[](const char*) const // operator[](const char*) const
// operator[](const __FlashStringHelper*) const // operator[](const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value, FORCE_INLINE typename enable_if<
MemberProxy<TObject, TChar*> >::type IsString<TChar*>::value,
VariantProxy<MemberDataSource<TObject, TChar*> > >::type
operator[](TChar* key) const; operator[](TChar* key) const;
// createNestedArray(const std::string&) const // createNestedArray(const std::string&) const

View File

@ -0,0 +1,185 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Variant/VariantOperators.hpp>
#include <ArduinoJson/Variant/VariantShortcuts.hpp>
#include <ArduinoJson/Variant/VariantTo.hpp>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable : 4522)
#endif
namespace ARDUINOJSON_NAMESPACE {
template <typename TDataSource>
class VariantProxy : public VariantShortcuts<VariantProxy<TDataSource> >,
public VariantOperators<VariantProxy<TDataSource> >,
public VariantTag {
friend class VariantAttorney;
public:
explicit FORCE_INLINE VariantProxy(TDataSource source) : _source(source) {}
// Copy-constructor required because of user-defined copy-assignment operator
FORCE_INLINE VariantProxy(const VariantProxy& src) : _source(src._source) {}
FORCE_INLINE VariantProxy& operator=(const VariantProxy& src) {
getOrAddUpstreamVariant().set(src);
return *this;
}
template <typename T>
FORCE_INLINE VariantProxy& operator=(const T& src) {
getOrAddUpstreamVariant().set(src);
return *this;
}
template <typename T>
FORCE_INLINE VariantProxy& operator=(T* src) {
getOrAddUpstreamVariant().set(src);
return *this;
}
FORCE_INLINE void clear() const {
getUpstreamVariant().clear();
}
FORCE_INLINE bool isNull() const {
return getUpstreamVariantConst().isNull();
}
template <typename T>
FORCE_INLINE typename enable_if<!is_same<T, char*>::value &&
!ConverterNeedsWriteableRef<T>::value,
T>::type
as() const {
return getUpstreamVariantConst().template as<T>();
}
template <typename T>
FORCE_INLINE typename enable_if<ConverterNeedsWriteableRef<T>::value, T>::type
as() const {
return getUpstreamVariant().template as<T>();
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char*>::value, const char*>::type
ARDUINOJSON_DEPRECATED("Replace as<char*>() with as<const char*>()")
as() const {
return as<const char*>();
}
template <typename T>
FORCE_INLINE operator T() const {
return as<T>();
}
template <typename T>
FORCE_INLINE typename VariantTo<T>::type to() {
return getOrAddUpstreamVariant().template to<T>();
}
template <typename T>
FORCE_INLINE
typename enable_if<ConverterNeedsWriteableRef<T>::value, bool>::type
is() const {
return getUpstreamVariant().template is<T>();
}
template <typename T>
FORCE_INLINE
typename enable_if<!ConverterNeedsWriteableRef<T>::value, bool>::type
is() const {
return getUpstreamVariantConst().template is<T>();
}
FORCE_INLINE void shallowCopy(VariantConstRef value) {
getOrAddUpstreamVariant().shallowCopy(value);
}
template <typename T>
FORCE_INLINE bool set(const T& value) {
return getOrAddUpstreamVariant().set(value);
}
template <typename T>
FORCE_INLINE bool set(T* value) {
return getOrAddUpstreamVariant().set(value);
}
FORCE_INLINE size_t size() const {
return getUpstreamVariantConst().size();
}
FORCE_INLINE size_t memoryUsage() const {
return getUpstreamVariantConst().memoryUsage();
}
FORCE_INLINE VariantRef add() const {
return getOrAddUpstreamVariant().add();
}
using ArrayShortcuts<VariantProxy<TDataSource> >::add;
FORCE_INLINE void remove(size_t index) const {
getUpstreamVariant().remove(index);
}
// remove(char*) const
// remove(const char*) const
// remove(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
TChar* key) const {
getUpstreamVariant().remove(key);
}
// remove(const std::string&) const
// remove(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString& key) const {
getUpstreamVariant().remove(key);
}
protected:
FORCE_INLINE MemoryPool* getPool() const {
return _source.getPool();
}
FORCE_INLINE VariantData* getData() const {
return _source.getData();
}
FORCE_INLINE VariantData* getOrCreateData() const {
return _source.getOrCreateData();
}
private:
FORCE_INLINE VariantRef getUpstreamVariant() const {
return VariantRef(getPool(), getData());
}
FORCE_INLINE VariantConstRef getUpstreamVariantConst() const {
return VariantConstRef(getData());
}
FORCE_INLINE VariantRef getOrAddUpstreamVariant() const {
return VariantRef(getPool(), getOrCreateData());
}
friend void convertToJson(const VariantProxy& src, VariantRef dst) {
dst.set(src.getUpstreamVariantConst());
}
const TDataSource _source;
};
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
# pragma warning(pop)
#endif