Store adapted string in MemberProxy

This commit is contained in:
Benoit Blanchon
2024-11-13 14:50:18 +01:00
parent 8110058729
commit 5e7653b36a
7 changed files with 53 additions and 48 deletions

View File

@ -14,12 +14,9 @@
using ArduinoJson::detail::sizeofArray; using ArduinoJson::detail::sizeofArray;
using ArduinoJson::detail::sizeofObject; using ArduinoJson::detail::sizeofObject;
using MemberProxy =
ArduinoJson::detail::MemberProxy<JsonDocument&, const char*>;
TEST_CASE("MemberProxy::add()") { TEST_CASE("MemberProxy::add()") {
JsonDocument doc; JsonDocument doc;
MemberProxy mp = doc["hello"]; auto mp = doc["hello"];
SECTION("add(int)") { SECTION("add(int)") {
mp.add(42); mp.add(42);
@ -48,7 +45,7 @@ TEST_CASE("MemberProxy::add()") {
TEST_CASE("MemberProxy::clear()") { TEST_CASE("MemberProxy::clear()") {
JsonDocument doc; JsonDocument doc;
MemberProxy mp = doc["hello"]; auto mp = doc["hello"];
SECTION("size goes back to zero") { SECTION("size goes back to zero") {
mp.add(42); mp.add(42);
@ -139,7 +136,7 @@ TEST_CASE("MemberProxy::operator|()") {
TEST_CASE("MemberProxy::remove()") { TEST_CASE("MemberProxy::remove()") {
JsonDocument doc; JsonDocument doc;
MemberProxy mp = doc["hello"]; auto mp = doc["hello"];
SECTION("remove(int)") { SECTION("remove(int)") {
mp.add(1); mp.add(1);
@ -186,7 +183,7 @@ TEST_CASE("MemberProxy::remove()") {
TEST_CASE("MemberProxy::set()") { TEST_CASE("MemberProxy::set()") {
JsonDocument doc; JsonDocument doc;
MemberProxy mp = doc["hello"]; auto mp = doc["hello"];
SECTION("set(int)") { SECTION("set(int)") {
mp.set(42); mp.set(42);
@ -223,7 +220,7 @@ TEST_CASE("MemberProxy::set()") {
TEST_CASE("MemberProxy::size()") { TEST_CASE("MemberProxy::size()") {
JsonDocument doc; JsonDocument doc;
MemberProxy mp = doc["hello"]; auto mp = doc["hello"];
SECTION("returns 0") { SECTION("returns 0") {
REQUIRE(mp.size() == 0); REQUIRE(mp.size() == 0);
@ -246,7 +243,7 @@ TEST_CASE("MemberProxy::size()") {
TEST_CASE("MemberProxy::operator[]") { TEST_CASE("MemberProxy::operator[]") {
JsonDocument doc; JsonDocument doc;
MemberProxy mp = doc["hello"]; auto mp = doc["hello"];
SECTION("set member") { SECTION("set member") {
mp["world"] = 42; mp["world"] = 42;
@ -265,7 +262,7 @@ TEST_CASE("MemberProxy cast to JsonVariantConst") {
JsonDocument doc; JsonDocument doc;
doc["hello"] = "world"; doc["hello"] = "world";
const MemberProxy mp = doc["hello"]; const auto mp = doc["hello"];
JsonVariantConst var = mp; JsonVariantConst var = mp;
@ -276,7 +273,7 @@ TEST_CASE("MemberProxy cast to JsonVariant") {
JsonDocument doc; JsonDocument doc;
doc["hello"] = "world"; doc["hello"] = "world";
MemberProxy mp = doc["hello"]; auto mp = doc["hello"];
JsonVariant var = mp; JsonVariant var = mp;

View File

@ -186,19 +186,21 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Gets or sets a root object's member. // Gets or sets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/ // https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TString> template <typename TString>
detail::enable_if_t<detail::IsString<TString>::value, detail::enable_if_t<
detail::MemberProxy<JsonDocument&, TString>> detail::IsString<TString>::value,
detail::MemberProxy<JsonDocument&, detail::AdaptedString<TString>>>
operator[](const TString& key) { operator[](const TString& key) {
return {*this, key}; return {*this, detail::adaptString(key)};
} }
// Gets or sets a root object's member. // Gets or sets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/ // https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TChar> template <typename TChar>
detail::enable_if_t<detail::IsString<TChar*>::value, detail::enable_if_t<
detail::MemberProxy<JsonDocument&, TChar*>> detail::IsString<TChar*>::value,
detail::MemberProxy<JsonDocument&, detail::AdaptedString<TChar*>>>
operator[](TChar* key) { operator[](TChar* key) {
return {*this, key}; return {*this, detail::adaptString(key)};
} }
// Gets a root object's member. // Gets a root object's member.

View File

@ -102,31 +102,31 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// Gets or sets the member with specified key. // Gets or sets the member with specified key.
// https://arduinojson.org/v7/api/jsonobject/subscript/ // https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TString> template <typename TString>
detail::enable_if_t<detail::IsString<TString>::value, detail::enable_if_t<
detail::MemberProxy<JsonObject, TString>> detail::IsString<TString>::value,
detail::MemberProxy<JsonObject, detail::AdaptedString<TString>>>
operator[](const TString& key) const { operator[](const TString& key) const {
return {*this, key}; return {*this, detail::adaptString(key)};
} }
// Gets or sets the member with specified key. // Gets or sets the member with specified key.
// https://arduinojson.org/v7/api/jsonobject/subscript/ // https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TChar> template <typename TChar>
detail::enable_if_t<detail::IsString<TChar*>::value, detail::enable_if_t<
detail::MemberProxy<JsonObject, TChar*>> detail::IsString<TChar*>::value,
detail::MemberProxy<JsonObject, detail::AdaptedString<TChar*>>>
operator[](TChar* key) const { operator[](TChar* key) const {
return {*this, key}; return {*this, detail::adaptString(key)};
} }
// Gets or sets the member with specified key. // Gets or sets the member with specified key.
// https://arduinojson.org/v7/api/jsonobject/subscript/ // https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TVariant> template <typename TVariant>
detail::enable_if_t<detail::IsVariant<TVariant>::value, detail::enable_if_t<
detail::MemberProxy<JsonObject, JsonString>> detail::IsVariant<TVariant>::value,
detail::MemberProxy<JsonObject, detail::AdaptedString<JsonString>>>
operator[](const TVariant& key) const { operator[](const TVariant& key) const {
if (key.template is<JsonString>()) return {*this, detail::adaptString(key.template as<JsonString>())};
return {*this, key.template as<JsonString>()};
else
return {*this, nullptr};
} }
// Removes the member at the specified iterator. // Removes the member at the specified iterator.

View File

@ -10,14 +10,14 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
// A proxy class to get or set a member of an object. // A proxy class to get or set a member of an object.
// https://arduinojson.org/v7/api/jsonobject/subscript/ // https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TUpstream, typename TStringRef> template <typename TUpstream, typename AdaptedString>
class MemberProxy class MemberProxy
: public VariantRefBase<MemberProxy<TUpstream, TStringRef>>, : public VariantRefBase<MemberProxy<TUpstream, AdaptedString>>,
public VariantOperators<MemberProxy<TUpstream, TStringRef>> { public VariantOperators<MemberProxy<TUpstream, AdaptedString>> {
friend class VariantAttorney; friend class VariantAttorney;
public: public:
MemberProxy(TUpstream upstream, TStringRef key) MemberProxy(TUpstream upstream, AdaptedString key)
: upstream_(upstream), key_(key) {} : upstream_(upstream), key_(key) {}
MemberProxy(const MemberProxy& src) MemberProxy(const MemberProxy& src)
@ -47,7 +47,7 @@ class MemberProxy
VariantData* getData() const { VariantData* getData() const {
return VariantData::getMember( return VariantData::getMember(
VariantAttorney::getData(upstream_), adaptString(key_), VariantAttorney::getData(upstream_), key_,
VariantAttorney::getResourceManager(upstream_)); VariantAttorney::getResourceManager(upstream_));
} }
@ -55,13 +55,13 @@ class MemberProxy
auto data = VariantAttorney::getOrCreateData(upstream_); auto data = VariantAttorney::getOrCreateData(upstream_);
if (!data) if (!data)
return nullptr; return nullptr;
return data->getOrAddMember(adaptString(key_), return data->getOrAddMember(key_,
VariantAttorney::getResourceManager(upstream_)); VariantAttorney::getResourceManager(upstream_));
} }
private: private:
TUpstream upstream_; TUpstream upstream_;
TStringRef key_; AdaptedString key_;
}; };
ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -70,4 +70,8 @@ static void stringGetChars(TAdaptedString s, char* p, size_t n) {
} }
} }
template <typename T>
using AdaptedString =
typename StringAdapter<remove_reference_t<T>>::AdaptedString;
ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -188,16 +188,16 @@ class VariantRefBase : public VariantTag {
// Gets or sets an object member. // Gets or sets an object member.
// https://arduinojson.org/v7/api/jsonvariant/subscript/ // https://arduinojson.org/v7/api/jsonvariant/subscript/
template <typename TString> template <typename TString>
FORCE_INLINE FORCE_INLINE enable_if_t<IsString<TString>::value,
enable_if_t<IsString<TString>::value, MemberProxy<TDerived, TString>> MemberProxy<TDerived, AdaptedString<TString>>>
operator[](const TString& key) const; operator[](const TString& key) const;
// Gets or sets an object member. // Gets or sets an object member.
// https://arduinojson.org/v7/api/jsonvariant/subscript/ // https://arduinojson.org/v7/api/jsonvariant/subscript/
template <typename TChar> template <typename TChar>
FORCE_INLINE FORCE_INLINE enable_if_t<IsString<TChar*>::value,
enable_if_t<IsString<TChar*>::value, MemberProxy<TDerived, TChar*>> MemberProxy<TDerived, AdaptedString<TChar*>>>
operator[](TChar* key) const; operator[](TChar* key) const;
// Gets an object member or an array element. // Gets an object member or an array element.
// https://arduinojson.org/v7/api/jsonvariant/subscript/ // https://arduinojson.org/v7/api/jsonvariant/subscript/

View File

@ -123,17 +123,19 @@ inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
} }
template <typename TDerived> template <typename TDerived>
template <typename TString> template <typename TChar>
inline enable_if_t<IsString<TString*>::value, MemberProxy<TDerived, TString*>> inline enable_if_t<IsString<TChar*>::value,
VariantRefBase<TDerived>::operator[](TString* key) const { MemberProxy<TDerived, AdaptedString<TChar*>>>
return MemberProxy<TDerived, TString*>(derived(), key); VariantRefBase<TDerived>::operator[](TChar* key) const {
return {derived(), adaptString(key)};
} }
template <typename TDerived> template <typename TDerived>
template <typename TString> template <typename TString>
inline enable_if_t<IsString<TString>::value, MemberProxy<TDerived, TString>> inline enable_if_t<IsString<TString>::value,
MemberProxy<TDerived, AdaptedString<TString>>>
VariantRefBase<TDerived>::operator[](const TString& key) const { VariantRefBase<TDerived>::operator[](const TString& key) const {
return MemberProxy<TDerived, TString>(derived(), key); return {derived(), adaptString(key)};
} }
template <typename TDerived> template <typename TDerived>