mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Changed the array subscript to automatically add missing elements
This commit is contained in:
		| @@ -6,6 +6,7 @@ HEAD | |||||||
|  |  | ||||||
| * Added `DeserializationOption::Filter` (issue #959) | * Added `DeserializationOption::Filter` (issue #959) | ||||||
| * Added example `JsonFilterExample.ino` | * Added example `JsonFilterExample.ino` | ||||||
|  | * Changed the array subscript operator to automatically add missing elements | ||||||
| * Fixed "deprecated-copy" warning on GCC 9 (fixes #1184) | * Fixed "deprecated-copy" warning on GCC 9 (fixes #1184) | ||||||
|  |  | ||||||
| v6.14.1 (2020-01-27) | v6.14.1 (2020-01-27) | ||||||
|   | |||||||
| @@ -33,12 +33,9 @@ void setup() { | |||||||
|       "1000000,\"timezone\":0,\"sunrise\":1581492085,\"sunset\":1581527294}}"); |       "1000000,\"timezone\":0,\"sunrise\":1581492085,\"sunset\":1581527294}}"); | ||||||
|  |  | ||||||
|   // The filter: it contains "true" for each value we want to keep |   // The filter: it contains "true" for each value we want to keep | ||||||
|   const __FlashStringHelper* filter_json = |  | ||||||
|       F("{\"list\":[{\"dt\":true,\"main\":{\"temp\":true}]}"); |  | ||||||
|  |  | ||||||
|   // Create the filter document |  | ||||||
|   StaticJsonDocument<200> filter; |   StaticJsonDocument<200> filter; | ||||||
|   deserializeJson(filter, filter_json); |   filter["list"][0]["dt"] = true; | ||||||
|  |   filter["list"][0]["main"]["temp"] = true; | ||||||
|  |  | ||||||
|   // Deserialize the document |   // Deserialize the document | ||||||
|   StaticJsonDocument<400> doc; |   StaticJsonDocument<400> doc; | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ using namespace ARDUINOJSON_NAMESPACE; | |||||||
|  |  | ||||||
| TEST_CASE("ElementProxy::set()") { | TEST_CASE("ElementProxy::set()") { | ||||||
|   DynamicJsonDocument doc(4096); |   DynamicJsonDocument doc(4096); | ||||||
|   doc.addElement(); |  | ||||||
|   ElementProxy<JsonDocument&> ep = doc[0]; |   ElementProxy<JsonDocument&> ep = doc[0]; | ||||||
|  |  | ||||||
|   SECTION("set(int)") { |   SECTION("set(int)") { | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								extras/tests/ElementProxy/subscript.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								extras/tests/ElementProxy/subscript.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2020 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | using namespace ARDUINOJSON_NAMESPACE; | ||||||
|  |  | ||||||
|  | TEST_CASE("MemberProxy::operator[]") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   ElementProxy<JsonDocument&> ep = doc[1]; | ||||||
|  |  | ||||||
|  |   SECTION("set member") { | ||||||
|  |     ep["world"] = 42; | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "[null,{\"world\":42}]"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("set element") { | ||||||
|  |     ep[2] = 42; | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "[null,[null,null,42]]"); | ||||||
|  |   } | ||||||
|  | } | ||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -9,7 +9,20 @@ | |||||||
| TEST_CASE("JsonArray::operator[]") { | TEST_CASE("JsonArray::operator[]") { | ||||||
|   DynamicJsonDocument doc(4096); |   DynamicJsonDocument doc(4096); | ||||||
|   JsonArray array = doc.to<JsonArray>(); |   JsonArray array = doc.to<JsonArray>(); | ||||||
|   array.add(0); |  | ||||||
|  |   SECTION("Pad with null") { | ||||||
|  |     array[2] = 2; | ||||||
|  |     array[5] = 5; | ||||||
|  |     REQUIRE(array.size() == 6); | ||||||
|  |     REQUIRE(array[0].isNull() == true); | ||||||
|  |     REQUIRE(array[1].isNull() == true); | ||||||
|  |     REQUIRE(array[2].isNull() == false); | ||||||
|  |     REQUIRE(array[3].isNull() == true); | ||||||
|  |     REQUIRE(array[4].isNull() == true); | ||||||
|  |     REQUIRE(array[5].isNull() == false); | ||||||
|  |     REQUIRE(array[2] == 2); | ||||||
|  |     REQUIRE(array[5] == 5); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   SECTION("int") { |   SECTION("int") { | ||||||
|     array[0] = 123; |     array[0] = 123; | ||||||
|   | |||||||
| @@ -43,3 +43,11 @@ TEST_CASE("JsonDocument automatically promotes to object") { | |||||||
|  |  | ||||||
|   REQUIRE(doc["one"]["two"]["three"] == 4); |   REQUIRE(doc["one"]["two"]["three"] == 4); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonDocument automatically promotes to array") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |  | ||||||
|  |   doc[2] = 2; | ||||||
|  |  | ||||||
|  |   REQUIRE(doc.as<std::string>() == "[null,null,2]"); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -43,10 +43,10 @@ TEST_CASE("JsonVariant::operator[]") { | |||||||
|     SECTION("set value") { |     SECTION("set value") { | ||||||
|       array.add("hello"); |       array.add("hello"); | ||||||
|  |  | ||||||
|       var[0] = "world"; |       var[1] = "world"; | ||||||
|  |  | ||||||
|       REQUIRE(1 == var.size()); |       REQUIRE(var.size() == 2); | ||||||
|       REQUIRE(std::string("world") == var[0]); |       REQUIRE(std::string("world") == var[1]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     SECTION("set value in a nested object") { |     SECTION("set value in a nested object") { | ||||||
|   | |||||||
| @@ -11,9 +11,15 @@ TEST_CASE("MemberProxy::operator[]") { | |||||||
|   DynamicJsonDocument doc(4096); |   DynamicJsonDocument doc(4096); | ||||||
|   MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; |   MemberProxy<JsonDocument&, const char*> mp = doc["hello"]; | ||||||
|  |  | ||||||
|   SECTION("set integer") { |   SECTION("set member") { | ||||||
|     mp["world"] = 42; |     mp["world"] = 42; | ||||||
|  |  | ||||||
|     REQUIRE(doc.as<std::string>() == "{\"hello\":{\"world\":42}}"); |     REQUIRE(doc.as<std::string>() == "{\"hello\":{\"world\":42}}"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("set element") { | ||||||
|  |     mp[2] = 42; | ||||||
|  |  | ||||||
|  |     REQUIRE(doc.as<std::string>() == "{\"hello\":[null,null,42]}"); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) { | inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) { | ||||||
|   return arr ? arr->add(pool) : 0; |   return arr ? arr->addElement(pool) : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Visitor> | template <typename Visitor> | ||||||
|   | |||||||
| @@ -87,7 +87,7 @@ class ArrayConstRef : public ArrayRefBase<const CollectionData>, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE VariantConstRef getElement(size_t index) const { |   FORCE_INLINE VariantConstRef getElement(size_t index) const { | ||||||
|     return VariantConstRef(_data ? _data->get(index) : 0); |     return VariantConstRef(_data ? _data->getElement(index) : 0); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -137,23 +137,28 @@ class ArrayRef : public ArrayRefBase<CollectionData>, | |||||||
|     return arrayEquals(_data, rhs._data); |     return arrayEquals(_data, rhs._data); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   // Internal use | ||||||
|  |   FORCE_INLINE VariantRef getOrAddElement(size_t index) const { | ||||||
|  |     return VariantRef(_pool, _data ? _data->getOrAddElement(index, _pool) : 0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Gets the value at the specified index. |   // Gets the value at the specified index. | ||||||
|   FORCE_INLINE VariantRef getElement(size_t index) const { |   FORCE_INLINE VariantRef getElement(size_t index) const { | ||||||
|     return VariantRef(_pool, _data ? _data->get(index) : 0); |     return VariantRef(_pool, _data ? _data->getElement(index) : 0); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Removes element at specified position. |   // Removes element at specified position. | ||||||
|   FORCE_INLINE void remove(iterator it) const { |   FORCE_INLINE void remove(iterator it) const { | ||||||
|     if (!_data) |     if (!_data) | ||||||
|       return; |       return; | ||||||
|     _data->remove(it.internal()); |     _data->removeSlot(it.internal()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Removes element at specified index. |   // Removes element at specified index. | ||||||
|   FORCE_INLINE void remove(size_t index) const { |   FORCE_INLINE void remove(size_t index) const { | ||||||
|     if (!_data) |     if (!_data) | ||||||
|       return; |       return; | ||||||
|     _data->remove(index); |     _data->removeElement(index); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | |||||||
|       : _array(src._array), _index(src._index) {} |       : _array(src._array), _index(src._index) {} | ||||||
|  |  | ||||||
|   FORCE_INLINE this_type& operator=(const this_type& src) { |   FORCE_INLINE this_type& operator=(const this_type& src) { | ||||||
|     getUpstreamElement().set(src.as<VariantConstRef>()); |     getOrAddUpstreamElement().set(src.as<VariantConstRef>()); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -39,7 +39,7 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | |||||||
|   //          std::string, String, ArrayRef, ObjectRef |   //          std::string, String, ArrayRef, ObjectRef | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE this_type& operator=(const T& src) { |   FORCE_INLINE this_type& operator=(const T& src) { | ||||||
|     getUpstreamElement().set(src); |     getOrAddUpstreamElement().set(src); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
| @@ -47,7 +47,7 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | |||||||
|   // TValue = char*, const char*, const __FlashStringHelper* |   // TValue = char*, const char*, const __FlashStringHelper* | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE this_type& operator=(T* src) { |   FORCE_INLINE this_type& operator=(T* src) { | ||||||
|     getUpstreamElement().set(src); |     getOrAddUpstreamElement().set(src); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -79,7 +79,7 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | |||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE typename VariantTo<T>::type to() const { |   FORCE_INLINE typename VariantTo<T>::type to() const { | ||||||
|     return getUpstreamElement().template to<T>(); |     return getOrAddUpstreamElement().template to<T>(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Replaces the value |   // Replaces the value | ||||||
| @@ -89,14 +89,14 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | |||||||
|   //          std::string, String, ArrayRef, ObjectRef |   //          std::string, String, ArrayRef, ObjectRef | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(const TValue& value) const { |   FORCE_INLINE bool set(const TValue& value) const { | ||||||
|     return getUpstreamElement().set(value); |     return getOrAddUpstreamElement().set(value); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool set(TValue) |   // bool set(TValue) | ||||||
|   // TValue = char*, const char*, const __FlashStringHelper* |   // TValue = char*, const char*, const __FlashStringHelper* | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(TValue* value) const { |   FORCE_INLINE bool set(TValue* value) const { | ||||||
|     return getUpstreamElement().set(value); |     return getOrAddUpstreamElement().set(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename Visitor> |   template <typename Visitor> | ||||||
| @@ -120,20 +120,20 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | |||||||
|  |  | ||||||
|   template <typename TNestedKey> |   template <typename TNestedKey> | ||||||
|   VariantRef getOrAddMember(TNestedKey* key) const { |   VariantRef getOrAddMember(TNestedKey* key) const { | ||||||
|     return getUpstreamElement().getOrAddMember(key); |     return getOrAddUpstreamElement().getOrAddMember(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TNestedKey> |   template <typename TNestedKey> | ||||||
|   VariantRef getOrAddMember(const TNestedKey& key) const { |   VariantRef getOrAddMember(const TNestedKey& key) const { | ||||||
|     return getUpstreamElement().getOrAddMember(key); |     return getOrAddUpstreamElement().getOrAddMember(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   VariantRef addElement() const { |   VariantRef addElement() const { | ||||||
|     return getUpstreamElement().addElement(); |     return getOrAddUpstreamElement().addElement(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   VariantRef getElement(size_t index) const { |   VariantRef getElement(size_t index) const { | ||||||
|     return getUpstreamElement().getElement(index); |     return getOrAddUpstreamElement().getElement(index); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE void remove(size_t index) const { |   FORCE_INLINE void remove(size_t index) const { | ||||||
| @@ -160,6 +160,10 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | |||||||
|     return _array.getElement(_index); |     return _array.getElement(_index); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   FORCE_INLINE VariantRef getOrAddUpstreamElement() const { | ||||||
|  |     return _array.getOrAddElement(_index); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   TArray _array; |   TArray _array; | ||||||
|   const size_t _index; |   const size_t _index; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -25,45 +25,56 @@ class CollectionData { | |||||||
|   // - no destructor |   // - no destructor | ||||||
|   // - no virtual |   // - no virtual | ||||||
|   // - no inheritance |   // - no inheritance | ||||||
|   VariantSlot *addSlot(MemoryPool *); |  | ||||||
|  |  | ||||||
|   VariantData *add(MemoryPool *pool); |   // Array only | ||||||
|  |  | ||||||
|  |   VariantData *addElement(MemoryPool *pool); | ||||||
|  |  | ||||||
|  |   VariantData *getElement(size_t index) const; | ||||||
|  |  | ||||||
|  |   VariantData *getOrAddElement(size_t index, MemoryPool *pool); | ||||||
|  |  | ||||||
|  |   void removeElement(size_t index); | ||||||
|  |  | ||||||
|  |   bool equalsArray(const CollectionData &other) const; | ||||||
|  |  | ||||||
|  |   // Object only | ||||||
|  |  | ||||||
|   template <typename TAdaptedString> |   template <typename TAdaptedString> | ||||||
|   VariantData *add(TAdaptedString key, MemoryPool *pool); |   VariantData *addMember(TAdaptedString key, MemoryPool *pool); | ||||||
|  |  | ||||||
|   void clear(); |   template <typename TAdaptedString> | ||||||
|  |   VariantData *getMember(TAdaptedString key) const; | ||||||
|  |  | ||||||
|  |   template <typename TAdaptedString> | ||||||
|  |   VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool); | ||||||
|  |  | ||||||
|  |   template <typename TAdaptedString> | ||||||
|  |   void removeMember(TAdaptedString key) { | ||||||
|  |     removeSlot(getSlot(key)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename TAdaptedString> |   template <typename TAdaptedString> | ||||||
|   bool containsKey(const TAdaptedString &key) const; |   bool containsKey(const TAdaptedString &key) const; | ||||||
|  |  | ||||||
|   bool copyFrom(const CollectionData &src, MemoryPool *pool); |  | ||||||
|  |  | ||||||
|   bool equalsArray(const CollectionData &other) const; |  | ||||||
|   bool equalsObject(const CollectionData &other) const; |   bool equalsObject(const CollectionData &other) const; | ||||||
|  |  | ||||||
|   VariantData *get(size_t index) const; |   // Generic | ||||||
|  |  | ||||||
|   template <typename TAdaptedString> |   void clear(); | ||||||
|   VariantData *get(TAdaptedString key) const; |   size_t memoryUsage() const; | ||||||
|  |   size_t nesting() const; | ||||||
|  |   size_t size() const; | ||||||
|  |  | ||||||
|  |   VariantSlot *addSlot(MemoryPool *); | ||||||
|  |   void removeSlot(VariantSlot *slot); | ||||||
|  |  | ||||||
|  |   bool copyFrom(const CollectionData &src, MemoryPool *pool); | ||||||
|  |  | ||||||
|   VariantSlot *head() const { |   VariantSlot *head() const { | ||||||
|     return _head; |     return _head; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void remove(size_t index); |  | ||||||
|  |  | ||||||
|   template <typename TAdaptedString> |  | ||||||
|   void remove(TAdaptedString key) { |  | ||||||
|     remove(getSlot(key)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void remove(VariantSlot *slot); |  | ||||||
|  |  | ||||||
|   size_t memoryUsage() const; |  | ||||||
|   size_t nesting() const; |  | ||||||
|   size_t size() const; |  | ||||||
|  |  | ||||||
|   void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance); |   void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance); | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   | |||||||
| @@ -26,12 +26,13 @@ inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) { | |||||||
|   return slot; |   return slot; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline VariantData* CollectionData::add(MemoryPool* pool) { | inline VariantData* CollectionData::addElement(MemoryPool* pool) { | ||||||
|   return slotData(addSlot(pool)); |   return slotData(addSlot(pool)); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TAdaptedString> | template <typename TAdaptedString> | ||||||
| inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) { | inline VariantData* CollectionData::addMember(TAdaptedString key, | ||||||
|  |                                               MemoryPool* pool) { | ||||||
|   VariantSlot* slot = addSlot(pool); |   VariantSlot* slot = addSlot(pool); | ||||||
|   if (!slotSetKey(slot, key, pool)) |   if (!slotSetKey(slot, key, pool)) | ||||||
|     return 0; |     return 0; | ||||||
| @@ -55,11 +56,11 @@ inline bool CollectionData::copyFrom(const CollectionData& src, | |||||||
|     VariantData* var; |     VariantData* var; | ||||||
|     if (s->key() != 0) { |     if (s->key() != 0) { | ||||||
|       if (s->ownsKey()) |       if (s->ownsKey()) | ||||||
|         var = add(RamStringAdapter(s->key()), pool); |         var = addMember(RamStringAdapter(s->key()), pool); | ||||||
|       else |       else | ||||||
|         var = add(ConstRamStringAdapter(s->key()), pool); |         var = addMember(ConstRamStringAdapter(s->key()), pool); | ||||||
|     } else { |     } else { | ||||||
|       var = add(pool); |       var = addElement(pool); | ||||||
|     } |     } | ||||||
|     if (!var) |     if (!var) | ||||||
|       return false; |       return false; | ||||||
| @@ -73,7 +74,7 @@ inline bool CollectionData::equalsObject(const CollectionData& other) const { | |||||||
|   size_t count = 0; |   size_t count = 0; | ||||||
|   for (VariantSlot* slot = _head; slot; slot = slot->next()) { |   for (VariantSlot* slot = _head; slot; slot = slot->next()) { | ||||||
|     VariantData* v1 = slot->data(); |     VariantData* v1 = slot->data(); | ||||||
|     VariantData* v2 = other.get(adaptString(slot->key())); |     VariantData* v2 = other.getMember(adaptString(slot->key())); | ||||||
|     if (!variantEquals(v1, v2)) |     if (!variantEquals(v1, v2)) | ||||||
|       return false; |       return false; | ||||||
|     count++; |     count++; | ||||||
| @@ -123,17 +124,40 @@ inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const { | |||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TAdaptedString> | template <typename TAdaptedString> | ||||||
| inline VariantData* CollectionData::get(TAdaptedString key) const { | inline VariantData* CollectionData::getMember(TAdaptedString key) const { | ||||||
|   VariantSlot* slot = getSlot(key); |   VariantSlot* slot = getSlot(key); | ||||||
|   return slot ? slot->data() : 0; |   return slot ? slot->data() : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline VariantData* CollectionData::get(size_t index) const { | template <typename TAdaptedString> | ||||||
|  | inline VariantData* CollectionData::getOrAddMember(TAdaptedString key, | ||||||
|  |                                                    MemoryPool* pool) { | ||||||
|  |   VariantSlot* slot = getSlot(key); | ||||||
|  |   return slot ? slot->data() : addMember(key, pool); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline VariantData* CollectionData::getElement(size_t index) const { | ||||||
|   VariantSlot* slot = getSlot(index); |   VariantSlot* slot = getSlot(index); | ||||||
|   return slot ? slot->data() : 0; |   return slot ? slot->data() : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline void CollectionData::remove(VariantSlot* slot) { | inline VariantData* CollectionData::getOrAddElement(size_t index, | ||||||
|  |                                                     MemoryPool* pool) { | ||||||
|  |   VariantSlot* slot = _head; | ||||||
|  |   while (slot && index > 0) { | ||||||
|  |     slot = slot->next(); | ||||||
|  |     index--; | ||||||
|  |   } | ||||||
|  |   if (!slot) | ||||||
|  |     index++; | ||||||
|  |   while (index > 0) { | ||||||
|  |     slot = addSlot(pool); | ||||||
|  |     index--; | ||||||
|  |   } | ||||||
|  |   return slotData(slot); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void CollectionData::removeSlot(VariantSlot* slot) { | ||||||
|   if (!slot) |   if (!slot) | ||||||
|     return; |     return; | ||||||
|   VariantSlot* prev = getPreviousSlot(slot); |   VariantSlot* prev = getPreviousSlot(slot); | ||||||
| @@ -146,8 +170,8 @@ inline void CollectionData::remove(VariantSlot* slot) { | |||||||
|     _tail = prev; |     _tail = prev; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline void CollectionData::remove(size_t index) { | inline void CollectionData::removeElement(size_t index) { | ||||||
|   remove(getSlot(index)); |   removeSlot(getSlot(index)); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline size_t CollectionData::memoryUsage() const { | inline size_t CollectionData::memoryUsage() const { | ||||||
|   | |||||||
| @@ -192,6 +192,10 @@ class JsonDocument : public Visitable { | |||||||
|     return VariantConstRef(_data.getElement(index)); |     return VariantConstRef(_data.getElement(index)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   FORCE_INLINE VariantRef getOrAddElement(size_t index) { | ||||||
|  |     return VariantRef(&_pool, _data.getOrAddElement(index, &_pool)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // JsonVariantConst getMember(char*) const |   // JsonVariantConst getMember(char*) const | ||||||
|   // JsonVariantConst getMember(const char*) const |   // JsonVariantConst getMember(const char*) const | ||||||
|   // JsonVariantConst getMember(const __FlashStringHelper*) const |   // JsonVariantConst getMember(const __FlashStringHelper*) const | ||||||
|   | |||||||
| @@ -139,7 +139,7 @@ class JsonDeserializer { | |||||||
|     for (;;) { |     for (;;) { | ||||||
|       if (memberFilter.allow()) { |       if (memberFilter.allow()) { | ||||||
|         // Allocate slot in array |         // Allocate slot in array | ||||||
|         VariantData *value = array.add(_pool); |         VariantData *value = array.addElement(_pool); | ||||||
|         if (!value) |         if (!value) | ||||||
|           return DeserializationError::NoMemory; |           return DeserializationError::NoMemory; | ||||||
|  |  | ||||||
| @@ -231,7 +231,7 @@ class JsonDeserializer { | |||||||
|       TFilter memberFilter = filter[key]; |       TFilter memberFilter = filter[key]; | ||||||
|  |  | ||||||
|       if (memberFilter.allow()) { |       if (memberFilter.allow()) { | ||||||
|         VariantData *variant = object.get(adaptString(key)); |         VariantData *variant = object.getMember(adaptString(key)); | ||||||
|         if (!variant) { |         if (!variant) { | ||||||
|           // Allocate slot in object |           // Allocate slot in object | ||||||
|           VariantSlot *slot = object.addSlot(_pool); |           VariantSlot *slot = object.addSlot(_pool); | ||||||
|   | |||||||
| @@ -269,7 +269,7 @@ class MsgPackDeserializer { | |||||||
|       return DeserializationError::TooDeep; |       return DeserializationError::TooDeep; | ||||||
|  |  | ||||||
|     for (; n; --n) { |     for (; n; --n) { | ||||||
|       VariantData *value = array.add(_pool); |       VariantData *value = array.addElement(_pool); | ||||||
|       if (!value) |       if (!value) | ||||||
|         return DeserializationError::NoMemory; |         return DeserializationError::NoMemory; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -129,11 +129,14 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >, | |||||||
|     return getOrAddUpstreamMember().addElement(); |     return getOrAddUpstreamMember().addElement(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // getElement(size_t) const |  | ||||||
|   FORCE_INLINE VariantRef getElement(size_t index) const { |   FORCE_INLINE VariantRef getElement(size_t index) const { | ||||||
|     return getUpstreamMember().getElement(index); |     return getUpstreamMember().getElement(index); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   FORCE_INLINE VariantRef getOrAddElement(size_t index) const { | ||||||
|  |     return getOrAddUpstreamMember().getOrAddElement(index); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // getMember(char*) const |   // getMember(char*) const | ||||||
|   // getMember(const char*) const |   // getMember(const char*) const | ||||||
|   // getMember(const __FlashStringHelper*) const |   // getMember(const __FlashStringHelper*) const | ||||||
|   | |||||||
| @@ -28,14 +28,14 @@ template <typename TAdaptedString> | |||||||
| inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) { | inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) { | ||||||
|   if (!obj) |   if (!obj) | ||||||
|     return 0; |     return 0; | ||||||
|   return obj->get(key); |   return obj->getMember(key); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TAdaptedString> | template <typename TAdaptedString> | ||||||
| void objectRemove(CollectionData *obj, TAdaptedString key) { | void objectRemove(CollectionData *obj, TAdaptedString key) { | ||||||
|   if (!obj) |   if (!obj) | ||||||
|     return; |     return; | ||||||
|   obj->remove(key); |   obj->removeMember(key); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TAdaptedString> | template <typename TAdaptedString> | ||||||
| @@ -49,10 +49,10 @@ inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key, | |||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|   // search a matching key |   // search a matching key | ||||||
|   VariantData *var = obj->get(key); |   VariantData *var = obj->getMember(key); | ||||||
|   if (var) |   if (var) | ||||||
|     return var; |     return var; | ||||||
|  |  | ||||||
|   return obj->add(key, pool); |   return obj->addMember(key, pool); | ||||||
| } | } | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -213,7 +213,7 @@ class ObjectRef : public ObjectRefBase<CollectionData>, | |||||||
|   FORCE_INLINE void remove(iterator it) const { |   FORCE_INLINE void remove(iterator it) const { | ||||||
|     if (!_data) |     if (!_data) | ||||||
|       return; |       return; | ||||||
|     _data->remove(it.internal()); |     _data->removeSlot(it.internal()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // remove(const std::string&) const |   // remove(const std::string&) const | ||||||
|   | |||||||
| @@ -186,13 +186,13 @@ class VariantData { | |||||||
|  |  | ||||||
|   void remove(size_t index) { |   void remove(size_t index) { | ||||||
|     if (isArray()) |     if (isArray()) | ||||||
|       _content.asCollection.remove(index); |       _content.asCollection.removeElement(index); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TAdaptedString> |   template <typename TAdaptedString> | ||||||
|   void remove(TAdaptedString key) { |   void remove(TAdaptedString key) { | ||||||
|     if (isObject()) |     if (isObject()) | ||||||
|       _content.asCollection.remove(key); |       _content.asCollection.removeMember(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void setBoolean(bool value) { |   void setBoolean(bool value) { | ||||||
| @@ -335,16 +335,24 @@ class VariantData { | |||||||
|       toArray(); |       toArray(); | ||||||
|     if (!isArray()) |     if (!isArray()) | ||||||
|       return 0; |       return 0; | ||||||
|     return _content.asCollection.add(pool); |     return _content.asCollection.addElement(pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   VariantData *getElement(size_t index) const { |   VariantData *getElement(size_t index) const { | ||||||
|     return isArray() ? _content.asCollection.get(index) : 0; |     return isArray() ? _content.asCollection.getElement(index) : 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   VariantData *getOrAddElement(size_t index, MemoryPool *pool) { | ||||||
|  |     if (isNull()) | ||||||
|  |       toArray(); | ||||||
|  |     if (!isArray()) | ||||||
|  |       return 0; | ||||||
|  |     return _content.asCollection.getOrAddElement(index, pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TAdaptedString> |   template <typename TAdaptedString> | ||||||
|   VariantData *getMember(TAdaptedString key) const { |   VariantData *getMember(TAdaptedString key) const { | ||||||
|     return isObject() ? _content.asCollection.get(key) : 0; |     return isObject() ? _content.asCollection.getMember(key) : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TAdaptedString> |   template <typename TAdaptedString> | ||||||
| @@ -353,10 +361,7 @@ class VariantData { | |||||||
|       toObject(); |       toObject(); | ||||||
|     if (!isObject()) |     if (!isObject()) | ||||||
|       return 0; |       return 0; | ||||||
|     VariantData *var = _content.asCollection.get(key); |     return _content.asCollection.getOrAddMember(key, pool); | ||||||
|     if (var) |  | ||||||
|       return var; |  | ||||||
|     return _content.asCollection.add(key, pool); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) { |   void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) { | ||||||
|   | |||||||
| @@ -160,19 +160,27 @@ inline CollectionData *variantToObject(VariantData *var) { | |||||||
|   return &var->toObject(); |   return &var->toObject(); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline NO_INLINE VariantData *variantAdd(VariantData *var, MemoryPool *pool) { | inline NO_INLINE VariantData *variantAddElement(VariantData *var, | ||||||
|  |                                                 MemoryPool *pool) { | ||||||
|   return var != 0 ? var->addElement(pool) : 0; |   return var != 0 ? var->addElement(pool) : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline NO_INLINE VariantData *variantGetOrAddElement(VariantData *var, | ||||||
|  |                                                      size_t index, | ||||||
|  |                                                      MemoryPool *pool) { | ||||||
|  |   return var != 0 ? var->getOrAddElement(index, pool) : 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| template <typename TChar> | template <typename TChar> | ||||||
| NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TChar *key, | NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, TChar *key, | ||||||
|                                           MemoryPool *pool) { |                                              MemoryPool *pool) { | ||||||
|   return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0; |   return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TString> | template <typename TString> | ||||||
| NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TString &key, | NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, | ||||||
|                                           MemoryPool *pool) { |                                              const TString &key, | ||||||
|  |                                              MemoryPool *pool) { | ||||||
|   return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0; |   return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -119,13 +119,17 @@ inline VariantConstRef VariantConstRef::getElement(size_t index) const { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline VariantRef VariantRef::addElement() const { | inline VariantRef VariantRef::addElement() const { | ||||||
|   return VariantRef(_pool, variantAdd(_data, _pool)); |   return VariantRef(_pool, variantAddElement(_data, _pool)); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline VariantRef VariantRef::getElement(size_t index) const { | inline VariantRef VariantRef::getElement(size_t index) const { | ||||||
|   return VariantRef(_pool, _data != 0 ? _data->getElement(index) : 0); |   return VariantRef(_pool, _data != 0 ? _data->getElement(index) : 0); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline VariantRef VariantRef::getOrAddElement(size_t index) const { | ||||||
|  |   return VariantRef(_pool, variantGetOrAddElement(_data, index, _pool)); | ||||||
|  | } | ||||||
|  |  | ||||||
| template <typename TChar> | template <typename TChar> | ||||||
| inline VariantRef VariantRef::getMember(TChar *key) const { | inline VariantRef VariantRef::getMember(TChar *key) const { | ||||||
|   return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0); |   return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0); | ||||||
| @@ -139,11 +143,11 @@ VariantRef::getMember(const TString &key) const { | |||||||
|  |  | ||||||
| template <typename TChar> | template <typename TChar> | ||||||
| inline VariantRef VariantRef::getOrAddMember(TChar *key) const { | inline VariantRef VariantRef::getOrAddMember(TChar *key) const { | ||||||
|   return VariantRef(_pool, variantGetOrCreate(_data, key, _pool)); |   return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool)); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TString> | template <typename TString> | ||||||
| inline VariantRef VariantRef::getOrAddMember(const TString &key) const { | inline VariantRef VariantRef::getOrAddMember(const TString &key) const { | ||||||
|   return VariantRef(_pool, variantGetOrCreate(_data, key, _pool)); |   return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool)); | ||||||
| } | } | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -301,6 +301,8 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|  |  | ||||||
|   FORCE_INLINE VariantRef getElement(size_t) const; |   FORCE_INLINE VariantRef getElement(size_t) const; | ||||||
|  |  | ||||||
|  |   FORCE_INLINE VariantRef getOrAddElement(size_t) const; | ||||||
|  |  | ||||||
|   // getMember(const char*) const |   // getMember(const char*) const | ||||||
|   // getMember(const __FlashStringHelper*) const |   // getMember(const __FlashStringHelper*) const | ||||||
|   template <typename TChar> |   template <typename TChar> | ||||||
| @@ -391,7 +393,7 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | |||||||
|   template <typename TChar> |   template <typename TChar> | ||||||
|   FORCE_INLINE VariantConstRef getMember(TChar *key) const { |   FORCE_INLINE VariantConstRef getMember(TChar *key) const { | ||||||
|     const CollectionData *obj = variantAsObject(_data); |     const CollectionData *obj = variantAsObject(_data); | ||||||
|     return VariantConstRef(obj ? obj->get(adaptString(key)) : 0); |     return VariantConstRef(obj ? obj->getMember(adaptString(key)) : 0); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // operator[](const std::string&) const |   // operator[](const std::string&) const | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user