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

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

View File

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

View File

@ -11,14 +11,19 @@ namespace ARDUINOJSON_NAMESPACE {
// Forward declarations.
class ArrayRef;
class ObjectRef;
template <typename>
class ElementProxy;
class ElementDataSource;
template <typename>
class VariantProxy;
template <typename TArray>
class ArrayShortcuts {
public:
// 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;

View File

@ -4,150 +4,16 @@
#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
#include <ArduinoJson/Variant/VariantProxy.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TUpstream>
class ElementProxy //
: public VariantOperators<ElementProxy<TUpstream> >,
public VariantShortcuts<ElementProxy<TUpstream> >,
public VariantTag {
friend class VariantAttorney;
class ElementDataSource {
public:
FORCE_INLINE ElementProxy(TUpstream upstream, size_t index)
ElementDataSource(TUpstream upstream, size_t 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 {
return VariantAttorney::getPool(_upstream);
}
@ -162,28 +28,13 @@ class ElementProxy //
}
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 ElementProxy& src, VariantRef dst) {
dst.set(src.getUpstreamVariantConst());
}
#if defined _MSC_VER && _MSC_VER <= 1800 // Visual Studio 2013 or below
// Prevent "assignment operator could not be generated"
ElementDataSource& operator=(const ElementDataSource&);
#endif
TUpstream _upstream;
const size_t _index;
size_t _index;
};
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@ -9,15 +9,9 @@
namespace ARDUINOJSON_NAMESPACE {
template <typename TArray>
struct Reader<ElementProxy<TArray>, void> : Reader<char*, void> {
explicit Reader(const ElementProxy<TArray>& 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)
template <typename TSource>
struct Reader<VariantProxy<TSource>, void> : Reader<char*, void> {
explicit Reader(const VariantProxy<TSource>& x)
: 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 String&)
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value,
MemberProxy<JsonDocument&, TString> >::type
FORCE_INLINE typename enable_if<
IsString<TString>::value,
VariantProxy<MemberDataSource<JsonDocument&, TString> > >::type
operator[](const TString& key) {
return MemberProxy<JsonDocument&, TString>(*this, key);
return VariantProxy<MemberDataSource<JsonDocument&, TString> >(
MemberDataSource<JsonDocument&, TString>(*this, key));
}
// operator[](char*)
// operator[](const char*)
// operator[](const __FlashStringHelper*)
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
MemberProxy<JsonDocument&, TChar*> >::type
FORCE_INLINE typename enable_if<
IsString<TChar*>::value,
VariantProxy<MemberDataSource<JsonDocument&, TChar*> > >::type
operator[](TChar* key) {
return MemberProxy<JsonDocument&, TChar*>(*this, key);
return VariantProxy<MemberDataSource<JsonDocument&, TChar*> >(
MemberDataSource<JsonDocument&, TChar*>(*this, key));
}
// operator[](const std::string&) const
@ -174,8 +178,10 @@ class JsonDocument : public VariantOperators<const JsonDocument&> {
return VariantConstRef(_data.getMember(adaptString(key)));
}
FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) {
return ElementProxy<JsonDocument&>(*this, index);
FORCE_INLINE VariantProxy<ElementDataSource<JsonDocument&> > operator[](
size_t index) {
return VariantProxy<ElementDataSource<JsonDocument&> >(
ElementDataSource<JsonDocument&>(*this, index));
}
FORCE_INLINE VariantConstRef operator[](size_t index) const {

View File

@ -4,153 +4,16 @@
#pragma once
#include <ArduinoJson/Configuration.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
#include <ArduinoJson/Variant/VariantProxy.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TUpstream, typename TStringRef>
class MemberProxy //
: public VariantOperators<MemberProxy<TUpstream, TStringRef> >,
public VariantShortcuts<MemberProxy<TUpstream, TStringRef> >,
public VariantTag {
friend class VariantAttorney;
class MemberDataSource {
public:
FORCE_INLINE MemberProxy(TUpstream upstream, TStringRef key)
FORCE_INLINE MemberDataSource(TUpstream upstream, TStringRef 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 {
return VariantAttorney::getPool(_upstream);
}
@ -166,28 +29,13 @@ class MemberProxy //
}
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 MemberProxy& src, VariantRef dst) {
dst.set(src.getUpstreamVariantConst());
}
#if defined _MSC_VER && _MSC_VER <= 1800 // Visual Studio 2013 or below
// Prevent "assignment operator could not be generated"
MemberDataSource& operator=(const MemberDataSource&);
#endif
TUpstream _upstream;
TStringRef _key;
};
} // 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 TString>
inline typename enable_if<IsString<TString*>::value,
MemberProxy<TObject, TString*> >::type
inline typename enable_if<
IsString<TString*>::value,
VariantProxy<MemberDataSource<TObject, TString*> > >::type
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 TString>
inline typename enable_if<IsString<TString>::value,
MemberProxy<TObject, TString> >::type
ObjectShortcuts<TObject>::operator[](const TString& key) const {
return MemberProxy<TObject, TString>(*impl(), key);
inline
typename enable_if<IsString<TString>::value,
VariantProxy<MemberDataSource<TObject, TString> > >::type
ObjectShortcuts<TObject>::operator[](const TString& key) const {
return VariantProxy<MemberDataSource<TObject, TString> >(
MemberDataSource<TObject, TString>(*impl(), key));
}
} // namespace ARDUINOJSON_NAMESPACE

View File

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