diff --git a/extras/tests/JsonObject/copy.cpp b/extras/tests/JsonObject/copy.cpp index af213f88..74e4b91e 100644 --- a/extras/tests/JsonObject/copy.cpp +++ b/extras/tests/JsonObject/copy.cpp @@ -15,8 +15,9 @@ TEST_CASE("JsonObject::set()") { SECTION("doesn't copy static string in key or value") { obj1["hello"] = "world"; - obj2.set(obj1); + bool success = obj2.set(obj1); + REQUIRE(success == true); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(obj2["hello"] == std::string("world")); } @@ -24,8 +25,9 @@ TEST_CASE("JsonObject::set()") { SECTION("copy local string value") { obj1["hello"] = std::string("world"); - obj2.set(obj1); + bool success = obj2.set(obj1); + REQUIRE(success == true); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(obj2["hello"] == std::string("world")); } @@ -33,8 +35,9 @@ TEST_CASE("JsonObject::set()") { SECTION("copy local key") { obj1[std::string("hello")] = "world"; - obj2.set(obj1); + bool success = obj2.set(obj1); + REQUIRE(success == true); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(obj2["hello"] == std::string("world")); } @@ -42,8 +45,9 @@ TEST_CASE("JsonObject::set()") { SECTION("copy string from deserializeJson()") { deserializeJson(doc1, "{'hello':'world'}"); - obj2.set(obj1); + bool success = obj2.set(obj1); + REQUIRE(success == true); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(obj2["hello"] == std::string("world")); } @@ -51,8 +55,9 @@ TEST_CASE("JsonObject::set()") { SECTION("copy string from deserializeMsgPack()") { deserializeMsgPack(doc1, "\x81\xA5hello\xA5world"); - obj2.set(obj1); + bool success = obj2.set(obj1); + REQUIRE(success == true); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(obj2["hello"] == std::string("world")); } @@ -65,4 +70,28 @@ TEST_CASE("JsonObject::set()") { REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(obj2["hello"] == std::string("world")); } + + SECTION("destination too small to store the key") { + StaticJsonDocument doc3; + JsonObject obj3 = doc3.to(); + + obj1[std::string("hello")] = "world"; + + bool success = obj3.set(obj1); + + REQUIRE(success == false); + REQUIRE(doc3.as() == "{}"); + } + + SECTION("destination too small to store the value") { + StaticJsonDocument doc3; + JsonObject obj3 = doc3.to(); + + obj1["hello"] = std::string("world"); + + bool success = obj3.set(obj1); + + REQUIRE(success == false); + REQUIRE(doc3.as() == "{\"hello\":null}"); + } } diff --git a/src/ArduinoJson/Collection/CollectionImpl.hpp b/src/ArduinoJson/Collection/CollectionImpl.hpp index 1f448ff2..910a2a62 100644 --- a/src/ArduinoJson/Collection/CollectionImpl.hpp +++ b/src/ArduinoJson/Collection/CollectionImpl.hpp @@ -34,8 +34,10 @@ template inline VariantData* CollectionData::addMember(TAdaptedString key, MemoryPool* pool) { VariantSlot* slot = addSlot(pool); - if (!slotSetKey(slot, key, pool)) + if (!slotSetKey(slot, key, pool)) { + removeSlot(slot); return 0; + } return slot->data(); } @@ -132,8 +134,16 @@ inline VariantData* CollectionData::getMember(TAdaptedString key) const { template inline VariantData* CollectionData::getOrAddMember(TAdaptedString key, MemoryPool* pool) { + // ignore null key + if (key.isNull()) + return 0; + + // search a matching key VariantSlot* slot = getSlot(key); - return slot ? slot->data() : addMember(key, pool); + if (slot) + return slot->data(); + + return addMember(key, pool); } inline VariantData* CollectionData::getElement(size_t index) const { diff --git a/src/ArduinoJson/Object/ObjectFunctions.hpp b/src/ArduinoJson/Object/ObjectFunctions.hpp index 90859bdf..0c754eb3 100644 --- a/src/ArduinoJson/Object/ObjectFunctions.hpp +++ b/src/ArduinoJson/Object/ObjectFunctions.hpp @@ -25,7 +25,8 @@ inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) { } template -inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) { +inline VariantData *objectGetMember(const CollectionData *obj, + TAdaptedString key) { if (!obj) return 0; return obj->getMember(key); @@ -39,20 +40,11 @@ void objectRemove(CollectionData *obj, TAdaptedString key) { } template -inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key, - MemoryPool *pool) { +inline VariantData *objectGetOrAddMember(CollectionData *obj, + TAdaptedString key, MemoryPool *pool) { if (!obj) return 0; - // ignore null key - if (key.isNull()) - return 0; - - // search a matching key - VariantData *var = obj->getMember(key); - if (var) - return var; - - return obj->addMember(key, pool); + return obj->getOrAddMember(key, pool); } } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Object/ObjectRef.hpp b/src/ArduinoJson/Object/ObjectRef.hpp index faf00bde..599a2ae9 100644 --- a/src/ArduinoJson/Object/ObjectRef.hpp +++ b/src/ArduinoJson/Object/ObjectRef.hpp @@ -129,7 +129,7 @@ class ObjectConstRef : public ObjectRefBase, private: template FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const { - return VariantConstRef(objectGet(_data, key)); + return VariantConstRef(objectGetMember(_data, key)); } }; @@ -180,7 +180,7 @@ class ObjectRef : public ObjectRefBase, // getMember(const String&) const template FORCE_INLINE VariantRef getMember(const TString& key) const { - return get_impl(adaptString(key)); + return VariantRef(_pool, objectGetMember(_data, adaptString(key))); } // getMember(char*) const @@ -188,14 +188,15 @@ class ObjectRef : public ObjectRefBase, // getMember(const __FlashStringHelper*) const template FORCE_INLINE VariantRef getMember(TChar* key) const { - return get_impl(adaptString(key)); + return VariantRef(_pool, objectGetMember(_data, adaptString(key))); } // getOrAddMember(const std::string&) const // getOrAddMember(const String&) const template FORCE_INLINE VariantRef getOrAddMember(const TString& key) const { - return getOrCreate_impl(adaptString(key)); + return VariantRef(_pool, + objectGetOrAddMember(_data, adaptString(key), _pool)); } // getOrAddMember(char*) const @@ -203,7 +204,8 @@ class ObjectRef : public ObjectRefBase, // getOrAddMember(const __FlashStringHelper*) const template FORCE_INLINE VariantRef getOrAddMember(TChar* key) const { - return getOrCreate_impl(adaptString(key)); + return VariantRef(_pool, + objectGetOrAddMember(_data, adaptString(key), _pool)); } FORCE_INLINE bool operator==(ObjectRef rhs) const { @@ -232,16 +234,6 @@ class ObjectRef : public ObjectRefBase, } private: - template - FORCE_INLINE VariantRef get_impl(TAdaptedString key) const { - return VariantRef(_pool, objectGet(_data, key)); - } - - template - FORCE_INLINE VariantRef getOrCreate_impl(TAdaptedString key) const { - return VariantRef(_pool, objectGetOrCreate(_data, key, _pool)); - } - MemoryPool* _pool; }; } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Variant/VariantRef.hpp b/src/ArduinoJson/Variant/VariantRef.hpp index 8398624f..a71908dc 100644 --- a/src/ArduinoJson/Variant/VariantRef.hpp +++ b/src/ArduinoJson/Variant/VariantRef.hpp @@ -384,7 +384,8 @@ class VariantConstRef : public VariantRefBase, // getMember(const String&) const template FORCE_INLINE VariantConstRef getMember(const TString &key) const { - return VariantConstRef(objectGet(variantAsObject(_data), adaptString(key))); + return VariantConstRef( + objectGetMember(variantAsObject(_data), adaptString(key))); } // getMember(char*) const