From c4d487b6cfa5f25ba56d91717a6dcdfd34eca3f4 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Thu, 31 Mar 2022 11:59:00 +0200 Subject: [PATCH] Add getMemberConst() and getElementConst() (6780,5602) --- extras/tests/JsonVariant/subscript.cpp | 3 +- src/ArduinoJson/Array/ArrayRef.hpp | 9 ++++- src/ArduinoJson/Array/ElementProxy.hpp | 32 ++++++++++++++-- src/ArduinoJson/Document/JsonDocument.hpp | 26 ++++++------- src/ArduinoJson/Object/MemberProxy.hpp | 38 +++++++++++++++++-- src/ArduinoJson/Object/ObjectImpl.hpp | 4 +- src/ArduinoJson/Object/ObjectRef.hpp | 45 ++++++++++++++--------- src/ArduinoJson/Variant/Converter.hpp | 3 ++ src/ArduinoJson/Variant/VariantImpl.hpp | 29 +++++++++++---- src/ArduinoJson/Variant/VariantRef.hpp | 34 ++++++++++++----- 10 files changed, 164 insertions(+), 59 deletions(-) diff --git a/extras/tests/JsonVariant/subscript.cpp b/extras/tests/JsonVariant/subscript.cpp index a1bba08c..a6172e63 100644 --- a/extras/tests/JsonVariant/subscript.cpp +++ b/extras/tests/JsonVariant/subscript.cpp @@ -154,7 +154,8 @@ TEST_CASE("JsonVariant::operator[]") { doc2.add(42); var.link(doc2); - CHECK(var[0].as() == 42); + bool ok = var[0].as() == 42; + CHECK(ok); } SECTION("set value to linked array") { diff --git a/src/ArduinoJson/Array/ArrayRef.hpp b/src/ArduinoJson/Array/ArrayRef.hpp index 99b4e22b..8ec2cf8f 100644 --- a/src/ArduinoJson/Array/ArrayRef.hpp +++ b/src/ArduinoJson/Array/ArrayRef.hpp @@ -87,10 +87,10 @@ class ArrayConstRef : public ArrayRefBase, } FORCE_INLINE VariantConstRef operator[](size_t index) const { - return getElement(index); + return getElementConst(index); } - FORCE_INLINE VariantConstRef getElement(size_t index) const { + FORCE_INLINE VariantConstRef getElementConst(size_t index) const { return VariantConstRef(_data ? _data->getElement(index) : 0); } }; @@ -151,6 +151,11 @@ class ArrayRef : public ArrayRefBase, return VariantRef(_pool, _data ? _data->getElement(index) : 0); } + // Gets the value at the specified index. + FORCE_INLINE VariantConstRef getElementConst(size_t index) const { + return VariantConstRef(_data ? _data->getElement(index) : 0); + } + // Removes element at specified position. FORCE_INLINE void remove(iterator it) const { if (!_data) diff --git a/src/ArduinoJson/Array/ElementProxy.hpp b/src/ArduinoJson/Array/ElementProxy.hpp index 07566551..33e73786 100644 --- a/src/ArduinoJson/Array/ElementProxy.hpp +++ b/src/ArduinoJson/Array/ElementProxy.hpp @@ -65,8 +65,16 @@ class ElementProxy : public VariantOperators >, } template - FORCE_INLINE typename enable_if::value, T>::type as() - const { + FORCE_INLINE typename enable_if::value && + !ConverterNeedsWriteableRef::value, + T>::type + as() const { + return getUpstreamElementConst().template as(); + } + + template + FORCE_INLINE typename enable_if::value, T>::type + as() const { return getUpstreamElement().template as(); } @@ -115,7 +123,7 @@ class ElementProxy : public VariantOperators >, template typename TVisitor::result_type accept(TVisitor& visitor) const { - return getUpstreamElement().accept(visitor); + return getUpstreamElementConst().accept(visitor); } FORCE_INLINE size_t size() const { @@ -136,6 +144,16 @@ class ElementProxy : public VariantOperators >, return getUpstreamElement().getMember(key); } + template + VariantConstRef getMemberConst(TNestedKey* key) const { + return getUpstreamElementConst().getMemberConst(key); + } + + template + VariantConstRef getMemberConst(const TNestedKey& key) const { + return getUpstreamElementConst().getMemberConst(key); + } + template VariantRef getOrAddMember(TNestedKey* key) const { return getOrAddUpstreamElement().getOrAddMember(key); @@ -154,6 +172,10 @@ class ElementProxy : public VariantOperators >, return getOrAddUpstreamElement().getElement(index); } + VariantConstRef getElementConst(size_t index) const { + return getUpstreamElementConst().getElementConst(index); + } + VariantRef getOrAddElement(size_t index) const { return getOrAddUpstreamElement().getOrAddElement(index); } @@ -182,6 +204,10 @@ class ElementProxy : public VariantOperators >, return _array.getElement(_index); } + FORCE_INLINE VariantConstRef getUpstreamElementConst() const { + return _array.getElementConst(_index); + } + FORCE_INLINE VariantRef getOrAddUpstreamElement() const { return _array.getOrAddElement(_index); } diff --git a/src/ArduinoJson/Document/JsonDocument.hpp b/src/ArduinoJson/Document/JsonDocument.hpp index 62d53030..9f0892a3 100644 --- a/src/ArduinoJson/Document/JsonDocument.hpp +++ b/src/ArduinoJson/Document/JsonDocument.hpp @@ -140,14 +140,14 @@ class JsonDocument : public Visitable, // containsKey(const __FlashStringHelper*) const template bool containsKey(TChar* key) const { - return !getMember(key).isUnbound(); + return !getMemberConst(key).isUnbound(); } // containsKey(const std::string&) const // containsKey(const String&) const template bool containsKey(const TString& key) const { - return !getMember(key).isUnbound(); + return !getMemberConst(key).isUnbound(); } // operator[](const std::string&) @@ -175,7 +175,7 @@ class JsonDocument : public Visitable, FORCE_INLINE typename enable_if::value, VariantConstRef>::type operator[](const TString& key) const { - return getMember(key); + return getMemberConst(key); } // operator[](char*) const @@ -185,7 +185,7 @@ class JsonDocument : public Visitable, FORCE_INLINE typename enable_if::value, VariantConstRef>::type operator[](TChar* key) const { - return getMember(key); + return getMemberConst(key); } FORCE_INLINE ElementProxy operator[](size_t index) { @@ -193,14 +193,14 @@ class JsonDocument : public Visitable, } FORCE_INLINE VariantConstRef operator[](size_t index) const { - return getElement(index); + return getElementConst(index); } FORCE_INLINE VariantRef getElement(size_t index) { return VariantRef(&_pool, _data.getElement(index)); } - FORCE_INLINE VariantConstRef getElement(size_t index) const { + FORCE_INLINE VariantConstRef getElementConst(size_t index) const { return VariantConstRef(_data.getElement(index)); } @@ -208,20 +208,20 @@ class JsonDocument : public Visitable, return VariantRef(&_pool, _data.getOrAddElement(index, &_pool)); } - // JsonVariantConst getMember(char*) const - // JsonVariantConst getMember(const char*) const - // JsonVariantConst getMember(const __FlashStringHelper*) const + // JsonVariantConst getMemberConst(char*) const + // JsonVariantConst getMemberConst(const char*) const + // JsonVariantConst getMemberConst(const __FlashStringHelper*) const template - FORCE_INLINE VariantConstRef getMember(TChar* key) const { + FORCE_INLINE VariantConstRef getMemberConst(TChar* key) const { return VariantConstRef(_data.getMember(adaptString(key))); } - // JsonVariantConst getMember(const std::string&) const - // JsonVariantConst getMember(const String&) const + // JsonVariantConst getMemberConst(const std::string&) const + // JsonVariantConst getMemberConst(const String&) const template FORCE_INLINE typename enable_if::value, VariantConstRef>::type - getMember(const TString& key) const { + getMemberConst(const TString& key) const { return VariantConstRef(_data.getMember(adaptString(key))); } diff --git a/src/ArduinoJson/Object/MemberProxy.hpp b/src/ArduinoJson/Object/MemberProxy.hpp index 8275c186..4419c3a0 100644 --- a/src/ArduinoJson/Object/MemberProxy.hpp +++ b/src/ArduinoJson/Object/MemberProxy.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -68,8 +69,16 @@ class MemberProxy : public VariantOperators >, } template - FORCE_INLINE typename enable_if::value, T>::type as() - const { + FORCE_INLINE typename enable_if::value && + !ConverterNeedsWriteableRef::value, + T>::type + as() const { + return getUpstreamMemberConst().template as(); + } + + template + FORCE_INLINE typename enable_if::value, T>::type + as() const { return getUpstreamMember().template as(); } @@ -141,7 +150,7 @@ class MemberProxy : public VariantOperators >, template typename TVisitor::result_type accept(TVisitor &visitor) const { - return getUpstreamMember().accept(visitor); + return getUpstreamMemberConst().accept(visitor); } FORCE_INLINE VariantRef addElement() const { @@ -152,6 +161,10 @@ class MemberProxy : public VariantOperators >, return getUpstreamMember().getElement(index); } + FORCE_INLINE VariantConstRef getElementConst(size_t index) const { + return getUpstreamMemberConst().getElementConst(index); + } + FORCE_INLINE VariantRef getOrAddElement(size_t index) const { return getOrAddUpstreamMember().getOrAddElement(index); } @@ -171,6 +184,21 @@ class MemberProxy : public VariantOperators >, return getUpstreamMember().getMember(key); } + // getMemberConst(char*) const + // getMemberConst(const char*) const + // getMemberConst(const __FlashStringHelper*) const + template + FORCE_INLINE VariantConstRef getMemberConst(TChar *key) const { + return getUpstreamMember().getMemberConst(key); + } + + // getMemberConst(const std::string&) const + // getMemberConst(const String&) const + template + FORCE_INLINE VariantConstRef getMemberConst(const TString &key) const { + return getUpstreamMember().getMemberConst(key); + } + // getOrAddMember(char*) const // getOrAddMember(const char*) const // getOrAddMember(const __FlashStringHelper*) const @@ -191,6 +219,10 @@ class MemberProxy : public VariantOperators >, return _object.getMember(_key); } + FORCE_INLINE VariantConstRef getUpstreamMemberConst() const { + return _object.getMemberConst(_key); + } + FORCE_INLINE VariantRef getOrAddUpstreamMember() const { return _object.getOrAddMember(_key); } diff --git a/src/ArduinoJson/Object/ObjectImpl.hpp b/src/ArduinoJson/Object/ObjectImpl.hpp index 66793a77..ba327628 100644 --- a/src/ArduinoJson/Object/ObjectImpl.hpp +++ b/src/ArduinoJson/Object/ObjectImpl.hpp @@ -40,14 +40,14 @@ template template inline typename enable_if::value, bool>::type ObjectShortcuts::containsKey(const TString& key) const { - return !impl()->getMember(key).isUnbound(); + return !impl()->getMemberConst(key).isUnbound(); } template template inline typename enable_if::value, bool>::type ObjectShortcuts::containsKey(TChar* key) const { - return !impl()->getMember(key).isUnbound(); + return !impl()->getMemberConst(key).isUnbound(); } template diff --git a/src/ArduinoJson/Object/ObjectRef.hpp b/src/ArduinoJson/Object/ObjectRef.hpp index 2d11bfbb..a278f016 100644 --- a/src/ArduinoJson/Object/ObjectRef.hpp +++ b/src/ArduinoJson/Object/ObjectRef.hpp @@ -81,7 +81,7 @@ class ObjectConstRef : public ObjectRefBase, // containsKey(const String&) const template FORCE_INLINE bool containsKey(const TString& key) const { - return !getMember(key).isUnbound(); + return !getMemberConst(key).isUnbound(); } // containsKey(char*) const @@ -89,22 +89,22 @@ class ObjectConstRef : public ObjectRefBase, // containsKey(const __FlashStringHelper*) const template FORCE_INLINE bool containsKey(TChar* key) const { - return !getMember(key).isUnbound(); + return !getMemberConst(key).isUnbound(); } - // getMember(const std::string&) const - // getMember(const String&) const + // getMemberConst(const std::string&) const + // getMemberConst(const String&) const template - FORCE_INLINE VariantConstRef getMember(const TString& key) const { - return get_impl(adaptString(key)); + FORCE_INLINE VariantConstRef getMemberConst(const TString& key) const { + return VariantConstRef(objectGetMember(_data, adaptString(key))); } - // getMember(char*) const - // getMember(const char*) const - // getMember(const __FlashStringHelper*) const + // getMemberConst(char*) const + // getMemberConst(const char*) const + // getMemberConst(const __FlashStringHelper*) const template - FORCE_INLINE VariantConstRef getMember(TChar* key) const { - return get_impl(adaptString(key)); + FORCE_INLINE VariantConstRef getMemberConst(TChar* key) const { + return VariantConstRef(objectGetMember(_data, adaptString(key))); } // operator[](const std::string&) const @@ -113,7 +113,7 @@ class ObjectConstRef : public ObjectRefBase, FORCE_INLINE typename enable_if::value, VariantConstRef>::type operator[](const TString& key) const { - return get_impl(adaptString(key)); + return getMemberConst(key); } // operator[](char*) const @@ -123,7 +123,7 @@ class ObjectConstRef : public ObjectRefBase, FORCE_INLINE typename enable_if::value, VariantConstRef>::type operator[](TChar* key) const { - return get_impl(adaptString(key)); + return getMemberConst(key); } FORCE_INLINE bool operator==(ObjectConstRef rhs) const { @@ -131,10 +131,6 @@ class ObjectConstRef : public ObjectRefBase, } private: - template - FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const { - return VariantConstRef(objectGetMember(_data, key)); - } }; class ObjectRef : public ObjectRefBase, @@ -195,6 +191,21 @@ class ObjectRef : public ObjectRefBase, return VariantRef(_pool, objectGetMember(_data, adaptString(key))); } + // getMemberConst(const std::string&) const + // getMemberConst(const String&) const + template + FORCE_INLINE VariantConstRef getMemberConst(const TString& key) const { + return VariantConstRef(objectGetMember(_data, adaptString(key))); + } + + // getMemberConst(char*) const + // getMemberConst(const char*) const + // getMemberConst(const __FlashStringHelper*) const + template + FORCE_INLINE VariantConstRef getMemberConst(TChar* key) const { + return VariantConstRef(objectGetMember(_data, adaptString(key))); + } + // getOrAddMember(const std::string&) const // getOrAddMember(const String&) const template diff --git a/src/ArduinoJson/Variant/Converter.hpp b/src/ArduinoJson/Variant/Converter.hpp index f9ce9ab7..72f9dfd4 100644 --- a/src/ArduinoJson/Variant/Converter.hpp +++ b/src/ArduinoJson/Variant/Converter.hpp @@ -14,4 +14,7 @@ template class InvalidConversion; // Error here? See https://arduinojson.org/v6/invalid-conversion/ // clang-format on +template +struct ConverterNeedsWriteableRef; + } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Variant/VariantImpl.hpp b/src/ArduinoJson/Variant/VariantImpl.hpp index 9be59a74..31a5db34 100644 --- a/src/ArduinoJson/Variant/VariantImpl.hpp +++ b/src/ArduinoJson/Variant/VariantImpl.hpp @@ -124,7 +124,7 @@ VariantRef::to() const { return *this; } -inline VariantConstRef VariantConstRef::getElement(size_t index) const { +inline VariantConstRef VariantConstRef::getElementConst(size_t index) const { return ArrayConstRef(_data != 0 ? _data->resolve()->asArray() : 0)[index]; } @@ -133,8 +133,11 @@ inline VariantRef VariantRef::addElement() const { } inline VariantRef VariantRef::getElement(size_t index) const { - return VariantRef(_pool, - _data != 0 ? _data->resolve()->getElement(index) : 0); + return VariantRef(_pool, _data != 0 ? _data->getElement(index) : 0); +} + +inline VariantConstRef VariantRef::getElementConst(size_t index) const { + return VariantConstRef(_data != 0 ? _data->resolve()->getElement(index) : 0); } inline VariantRef VariantRef::getOrAddElement(size_t index) const { @@ -143,16 +146,26 @@ inline VariantRef VariantRef::getOrAddElement(size_t index) const { template inline VariantRef VariantRef::getMember(TChar *key) const { - return VariantRef( // TODO: this returns a mutable reference to a linked - // object - _pool, _data != 0 ? _data->resolve()->getMember(adaptString(key)) : 0); + return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0); } template inline typename enable_if::value, VariantRef>::type VariantRef::getMember(const TString &key) const { - return VariantRef( // TODO: idem - _pool, _data != 0 ? _data->resolve()->getMember(adaptString(key)) : 0); + return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0); +} + +template +inline VariantConstRef VariantRef::getMemberConst(TChar *key) const { + return VariantConstRef( + _data != 0 ? _data->resolve()->getMember(adaptString(key)) : 0); +} + +template +inline typename enable_if::value, VariantConstRef>::type +VariantRef::getMemberConst(const TString &key) const { + return VariantConstRef( + _data != 0 ? _data->resolve()->getMember(adaptString(key)) : 0); } template diff --git a/src/ArduinoJson/Variant/VariantRef.hpp b/src/ArduinoJson/Variant/VariantRef.hpp index bfed6134..bb6a0d12 100644 --- a/src/ArduinoJson/Variant/VariantRef.hpp +++ b/src/ArduinoJson/Variant/VariantRef.hpp @@ -174,6 +174,8 @@ class VariantRef : public VariantRefBase, FORCE_INLINE VariantRef getElement(size_t) const; + FORCE_INLINE class VariantConstRef getElementConst(size_t) const; + FORCE_INLINE VariantRef getOrAddElement(size_t) const; // getMember(const char*) const @@ -187,6 +189,18 @@ class VariantRef : public VariantRefBase, FORCE_INLINE typename enable_if::value, VariantRef>::type getMember(const TString &) const; + // getMemberConst(const char*) const + // getMemberConst(const __FlashStringHelper*) const + template + FORCE_INLINE class VariantConstRef getMemberConst(TChar *) const; + + // getMemberConst(const std::string&) const + // getMemberConst(const String&) const + template + FORCE_INLINE + typename enable_if::value, class VariantConstRef>::type + getMemberConst(const TString &) const; + // getOrAddMember(char*) const // getOrAddMember(const char*) const // getOrAddMember(const __FlashStringHelper*) const @@ -293,25 +307,25 @@ class VariantConstRef : public VariantRefBase, return as(); } - FORCE_INLINE VariantConstRef getElement(size_t) const; + FORCE_INLINE VariantConstRef getElementConst(size_t) const; FORCE_INLINE VariantConstRef operator[](size_t index) const { - return getElement(index); + return getElementConst(index); } - // getMember(const std::string&) const - // getMember(const String&) const + // getMemberConst(const std::string&) const + // getMemberConst(const String&) const template - FORCE_INLINE VariantConstRef getMember(const TString &key) const { + FORCE_INLINE VariantConstRef getMemberConst(const TString &key) const { return VariantConstRef( objectGetMember(variantAsObject(_data), adaptString(key))); } - // getMember(char*) const - // getMember(const char*) const - // getMember(const __FlashStringHelper*) const + // getMemberConst(char*) const + // getMemberConst(const char*) const + // getMemberConst(const __FlashStringHelper*) const template - FORCE_INLINE VariantConstRef getMember(TChar *key) const { + FORCE_INLINE VariantConstRef getMemberConst(TChar *key) const { const CollectionData *obj = variantAsObject(_data); return VariantConstRef(obj ? obj->getMember(adaptString(key)) : 0); } @@ -332,7 +346,7 @@ class VariantConstRef : public VariantRefBase, FORCE_INLINE typename enable_if::value, VariantConstRef>::type operator[](TChar *key) const { - return getMember(key); + return getMemberConst(key); } };