From c4e5051a7aa5faa94804f6a560561de7c0799645 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 14 Jun 2023 11:57:31 +0200 Subject: [PATCH] Store index of slot in the pool instead of a pointer or a distance --- extras/conf_test/avr.cpp | 3 +- extras/conf_test/esp8266.cpp | 3 +- extras/conf_test/x64.cpp | 5 +- extras/conf_test/x86.cpp | 3 +- extras/tests/JsonDocument/assignment.cpp | 10 ++- extras/tests/JsonDocument/constructor.cpp | 11 +-- extras/tests/JsonDocument/garbageCollect.cpp | 9 +- .../MsgPackSerializer/serializeArray.cpp | 3 + extras/tests/ResourceManager/allocVariant.cpp | 24 +++-- extras/tests/ResourceManager/clear.cpp | 2 +- extras/tests/ResourceManager/size.cpp | 6 +- src/ArduinoJson/Array/ArrayData.hpp | 9 +- src/ArduinoJson/Array/ArrayImpl.hpp | 18 ++-- src/ArduinoJson/Array/ElementProxy.hpp | 4 +- src/ArduinoJson/Array/JsonArray.hpp | 8 +- src/ArduinoJson/Array/JsonArrayConst.hpp | 12 +-- src/ArduinoJson/Array/JsonArrayIterator.hpp | 4 +- src/ArduinoJson/Collection/CollectionData.hpp | 20 ++--- src/ArduinoJson/Collection/CollectionImpl.hpp | 89 +++++++++---------- src/ArduinoJson/Configuration.hpp | 11 ++- src/ArduinoJson/Document/JsonDocument.hpp | 41 +++++---- src/ArduinoJson/Json/JsonDeserializer.hpp | 2 +- src/ArduinoJson/Json/JsonSerializer.hpp | 14 +-- src/ArduinoJson/Json/PrettyJsonSerializer.hpp | 11 +-- src/ArduinoJson/Memory/ResourceManager.hpp | 12 ++- src/ArduinoJson/Memory/VariantPool.hpp | 46 ++++++++-- src/ArduinoJson/Memory/VariantPoolImpl.hpp | 34 +++---- src/ArduinoJson/MsgPack/MsgPackSerializer.hpp | 14 +-- src/ArduinoJson/Namespace.hpp | 2 +- src/ArduinoJson/Object/JsonObject.hpp | 14 +-- src/ArduinoJson/Object/JsonObjectConst.hpp | 20 +++-- src/ArduinoJson/Object/JsonObjectImpl.hpp | 8 +- src/ArduinoJson/Object/JsonObjectIterator.hpp | 4 +- src/ArduinoJson/Object/MemberProxy.hpp | 5 +- src/ArduinoJson/Object/ObjectData.hpp | 10 ++- src/ArduinoJson/Object/ObjectImpl.hpp | 14 +-- src/ArduinoJson/Polyfills/integer.hpp | 14 +-- src/ArduinoJson/Serialization/measure.hpp | 3 +- src/ArduinoJson/Serialization/serialize.hpp | 3 +- src/ArduinoJson/Variant/JsonVariant.hpp | 2 +- src/ArduinoJson/Variant/JsonVariantConst.hpp | 30 +++---- src/ArduinoJson/Variant/VariantData.hpp | 52 +++++------ src/ArduinoJson/Variant/VariantRefBase.hpp | 12 +-- src/ArduinoJson/Variant/VariantSlot.hpp | 32 ++----- 44 files changed, 343 insertions(+), 310 deletions(-) diff --git a/extras/conf_test/avr.cpp b/extras/conf_test/avr.cpp index b2b105e3..e0061eaf 100644 --- a/extras/conf_test/avr.cpp +++ b/extras/conf_test/avr.cpp @@ -4,8 +4,7 @@ static_assert(ARDUINOJSON_ENABLE_PROGMEM == 1, "ARDUINOJSON_ENABLE_PROGMEM"); static_assert(ARDUINOJSON_USE_LONG_LONG == 0, "ARDUINOJSON_USE_LONG_LONG"); -static_assert(ARDUINOJSON_SLOT_OFFSET_SIZE == 1, - "ARDUINOJSON_SLOT_OFFSET_SIZE"); +static_assert(ARDUINOJSON_SLOT_ID_SIZE == 1, "ARDUINOJSON_SLOT_ID_SIZE"); static_assert(ARDUINOJSON_LITTLE_ENDIAN == 1, "ARDUINOJSON_LITTLE_ENDIAN"); diff --git a/extras/conf_test/esp8266.cpp b/extras/conf_test/esp8266.cpp index caf70b2a..b2e6d06f 100644 --- a/extras/conf_test/esp8266.cpp +++ b/extras/conf_test/esp8266.cpp @@ -2,8 +2,7 @@ static_assert(ARDUINOJSON_USE_LONG_LONG == 1, "ARDUINOJSON_USE_LONG_LONG"); -static_assert(ARDUINOJSON_SLOT_OFFSET_SIZE == 2, - "ARDUINOJSON_SLOT_OFFSET_SIZE"); +static_assert(ARDUINOJSON_SLOT_ID_SIZE == 2, "ARDUINOJSON_SLOT_ID_SIZE"); static_assert(ARDUINOJSON_LITTLE_ENDIAN == 1, "ARDUINOJSON_LITTLE_ENDIAN"); diff --git a/extras/conf_test/x64.cpp b/extras/conf_test/x64.cpp index 97838e34..2b533bf7 100644 --- a/extras/conf_test/x64.cpp +++ b/extras/conf_test/x64.cpp @@ -2,14 +2,13 @@ static_assert(ARDUINOJSON_USE_LONG_LONG == 1, "ARDUINOJSON_USE_LONG_LONG"); -static_assert(ARDUINOJSON_SLOT_OFFSET_SIZE == 4, - "ARDUINOJSON_SLOT_OFFSET_SIZE"); +static_assert(ARDUINOJSON_SLOT_ID_SIZE == 4, "ARDUINOJSON_SLOT_ID_SIZE"); static_assert(ARDUINOJSON_LITTLE_ENDIAN == 1, "ARDUINOJSON_LITTLE_ENDIAN"); static_assert(ARDUINOJSON_USE_DOUBLE == 1, "ARDUINOJSON_USE_DOUBLE"); -static_assert(sizeof(ArduinoJson::detail::VariantSlot) == 32, +static_assert(sizeof(ArduinoJson::detail::VariantSlot) == 24, "sizeof(VariantSlot)"); int main() {} diff --git a/extras/conf_test/x86.cpp b/extras/conf_test/x86.cpp index f3dab30f..a9874efd 100644 --- a/extras/conf_test/x86.cpp +++ b/extras/conf_test/x86.cpp @@ -2,8 +2,7 @@ static_assert(ARDUINOJSON_USE_LONG_LONG == 1, "ARDUINOJSON_USE_LONG_LONG"); -static_assert(ARDUINOJSON_SLOT_OFFSET_SIZE == 2, - "ARDUINOJSON_SLOT_OFFSET_SIZE"); +static_assert(ARDUINOJSON_SLOT_ID_SIZE == 2, "ARDUINOJSON_SLOT_ID_SIZE"); static_assert(ARDUINOJSON_LITTLE_ENDIAN == 1, "ARDUINOJSON_LITTLE_ENDIAN"); diff --git a/extras/tests/JsonDocument/assignment.cpp b/extras/tests/JsonDocument/assignment.cpp index e374a6c9..173ecef9 100644 --- a/extras/tests/JsonDocument/assignment.cpp +++ b/extras/tests/JsonDocument/assignment.cpp @@ -31,7 +31,8 @@ TEST_CASE("JsonDocument assignment") { } SECTION("Copy assignment reallocates when capacity is smaller") { - JsonDocument doc1(4096, &spyingAllocator); + const size_t capacity = 100 * sizeof(ArduinoJson::detail::VariantSlot); + JsonDocument doc1(capacity, &spyingAllocator); deserializeJson(doc1, "[{\"hello\":\"world\"}]"); JsonDocument doc2(sizeofArray(1), &spyingAllocator); spyingAllocator.clearLog(); @@ -41,14 +42,15 @@ TEST_CASE("JsonDocument assignment") { REQUIRE(doc2.as() == "[{\"hello\":\"world\"}]"); REQUIRE(spyingAllocator.log() == AllocatorLog() << AllocatorLog::Deallocate(sizeofArray(1)) - << AllocatorLog::Allocate(4096) + << AllocatorLog::Allocate(capacity) << AllocatorLog::Allocate(sizeofString(5)) // hello << AllocatorLog::Allocate(sizeofString(5)) // world ); } SECTION("Copy assignment reallocates when capacity is larger") { - JsonDocument doc1(1024, &spyingAllocator); + const size_t capacity1 = 100 * sizeof(ArduinoJson::detail::VariantSlot); + JsonDocument doc1(capacity1, &spyingAllocator); deserializeJson(doc1, "{\"hello\":\"world\"}"); JsonDocument doc2(4096, &spyingAllocator); spyingAllocator.clearLog(); @@ -58,7 +60,7 @@ TEST_CASE("JsonDocument assignment") { REQUIRE(doc2.as() == "{\"hello\":\"world\"}"); REQUIRE(spyingAllocator.log() == AllocatorLog() << AllocatorLog::Deallocate(4096) - << AllocatorLog::Allocate(1024) + << AllocatorLog::Allocate(capacity1) << AllocatorLog::Allocate(sizeofString(5)) // hello << AllocatorLog::Allocate(sizeofString(5)) // world ); diff --git a/extras/tests/JsonDocument/constructor.cpp b/extras/tests/JsonDocument/constructor.cpp index 5e733bd7..52febf30 100644 --- a/extras/tests/JsonDocument/constructor.cpp +++ b/extras/tests/JsonDocument/constructor.cpp @@ -22,8 +22,9 @@ TEST_CASE("JsonDocument constructor") { } SECTION("JsonDocument(const JsonDocument&)") { + const size_t capacity = 100 * sizeof(ArduinoJson::detail::VariantSlot); { - JsonDocument doc1(4096, &spyingAllocator); + JsonDocument doc1(capacity, &spyingAllocator); doc1.set(std::string("The size of this string is 32!!")); JsonDocument doc2(doc1); @@ -32,14 +33,14 @@ TEST_CASE("JsonDocument constructor") { REQUIRE(doc2.as() == "The size of this string is 32!!"); } REQUIRE(spyingAllocator.log() == - AllocatorLog() << AllocatorLog::Allocate(4096) + AllocatorLog() << AllocatorLog::Allocate(capacity) << AllocatorLog::Allocate(sizeofString(31)) - << AllocatorLog::Allocate(4096) + << AllocatorLog::Allocate(capacity) << AllocatorLog::Allocate(sizeofString(31)) << AllocatorLog::Deallocate(sizeofString(31)) - << AllocatorLog::Deallocate(4096) + << AllocatorLog::Deallocate(capacity) << AllocatorLog::Deallocate(sizeofString(31)) - << AllocatorLog::Deallocate(4096)); + << AllocatorLog::Deallocate(capacity)); } SECTION("JsonDocument(JsonDocument&&)") { diff --git a/extras/tests/JsonDocument/garbageCollect.cpp b/extras/tests/JsonDocument/garbageCollect.cpp index 17c60ca1..15e9ee89 100644 --- a/extras/tests/JsonDocument/garbageCollect.cpp +++ b/extras/tests/JsonDocument/garbageCollect.cpp @@ -13,9 +13,10 @@ using ArduinoJson::detail::sizeofObject; using ArduinoJson::detail::sizeofString; TEST_CASE("JsonDocument::garbageCollect()") { + const size_t capacity = 100 * sizeof(ArduinoJson::detail::VariantSlot); ControllableAllocator controllableAllocator; SpyingAllocator spyingAllocator(&controllableAllocator); - JsonDocument doc(4096, &spyingAllocator); + JsonDocument doc(capacity, &spyingAllocator); SECTION("when allocation succeeds") { deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}"); @@ -29,10 +30,10 @@ TEST_CASE("JsonDocument::garbageCollect()") { REQUIRE(doc.memoryUsage() == sizeofObject(1) + sizeofString(7)); REQUIRE(doc.as() == "{\"dancing\":2}"); REQUIRE(spyingAllocator.log() == - AllocatorLog() << AllocatorLog::Allocate(4096) + AllocatorLog() << AllocatorLog::Allocate(capacity) << AllocatorLog::Allocate(sizeofString(7)) << AllocatorLog::Deallocate(sizeofString(7)) - << AllocatorLog::Deallocate(4096)); + << AllocatorLog::Deallocate(capacity)); } SECTION("when allocation fails") { @@ -49,7 +50,7 @@ TEST_CASE("JsonDocument::garbageCollect()") { REQUIRE(doc.as() == "{\"dancing\":2}"); REQUIRE(spyingAllocator.log() == - AllocatorLog() << AllocatorLog::AllocateFail(4096) + AllocatorLog() << AllocatorLog::AllocateFail(capacity) << AllocatorLog::AllocateFail(sizeofString(7))); } } diff --git a/extras/tests/MsgPackSerializer/serializeArray.cpp b/extras/tests/MsgPackSerializer/serializeArray.cpp index bd6c4102..d2a0f18f 100644 --- a/extras/tests/MsgPackSerializer/serializeArray.cpp +++ b/extras/tests/MsgPackSerializer/serializeArray.cpp @@ -2,6 +2,8 @@ // Copyright © 2014-2023, Benoit BLANCHON // MIT License +#define ARDUINOJSON_SLOT_ID_SIZE 4 // required to reach 65536 elements + #include #include @@ -55,6 +57,7 @@ TEST_CASE("serialize MsgPack array") { const char* nil = 0; for (int i = 0; i < 65536; i++) array.add(nil); + REQUIRE(array.size() == 65536); check(array, std::string("\xDD\x00\x01\x00\x00", 5) + std::string(65536, '\xc0')); diff --git a/extras/tests/ResourceManager/allocVariant.cpp b/extras/tests/ResourceManager/allocVariant.cpp index 3a87badc..34bea43c 100644 --- a/extras/tests/ResourceManager/allocVariant.cpp +++ b/extras/tests/ResourceManager/allocVariant.cpp @@ -11,13 +11,13 @@ using namespace ArduinoJson::detail; -TEST_CASE("ResourceManager::allocVariant()") { +TEST_CASE("ResourceManager::allocSlot()") { SECTION("Returns different pointer") { ResourceManager resources(4096); - VariantSlot* s1 = resources.allocVariant(); + VariantSlot* s1 = resources.allocSlot(); REQUIRE(s1 != 0); - VariantSlot* s2 = resources.allocVariant(); + VariantSlot* s2 = resources.allocSlot(); REQUIRE(s2 != 0); REQUIRE(s1 != s2); @@ -26,27 +26,33 @@ TEST_CASE("ResourceManager::allocVariant()") { SECTION("Returns aligned pointers") { ResourceManager resources(4096); - REQUIRE(isAligned(resources.allocVariant())); - REQUIRE(isAligned(resources.allocVariant())); + REQUIRE(isAligned(resources.allocSlot().operator VariantSlot*())); + REQUIRE(isAligned(resources.allocSlot().operator VariantSlot*())); } SECTION("Returns zero if capacity is 0") { ResourceManager resources(0); - REQUIRE(resources.allocVariant() == 0); + auto variant = resources.allocSlot(); + REQUIRE(variant.id() == NULL_SLOT); + REQUIRE(static_cast(variant) == nullptr); } SECTION("Returns zero if buffer is null") { ResourceManager resources(4096, FailingAllocator::instance()); - REQUIRE(resources.allocVariant() == 0); + auto variant = resources.allocSlot(); + REQUIRE(variant.id() == NULL_SLOT); + REQUIRE(static_cast(variant) == nullptr); } SECTION("Returns zero if capacity is insufficient") { ResourceManager resources(sizeof(VariantSlot)); - resources.allocVariant(); + resources.allocSlot(); - REQUIRE(resources.allocVariant() == 0); + auto variant = resources.allocSlot(); + REQUIRE(variant.id() == NULL_SLOT); + REQUIRE(static_cast(variant) == nullptr); } } diff --git a/extras/tests/ResourceManager/clear.cpp b/extras/tests/ResourceManager/clear.cpp index a20c22f1..8276217f 100644 --- a/extras/tests/ResourceManager/clear.cpp +++ b/extras/tests/ResourceManager/clear.cpp @@ -15,7 +15,7 @@ TEST_CASE("ResourceManager::clear()") { ResourceManager resources(poolCapacity); SECTION("Discards allocated variants") { - resources.allocVariant(); + resources.allocSlot(); resources.clear(); REQUIRE(resources.size() == 0); diff --git a/extras/tests/ResourceManager/size.cpp b/extras/tests/ResourceManager/size.cpp index 9927b0bb..240cf75a 100644 --- a/extras/tests/ResourceManager/size.cpp +++ b/extras/tests/ResourceManager/size.cpp @@ -9,7 +9,7 @@ using namespace ArduinoJson::detail; TEST_CASE("ResourceManager::capacity()") { - const size_t capacity = 64; + const size_t capacity = 4 * sizeof(VariantSlot); ResourceManager resources(capacity); REQUIRE(capacity == resources.capacity()); } @@ -25,10 +25,10 @@ TEST_CASE("ResourceManager::size()") { const size_t variantCount = resources.capacity() / sizeof(VariantSlot); for (size_t i = 0; i < variantCount; i++) - resources.allocVariant(); + resources.allocSlot(); size_t size = resources.size(); - resources.allocVariant(); + resources.allocSlot(); REQUIRE(size == resources.size()); } diff --git a/src/ArduinoJson/Array/ArrayData.hpp b/src/ArduinoJson/Array/ArrayData.hpp index 42df1276..5acca0aa 100644 --- a/src/ArduinoJson/Array/ArrayData.hpp +++ b/src/ArduinoJson/Array/ArrayData.hpp @@ -22,12 +22,13 @@ class ArrayData : public CollectionData { VariantData* getOrAddElement(size_t index, ResourceManager* resources); - VariantData* getElement(size_t index) const; + VariantData* getElement(size_t index, const ResourceManager* resources) const; - static VariantData* getElement(const ArrayData* array, size_t index) { + static VariantData* getElement(const ArrayData* array, size_t index, + const ResourceManager* resources) { if (!array) return nullptr; - return array->getElement(index); + return array->getElement(index, resources); } void removeElement(size_t index, ResourceManager* resources); @@ -50,7 +51,7 @@ class ArrayData : public CollectionData { } private: - iterator at(size_t index) const; + iterator at(size_t index, const ResourceManager* resources) const; }; ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Array/ArrayImpl.hpp b/src/ArduinoJson/Array/ArrayImpl.hpp index 72eff183..94a9623e 100644 --- a/src/ArduinoJson/Array/ArrayImpl.hpp +++ b/src/ArduinoJson/Array/ArrayImpl.hpp @@ -9,10 +9,11 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE -inline ArrayData::iterator ArrayData::at(size_t index) const { - auto it = createIterator(); +inline ArrayData::iterator ArrayData::at( + size_t index, const ResourceManager* resources) const { + auto it = createIterator(resources); while (!it.done() && index) { - it.next(); + it.next(resources); --index; } return it; @@ -20,9 +21,9 @@ inline ArrayData::iterator ArrayData::at(size_t index) const { inline VariantData* ArrayData::getOrAddElement(size_t index, ResourceManager* resources) { - auto it = createIterator(); + auto it = createIterator(resources); while (!it.done() && index > 0) { - it.next(); + it.next(resources); index--; } if (it.done()) @@ -37,12 +38,13 @@ inline VariantData* ArrayData::getOrAddElement(size_t index, return element; } -inline VariantData* ArrayData::getElement(size_t index) const { - return at(index).data(); +inline VariantData* ArrayData::getElement( + size_t index, const ResourceManager* resources) const { + return at(index, resources).data(); } inline void ArrayData::removeElement(size_t index, ResourceManager* resources) { - remove(at(index), resources); + remove(at(index, resources), resources); } ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Array/ElementProxy.hpp b/src/ArduinoJson/Array/ElementProxy.hpp index fba613fc..e9ca8096 100644 --- a/src/ArduinoJson/Array/ElementProxy.hpp +++ b/src/ArduinoJson/Array/ElementProxy.hpp @@ -45,7 +45,9 @@ class ElementProxy : public VariantRefBase>, } FORCE_INLINE VariantData* getData() const { - return VariantData::getElement(VariantAttorney::getData(upstream_), index_); + return VariantData::getElement( + VariantAttorney::getData(upstream_), index_, + VariantAttorney::getResourceManager(upstream_)); } FORCE_INLINE VariantData* getOrCreateData() const { diff --git a/src/ArduinoJson/Array/JsonArray.hpp b/src/ArduinoJson/Array/JsonArray.hpp index c7670b65..46ce1093 100644 --- a/src/ArduinoJson/Array/JsonArray.hpp +++ b/src/ArduinoJson/Array/JsonArray.hpp @@ -68,7 +68,7 @@ class JsonArray : public detail::VariantOperators { FORCE_INLINE iterator begin() const { if (!data_) return iterator(); - return iterator(data_->createIterator(), resources_); + return iterator(data_->createIterator(resources_), resources_); } // Returns an iterator following the last element of the array. @@ -148,19 +148,19 @@ class JsonArray : public detail::VariantOperators { // Returns the number of bytes occupied by the array. // https://arduinojson.org/v6/api/jsonarray/memoryusage/ FORCE_INLINE size_t memoryUsage() const { - return data_ ? data_->memoryUsage() : 0; + return data_ ? data_->memoryUsage(resources_) : 0; } // Returns the depth (nesting level) of the array. // https://arduinojson.org/v6/api/jsonarray/nesting/ FORCE_INLINE size_t nesting() const { - return detail::VariantData::nesting(collectionToVariant(data_)); + return detail::VariantData::nesting(collectionToVariant(data_), resources_); } // Returns the number of elements in the array. // https://arduinojson.org/v6/api/jsonarray/size/ FORCE_INLINE size_t size() const { - return data_ ? data_->size() : 0; + return data_ ? data_->size(resources_) : 0; } private: diff --git a/src/ArduinoJson/Array/JsonArrayConst.hpp b/src/ArduinoJson/Array/JsonArrayConst.hpp index d9816cf8..587728fe 100644 --- a/src/ArduinoJson/Array/JsonArrayConst.hpp +++ b/src/ArduinoJson/Array/JsonArrayConst.hpp @@ -26,7 +26,7 @@ class JsonArrayConst : public detail::VariantOperators { FORCE_INLINE iterator begin() const { if (!data_) return iterator(); - return iterator(data_->createIterator(), resources_); + return iterator(data_->createIterator(resources_), resources_); } // Returns an iterator to the element following the last element of the array. @@ -46,8 +46,8 @@ class JsonArrayConst : public detail::VariantOperators { // Returns the element at the specified index. // https://arduinojson.org/v6/api/jsonarrayconst/subscript/ FORCE_INLINE JsonVariantConst operator[](size_t index) const { - return JsonVariantConst(detail::ArrayData::getElement(data_, index), - resources_); + return JsonVariantConst( + detail::ArrayData::getElement(data_, index, resources_), resources_); } operator JsonVariantConst() const { @@ -69,19 +69,19 @@ class JsonArrayConst : public detail::VariantOperators { // Returns the number of bytes occupied by the array. // https://arduinojson.org/v6/api/jsonarrayconst/memoryusage/ FORCE_INLINE size_t memoryUsage() const { - return data_ ? data_->memoryUsage() : 0; + return data_ ? data_->memoryUsage(resources_) : 0; } // Returns the depth (nesting level) of the array. // https://arduinojson.org/v6/api/jsonarrayconst/nesting/ FORCE_INLINE size_t nesting() const { - return detail::VariantData::nesting(collectionToVariant(data_)); + return detail::VariantData::nesting(collectionToVariant(data_), resources_); } // Returns the number of elements in the array. // https://arduinojson.org/v6/api/jsonarrayconst/size/ FORCE_INLINE size_t size() const { - return data_ ? data_->size() : 0; + return data_ ? data_->size(resources_) : 0; } private: diff --git a/src/ArduinoJson/Array/JsonArrayIterator.hpp b/src/ArduinoJson/Array/JsonArrayIterator.hpp index 71aeed9b..e29342f5 100644 --- a/src/ArduinoJson/Array/JsonArrayIterator.hpp +++ b/src/ArduinoJson/Array/JsonArrayIterator.hpp @@ -50,7 +50,7 @@ class JsonArrayIterator { } JsonArrayIterator& operator++() { - iterator_.next(); + iterator_.next(resources_); return *this; } @@ -84,7 +84,7 @@ class JsonArrayConstIterator { } JsonArrayConstIterator& operator++() { - iterator_.next(); + iterator_.next(resources_); return *this; } diff --git a/src/ArduinoJson/Collection/CollectionData.hpp b/src/ArduinoJson/Collection/CollectionData.hpp index 51bb2175..ba7374fc 100644 --- a/src/ArduinoJson/Collection/CollectionData.hpp +++ b/src/ArduinoJson/Collection/CollectionData.hpp @@ -20,7 +20,7 @@ class CollectionIterator { public: CollectionIterator() : slot_(nullptr) {} - void next(); + void next(const ResourceManager* resources); bool done() const { return slot_ == nullptr; @@ -70,8 +70,8 @@ class CollectionIterator { }; class CollectionData { - VariantSlot* head_ = 0; - VariantSlot* tail_ = 0; + SlotId head_ = NULL_SLOT; + SlotId tail_ = NULL_SLOT; public: // Placement new @@ -83,13 +83,13 @@ class CollectionData { using iterator = CollectionIterator; - iterator createIterator() const { - return iterator(head_); + iterator createIterator(const ResourceManager* resources) const { + return iterator(resources->getSlot(head_)); } - size_t memoryUsage() const; - size_t size() const; - size_t nesting() const; + size_t memoryUsage(const ResourceManager*) const; + size_t size(const ResourceManager*) const; + size_t nesting(const ResourceManager*) const; void clear(ResourceManager* resources); @@ -99,8 +99,6 @@ class CollectionData { collection->clear(resources); } - void movePointers(ptrdiff_t variantDistance); - void remove(iterator it, ResourceManager* resources); static void remove(CollectionData* collection, iterator it, @@ -113,7 +111,7 @@ class CollectionData { iterator addSlot(ResourceManager*); private: - VariantSlot* getPreviousSlot(VariantSlot*) const; + SlotWithId getPreviousSlot(VariantSlot*, const ResourceManager*) const; static void releaseSlot(VariantSlot*, ResourceManager*); }; diff --git a/src/ArduinoJson/Collection/CollectionImpl.hpp b/src/ArduinoJson/Collection/CollectionImpl.hpp index 0b9ec9af..5ae94105 100644 --- a/src/ArduinoJson/Collection/CollectionImpl.hpp +++ b/src/ArduinoJson/Collection/CollectionImpl.hpp @@ -34,102 +34,95 @@ inline bool CollectionIterator::ownsKey() const { return slot_->ownsKey(); } -inline void CollectionIterator::next() { +inline void CollectionIterator::next(const ResourceManager* resources) { ARDUINOJSON_ASSERT(slot_ != nullptr); - slot_ = slot_->next(); + auto nextId = slot_->next(); + if (nextId != NULL_SLOT) + slot_ = resources->getSlot(nextId); + else + slot_ = nullptr; } inline CollectionData::iterator CollectionData::addSlot( ResourceManager* resources) { - auto slot = resources->allocVariant(); + auto slot = resources->allocSlot(); if (!slot) return nullptr; - if (tail_) { - tail_->setNextNotNull(slot); - tail_ = slot; + if (tail_ != NULL_SLOT) { + auto tail = resources->getSlot(tail_); + tail->setNext(slot.id()); + tail_ = slot.id(); } else { - head_ = slot; - tail_ = slot; + head_ = slot.id(); + tail_ = slot.id(); } - return slot; + return iterator(slot); } inline void CollectionData::clear(ResourceManager* resources) { - for (auto slot = head_; slot; slot = slot->next()) - releaseSlot(slot, resources); - head_ = 0; - tail_ = 0; + for (auto it = createIterator(resources); !it.done(); it.next(resources)) + releaseSlot(it.slot_, resources); + head_ = NULL_SLOT; + tail_ = NULL_SLOT; } -inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const { - VariantSlot* current = head_; - while (current) { - VariantSlot* next = current->next(); - if (next == target) - return current; - current = next; +inline SlotWithId CollectionData::getPreviousSlot( + VariantSlot* target, const ResourceManager* resources) const { + auto prev = SlotWithId(); + auto currentId = head_; + while (currentId != NULL_SLOT) { + auto currentSlot = resources->getSlot(currentId); + if (currentSlot == target) + return prev; + prev = SlotWithId(currentSlot, currentId); + currentId = currentSlot->next(); } - return 0; + return SlotWithId(); } inline void CollectionData::remove(iterator it, ResourceManager* resources) { if (it.done()) return; auto curr = it.slot_; - auto prev = getPreviousSlot(curr); + auto prev = getPreviousSlot(curr, resources); auto next = curr->next(); if (prev) prev->setNext(next); else head_ = next; - if (!next) - tail_ = prev; + if (next == NULL_SLOT) + tail_ = prev.id(); releaseSlot(curr, resources); } -inline size_t CollectionData::memoryUsage() const { +inline size_t CollectionData::memoryUsage( + const ResourceManager* resources) const { size_t total = 0; - for (auto it = createIterator(); !it.done(); it.next()) { - total += sizeof(VariantSlot) + it->memoryUsage(); + for (auto it = createIterator(resources); !it.done(); it.next(resources)) { + total += sizeof(VariantSlot) + it->memoryUsage(resources); if (it.ownsKey()) total += sizeofString(strlen(it.key())); } return total; } -inline size_t CollectionData::nesting() const { +inline size_t CollectionData::nesting(const ResourceManager* resources) const { size_t maxChildNesting = 0; - for (auto it = createIterator(); !it.done(); it.next()) { - size_t childNesting = it->nesting(); + for (auto it = createIterator(resources); !it.done(); it.next(resources)) { + size_t childNesting = it->nesting(resources); if (childNesting > maxChildNesting) maxChildNesting = childNesting; } return maxChildNesting + 1; } -inline size_t CollectionData::size() const { +inline size_t CollectionData::size(const ResourceManager* resources) const { size_t count = 0; - for (auto it = createIterator(); !it.done(); it.next()) + for (auto it = createIterator(resources); !it.done(); it.next(resources)) count++; return count; } -template -inline void movePointer(T*& p, ptrdiff_t offset) { - if (!p) - return; - p = reinterpret_cast( - reinterpret_cast(reinterpret_cast(p) + offset)); - ARDUINOJSON_ASSERT(isAligned(p)); -} - -inline void CollectionData::movePointers(ptrdiff_t variantDistance) { - movePointer(head_, variantDistance); - movePointer(tail_, variantDistance); - for (VariantSlot* slot = head_; slot; slot = slot->next()) - slot->data()->movePointers(variantDistance); -} - inline void CollectionData::releaseSlot(VariantSlot* slot, ResourceManager* resources) { ARDUINOJSON_ASSERT(slot != nullptr); diff --git a/src/ArduinoJson/Configuration.hpp b/src/ArduinoJson/Configuration.hpp index 9d3485bc..63cc861e 100644 --- a/src/ArduinoJson/Configuration.hpp +++ b/src/ArduinoJson/Configuration.hpp @@ -75,19 +75,18 @@ # define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10 #endif -// Number of bits to store the pointer to next node -// (saves RAM but limits the number of values in a document) -#ifndef ARDUINOJSON_SLOT_OFFSET_SIZE +// Number of bits to store the variant identifier +#ifndef ARDUINOJSON_SLOT_ID_SIZE # if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ <= 2 // Address space == 16-bit => max 127 values -# define ARDUINOJSON_SLOT_OFFSET_SIZE 1 +# define ARDUINOJSON_SLOT_ID_SIZE 1 # elif defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ >= 8 || \ defined(_WIN64) && _WIN64 // Address space == 64-bit => max 2147483647 values -# define ARDUINOJSON_SLOT_OFFSET_SIZE 4 +# define ARDUINOJSON_SLOT_ID_SIZE 4 # else // Address space == 32-bit => max 32767 values -# define ARDUINOJSON_SLOT_OFFSET_SIZE 2 +# define ARDUINOJSON_SLOT_ID_SIZE 2 # endif #endif diff --git a/src/ArduinoJson/Document/JsonDocument.hpp b/src/ArduinoJson/Document/JsonDocument.hpp index f8286b94..cb7e9813 100644 --- a/src/ArduinoJson/Document/JsonDocument.hpp +++ b/src/ArduinoJson/Document/JsonDocument.hpp @@ -86,8 +86,7 @@ class JsonDocument : public detail::VariantOperators { // Reduces the capacity of the memory pool to match the current usage. // https://arduinojson.org/v6/api/JsonDocument/shrinktofit/ void shrinkToFit() { - auto offset = resources_.shrinkToFit(); - data_.movePointers(offset); + resources_.shrinkToFit(); } // Reclaims the memory leaked when removing and replacing values. @@ -105,14 +104,14 @@ class JsonDocument : public detail::VariantOperators { // https://arduinojson.org/v6/api/jsondocument/as/ template T as() { - return getVariant().template as(); + return getSlot().template as(); } // Casts the root to the specified type. // https://arduinojson.org/v6/api/jsondocument/as/ template T as() const { - return getVariant().template as(); + return getSlot().template as(); } // Empties the document and resets the memory pool @@ -126,20 +125,20 @@ class JsonDocument : public detail::VariantOperators { // https://arduinojson.org/v6/api/jsondocument/is/ template bool is() { - return getVariant().template is(); + return getSlot().template is(); } // Returns true if the root is of the specified type. // https://arduinojson.org/v6/api/jsondocument/is/ template bool is() const { - return getVariant().template is(); + return getSlot().template is(); } // Returns true if the root is null. // https://arduinojson.org/v6/api/jsondocument/isnull/ bool isNull() const { - return getVariant().isNull(); + return getSlot().isNull(); } // Returns the number of used bytes in the memory pool. @@ -157,13 +156,13 @@ class JsonDocument : public detail::VariantOperators { // Returns the depth (nesting level) of the array. // https://arduinojson.org/v6/api/jsondocument/nesting/ size_t nesting() const { - return data_.nesting(); + return data_.nesting(&resources_); } // Returns the number of elements in the root array or object. // https://arduinojson.org/v6/api/jsondocument/size/ size_t size() const { - return data_.size(); + return data_.size(&resources_); } // Copies the specified document. @@ -186,7 +185,7 @@ class JsonDocument : public detail::VariantOperators { template typename detail::VariantTo::type to() { clear(); - return getVariant().template to(); + return getSlot().template to(); } // Creates an array and appends it to the root array. @@ -233,14 +232,14 @@ class JsonDocument : public detail::VariantOperators { // https://arduinojson.org/v6/api/jsondocument/containskey/ template bool containsKey(TChar* key) const { - return data_.getMember(detail::adaptString(key)) != 0; + return data_.getMember(detail::adaptString(key), &resources_) != 0; } // Returns true if the root object contains the specified key. // https://arduinojson.org/v6/api/jsondocument/containskey/ template bool containsKey(const TString& key) const { - return data_.getMember(detail::adaptString(key)) != 0; + return data_.getMember(detail::adaptString(key), &resources_) != 0; } // Gets or sets a root object's member. @@ -269,8 +268,8 @@ class JsonDocument : public detail::VariantOperators { FORCE_INLINE typename detail::enable_if::value, JsonVariantConst>::type operator[](const TString& key) const { - return JsonVariantConst(data_.getMember(detail::adaptString(key)), - &resources_); + return JsonVariantConst( + data_.getMember(detail::adaptString(key), &resources_), &resources_); } // Gets a root object's member. @@ -279,8 +278,8 @@ class JsonDocument : public detail::VariantOperators { FORCE_INLINE typename detail::enable_if::value, JsonVariantConst>::type operator[](TChar* key) const { - return JsonVariantConst(data_.getMember(detail::adaptString(key)), - &resources_); + return JsonVariantConst( + data_.getMember(detail::adaptString(key), &resources_), &resources_); } // Gets or sets a root array's element. @@ -292,7 +291,7 @@ class JsonDocument : public detail::VariantOperators { // Gets a root array's member. // https://arduinojson.org/v6/api/jsondocument/subscript/ FORCE_INLINE JsonVariantConst operator[](size_t index) const { - return JsonVariantConst(data_.getElement(index), &resources_); + return JsonVariantConst(data_.getElement(index, &resources_), &resources_); } // Appends a new (null) element to the root array. @@ -345,19 +344,19 @@ class JsonDocument : public detail::VariantOperators { } FORCE_INLINE operator JsonVariant() { - return getVariant(); + return getSlot(); } FORCE_INLINE operator JsonVariantConst() const { - return getVariant(); + return getSlot(); } private: - JsonVariant getVariant() { + JsonVariant getSlot() { return JsonVariant(&data_, &resources_); } - JsonVariantConst getVariant() const { + JsonVariantConst getSlot() const { return JsonVariantConst(&data_, &resources_); } diff --git a/src/ArduinoJson/Json/JsonDeserializer.hpp b/src/ArduinoJson/Json/JsonDeserializer.hpp index 8e4b8b9d..05d58171 100644 --- a/src/ArduinoJson/Json/JsonDeserializer.hpp +++ b/src/ArduinoJson/Json/JsonDeserializer.hpp @@ -273,7 +273,7 @@ class JsonDeserializer { TFilter memberFilter = filter[key.c_str()]; if (memberFilter.allow()) { - auto member = object.getMember(adaptString(key.c_str())); + auto member = object.getMember(adaptString(key.c_str()), resources_); if (!member) { // Save key in memory pool. auto savedKey = stringBuilder_.save(); diff --git a/src/ArduinoJson/Json/JsonSerializer.hpp b/src/ArduinoJson/Json/JsonSerializer.hpp index c2eeab83..45243cba 100644 --- a/src/ArduinoJson/Json/JsonSerializer.hpp +++ b/src/ArduinoJson/Json/JsonSerializer.hpp @@ -16,17 +16,18 @@ class JsonSerializer : public VariantDataVisitor { public: static const bool producesText = true; - JsonSerializer(TWriter writer) : formatter_(writer) {} + JsonSerializer(TWriter writer, const ResourceManager* resources) + : formatter_(writer), resources_(resources) {} FORCE_INLINE size_t visit(const ArrayData& array) { write('['); - auto it = array.createIterator(); + auto it = array.createIterator(resources_); while (!it.done()) { it->accept(*this); - it.next(); + it.next(resources_); if (it.done()) break; @@ -40,14 +41,14 @@ class JsonSerializer : public VariantDataVisitor { size_t visit(const ObjectData& object) { write('{'); - auto it = object.createIterator(); + auto it = object.createIterator(resources_); while (!it.done()) { formatter_.writeString(it.key()); write(':'); it->accept(*this); - it.next(); + it.next(resources_); if (it.done()) break; @@ -113,6 +114,9 @@ class JsonSerializer : public VariantDataVisitor { private: TextFormatter formatter_; + + protected: + const ResourceManager* resources_; }; ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Json/PrettyJsonSerializer.hpp b/src/ArduinoJson/Json/PrettyJsonSerializer.hpp index 1a34fe82..4167c9e5 100644 --- a/src/ArduinoJson/Json/PrettyJsonSerializer.hpp +++ b/src/ArduinoJson/Json/PrettyJsonSerializer.hpp @@ -16,10 +16,11 @@ class PrettyJsonSerializer : public JsonSerializer { typedef JsonSerializer base; public: - PrettyJsonSerializer(TWriter writer) : base(writer), nesting_(0) {} + PrettyJsonSerializer(TWriter writer, const ResourceManager* resources) + : base(writer, resources), nesting_(0) {} size_t visit(const ArrayData& array) { - auto it = array.createIterator(); + auto it = array.createIterator(base::resources_); if (!it.done()) { base::write("[\r\n"); nesting_++; @@ -27,7 +28,7 @@ class PrettyJsonSerializer : public JsonSerializer { indent(); it->accept(*this); - it.next(); + it.next(base::resources_); base::write(it.done() ? "\r\n" : ",\r\n"); } nesting_--; @@ -40,7 +41,7 @@ class PrettyJsonSerializer : public JsonSerializer { } size_t visit(const ObjectData& object) { - auto it = object.createIterator(); + auto it = object.createIterator(base::resources_); if (!it.done()) { base::write("{\r\n"); nesting_++; @@ -50,7 +51,7 @@ class PrettyJsonSerializer : public JsonSerializer { base::write(": "); it->accept(*this); - it.next(); + it.next(base::resources_); base::write(it.done() ? "\r\n" : ",\r\n"); } nesting_--; diff --git a/src/ArduinoJson/Memory/ResourceManager.hpp b/src/ArduinoJson/Memory/ResourceManager.hpp index 66b2297e..a2fc4674 100644 --- a/src/ArduinoJson/Memory/ResourceManager.hpp +++ b/src/ArduinoJson/Memory/ResourceManager.hpp @@ -67,13 +67,17 @@ class ResourceManager { return overflowed_; } - VariantSlot* allocVariant() { - auto p = variantPool_.allocVariant(); + SlotWithId allocSlot() { + auto p = variantPool_.allocSlot(); if (!p) overflowed_ = true; return p; } + VariantSlot* getSlot(SlotId id) const { + return variantPool_.getSlot(id); + } + template StringNode* saveString(TAdaptedString str) { if (str.isNull()) @@ -123,8 +127,8 @@ class ResourceManager { stringPool_.clear(allocator_); } - ptrdiff_t shrinkToFit() { - return variantPool_.shrinkToFit(allocator_); + void shrinkToFit() { + variantPool_.shrinkToFit(allocator_); } private: diff --git a/src/ArduinoJson/Memory/VariantPool.hpp b/src/ArduinoJson/Memory/VariantPool.hpp index 3588d1cf..5d0334c4 100644 --- a/src/ArduinoJson/Memory/VariantPool.hpp +++ b/src/ArduinoJson/Memory/VariantPool.hpp @@ -6,10 +6,39 @@ #include #include +#include ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE class VariantSlot; +using SlotId = uint_t::type; +using SlotCount = SlotId; +const SlotId NULL_SLOT = SlotId(-1); + +class SlotWithId { + public: + SlotWithId() : slot_(nullptr), id_(NULL_SLOT) {} + SlotWithId(VariantSlot* slot, SlotId id) : slot_(slot), id_(id) { + ARDUINOJSON_ASSERT((slot == nullptr) == (id == NULL_SLOT)); + } + + SlotId id() const { + return id_; + } + + operator VariantSlot*() { + return slot_; + } + + VariantSlot* operator->() { + ARDUINOJSON_ASSERT(slot_ != nullptr); + return slot_; + } + + private: + VariantSlot* slot_; + SlotId id_; +}; class VariantPool { public: @@ -30,18 +59,19 @@ class VariantPool { void create(size_t cap, Allocator* allocator); void destroy(Allocator* allocator); - VariantSlot* allocVariant(); + SlotWithId allocSlot(); + VariantSlot* getSlot(SlotId id) const; void clear(); - ptrdiff_t shrinkToFit(Allocator*); - size_t capacity() const; - size_t usage() const; + void shrinkToFit(Allocator*); + SlotCount capacity() const; + SlotCount usage() const; - static size_t bytesToSlots(size_t); - static size_t slotsToBytes(size_t); + static SlotCount bytesToSlots(size_t); + static size_t slotsToBytes(SlotCount); private: - size_t capacity_ = 0; - size_t usage_ = 0; + SlotCount capacity_ = 0; + SlotCount usage_ = 0; VariantSlot* slots_ = nullptr; }; diff --git a/src/ArduinoJson/Memory/VariantPoolImpl.hpp b/src/ArduinoJson/Memory/VariantPoolImpl.hpp index 357646a9..39b0a3e1 100644 --- a/src/ArduinoJson/Memory/VariantPoolImpl.hpp +++ b/src/ArduinoJson/Memory/VariantPoolImpl.hpp @@ -28,29 +28,31 @@ inline void VariantPool::destroy(Allocator* allocator) { usage_ = 0; } -inline ptrdiff_t VariantPool::shrinkToFit(Allocator* allocator) { - auto originalPool = slots_; +inline void VariantPool::shrinkToFit(Allocator* allocator) { slots_ = reinterpret_cast( allocator->reallocate(slots_, slotsToBytes(usage_))); - if (slots_) - capacity_ = usage_; - return reinterpret_cast(slots_) - - reinterpret_cast(originalPool); + capacity_ = usage_; } -inline VariantSlot* VariantPool::allocVariant() { +inline SlotWithId VariantPool::allocSlot() { if (!slots_) - return nullptr; - if (usage_ + 1 > capacity_) - return nullptr; - return new (&slots_[usage_++]) VariantSlot; + return {}; + if (usage_ >= capacity_) + return {}; + auto index = usage_++; + auto slot = &slots_[index]; + return {new (slot) VariantSlot, SlotId(index)}; } -inline size_t VariantPool::usage() const { +inline VariantSlot* VariantPool::getSlot(SlotId id) const { + return id == NULL_SLOT ? nullptr : &slots_[id]; +} + +inline SlotCount VariantPool::usage() const { return usage_; } -inline size_t VariantPool::capacity() const { +inline SlotCount VariantPool::capacity() const { return capacity_; } @@ -58,11 +60,11 @@ inline void VariantPool::clear() { usage_ = 0; } -inline size_t VariantPool::bytesToSlots(size_t n) { - return n / sizeof(VariantSlot); +inline SlotCount VariantPool::bytesToSlots(size_t n) { + return static_cast(n / sizeof(VariantSlot)); } -inline size_t VariantPool::slotsToBytes(size_t n) { +inline size_t VariantPool::slotsToBytes(SlotCount n) { return n * sizeof(VariantSlot); } diff --git a/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp b/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp index 71997bf5..1821d3c2 100644 --- a/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp @@ -19,7 +19,8 @@ class MsgPackSerializer : public VariantDataVisitor { public: static const bool producesText = false; - MsgPackSerializer(TWriter writer) : writer_(writer) {} + MsgPackSerializer(TWriter writer, const ResourceManager* resources) + : writer_(writer), resources_(resources) {} template typename enable_if::value && sizeof(T) == 4, @@ -48,7 +49,7 @@ class MsgPackSerializer : public VariantDataVisitor { } size_t visit(const ArrayData& array) { - size_t n = array.size(); + size_t n = array.size(resources_); if (n < 0x10) { writeByte(uint8_t(0x90 + n)); } else if (n < 0x10000) { @@ -58,14 +59,15 @@ class MsgPackSerializer : public VariantDataVisitor { writeByte(0xDD); writeInteger(uint32_t(n)); } - for (auto it = array.createIterator(); !it.done(); it.next()) { + for (auto it = array.createIterator(resources_); !it.done(); + it.next(resources_)) { it->accept(*this); } return bytesWritten(); } size_t visit(const ObjectData& object) { - size_t n = object.size(); + size_t n = object.size(resources_); if (n < 0x10) { writeByte(uint8_t(0x80 + n)); } else if (n < 0x10000) { @@ -75,7 +77,8 @@ class MsgPackSerializer : public VariantDataVisitor { writeByte(0xDF); writeInteger(uint32_t(n)); } - for (auto it = object.createIterator(); !it.done(); it.next()) { + for (auto it = object.createIterator(resources_); !it.done(); + it.next(resources_)) { visit(it.key()); it->accept(*this); } @@ -200,6 +203,7 @@ class MsgPackSerializer : public VariantDataVisitor { } CountingDecorator writer_; + const ResourceManager* resources_; }; ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Namespace.hpp b/src/ArduinoJson/Namespace.hpp index e20390b9..70584c2b 100644 --- a/src/ArduinoJson/Namespace.hpp +++ b/src/ArduinoJson/Namespace.hpp @@ -19,7 +19,7 @@ ARDUINOJSON_ENABLE_INFINITY, \ ARDUINOJSON_ENABLE_COMMENTS, \ ARDUINOJSON_DECODE_UNICODE), \ - ARDUINOJSON_SLOT_OFFSET_SIZE) + ARDUINOJSON_SLOT_ID_SIZE) #endif diff --git a/src/ArduinoJson/Object/JsonObject.hpp b/src/ArduinoJson/Object/JsonObject.hpp index eabff8a7..0d7b312c 100644 --- a/src/ArduinoJson/Object/JsonObject.hpp +++ b/src/ArduinoJson/Object/JsonObject.hpp @@ -56,19 +56,19 @@ class JsonObject : public detail::VariantOperators { // Returns the number of bytes occupied by the object. // https://arduinojson.org/v6/api/jsonobject/memoryusage/ FORCE_INLINE size_t memoryUsage() const { - return data_ ? data_->memoryUsage() : 0; + return data_ ? data_->memoryUsage(resources_) : 0; } // Returns the depth (nesting level) of the object. // https://arduinojson.org/v6/api/jsonobject/nesting/ FORCE_INLINE size_t nesting() const { - return detail::VariantData::nesting(collectionToVariant(data_)); + return detail::VariantData::nesting(collectionToVariant(data_), resources_); } // Returns the number of members in the object. // https://arduinojson.org/v6/api/jsonobject/size/ FORCE_INLINE size_t size() const { - return data_ ? data_->size() : 0; + return data_ ? data_->size(resources_) : 0; } // Returns an iterator to the first key-value pair of the object. @@ -76,7 +76,7 @@ class JsonObject : public detail::VariantOperators { FORCE_INLINE iterator begin() const { if (!data_) return iterator(); - return iterator(data_->createIterator(), resources_); + return iterator(data_->createIterator(resources_), resources_); } // Returns an iterator following the last key-value pair of the object. @@ -158,7 +158,8 @@ class JsonObject : public detail::VariantOperators { FORCE_INLINE typename detail::enable_if::value, bool>::type containsKey(const TString& key) const { - return detail::ObjectData::getMember(data_, detail::adaptString(key)) != 0; + return detail::ObjectData::getMember(data_, detail::adaptString(key), + resources_) != 0; } // Returns true if the object contains the specified key. @@ -167,7 +168,8 @@ class JsonObject : public detail::VariantOperators { FORCE_INLINE typename detail::enable_if::value, bool>::type containsKey(TChar* key) const { - return detail::ObjectData::getMember(data_, detail::adaptString(key)) != 0; + return detail::ObjectData::getMember(data_, detail::adaptString(key), + resources_) != 0; } // Creates an array and adds it to the object. diff --git a/src/ArduinoJson/Object/JsonObjectConst.hpp b/src/ArduinoJson/Object/JsonObjectConst.hpp index 49dcaffc..0a681d47 100644 --- a/src/ArduinoJson/Object/JsonObjectConst.hpp +++ b/src/ArduinoJson/Object/JsonObjectConst.hpp @@ -45,19 +45,19 @@ class JsonObjectConst : public detail::VariantOperators { // Returns the number of bytes occupied by the object. // https://arduinojson.org/v6/api/jsonobjectconst/memoryusage/ FORCE_INLINE size_t memoryUsage() const { - return data_ ? data_->memoryUsage() : 0; + return data_ ? data_->memoryUsage(resources_) : 0; } // Returns the depth (nesting level) of the object. // https://arduinojson.org/v6/api/jsonobjectconst/nesting/ FORCE_INLINE size_t nesting() const { - return detail::VariantData::nesting(collectionToVariant(data_)); + return detail::VariantData::nesting(collectionToVariant(data_), resources_); } // Returns the number of members in the object. // https://arduinojson.org/v6/api/jsonobjectconst/size/ FORCE_INLINE size_t size() const { - return data_ ? data_->size() : 0; + return data_ ? data_->size(resources_) : 0; } // Returns an iterator to the first key-value pair of the object. @@ -65,7 +65,7 @@ class JsonObjectConst : public detail::VariantOperators { FORCE_INLINE iterator begin() const { if (!data_) return iterator(); - return iterator(data_->createIterator(), resources_); + return iterator(data_->createIterator(resources_), resources_); } // Returns an iterator following the last key-value pair of the object. @@ -78,14 +78,16 @@ class JsonObjectConst : public detail::VariantOperators { // https://arduinojson.org/v6/api/jsonobjectconst/containskey/ template FORCE_INLINE bool containsKey(const TString& key) const { - return detail::ObjectData::getMember(data_, detail::adaptString(key)) != 0; + return detail::ObjectData::getMember(data_, detail::adaptString(key), + resources_) != 0; } // Returns true if the object contains the specified key. // https://arduinojson.org/v6/api/jsonobjectconst/containskey/ template FORCE_INLINE bool containsKey(TChar* key) const { - return detail::ObjectData::getMember(data_, detail::adaptString(key)) != 0; + return detail::ObjectData::getMember(data_, detail::adaptString(key), + resources_) != 0; } // Gets the member with specified key. @@ -94,9 +96,9 @@ class JsonObjectConst : public detail::VariantOperators { FORCE_INLINE typename detail::enable_if::value, JsonVariantConst>::type operator[](const TString& key) const { - return JsonVariantConst( - detail::ObjectData::getMember(data_, detail::adaptString(key)), - resources_); + return JsonVariantConst(detail::ObjectData::getMember( + data_, detail::adaptString(key), resources_), + resources_); } // Gets the member with specified key. diff --git a/src/ArduinoJson/Object/JsonObjectImpl.hpp b/src/ArduinoJson/Object/JsonObjectImpl.hpp index 4e0192e3..1a9c14e8 100644 --- a/src/ArduinoJson/Object/JsonObjectImpl.hpp +++ b/src/ArduinoJson/Object/JsonObjectImpl.hpp @@ -54,16 +54,16 @@ template template inline typename enable_if::value, bool>::type VariantRefBase::containsKey(const TString& key) const { - return VariantData::getMember(VariantAttorney::getData(derived()), - adaptString(key)) != 0; + return VariantData::getMember(getData(), adaptString(key), + getResourceManager()) != 0; } template template inline typename enable_if::value, bool>::type VariantRefBase::containsKey(TChar* key) const { - return VariantData::getMember(VariantAttorney::getData(derived()), - adaptString(key)) != 0; + return VariantData::getMember(getData(), adaptString(key), + getResourceManager()) != 0; } template diff --git a/src/ArduinoJson/Object/JsonObjectIterator.hpp b/src/ArduinoJson/Object/JsonObjectIterator.hpp index 75f0c598..3e79e7d3 100644 --- a/src/ArduinoJson/Object/JsonObjectIterator.hpp +++ b/src/ArduinoJson/Object/JsonObjectIterator.hpp @@ -34,7 +34,7 @@ class JsonObjectIterator { } JsonObjectIterator& operator++() { - iterator_.next(); + iterator_.next(resources_); return *this; } @@ -69,7 +69,7 @@ class JsonObjectConstIterator { } JsonObjectConstIterator& operator++() { - iterator_.next(); + iterator_.next(resources_); return *this; } diff --git a/src/ArduinoJson/Object/MemberProxy.hpp b/src/ArduinoJson/Object/MemberProxy.hpp index 85a1d293..3ce5ddb7 100644 --- a/src/ArduinoJson/Object/MemberProxy.hpp +++ b/src/ArduinoJson/Object/MemberProxy.hpp @@ -46,8 +46,9 @@ class MemberProxy } FORCE_INLINE VariantData* getData() const { - return VariantData::getMember(VariantAttorney::getData(upstream_), - adaptString(key_)); + return VariantData::getMember( + VariantAttorney::getData(upstream_), adaptString(key_), + VariantAttorney::getResourceManager(upstream_)); } FORCE_INLINE VariantData* getOrCreateData() const { diff --git a/src/ArduinoJson/Object/ObjectData.hpp b/src/ArduinoJson/Object/ObjectData.hpp index 0aed8619..20222147 100644 --- a/src/ArduinoJson/Object/ObjectData.hpp +++ b/src/ArduinoJson/Object/ObjectData.hpp @@ -43,13 +43,15 @@ class ObjectData : public CollectionData { VariantData* getOrAddMember(TAdaptedString key, ResourceManager* resources); template - VariantData* getMember(TAdaptedString key) const; + VariantData* getMember(TAdaptedString key, + const ResourceManager* resources) const; template - static VariantData* getMember(const ObjectData* object, TAdaptedString key) { + static VariantData* getMember(const ObjectData* object, TAdaptedString key, + const ResourceManager* resources) { if (!object) return nullptr; - return object->getMember(key); + return object->getMember(key, resources); } template @@ -65,7 +67,7 @@ class ObjectData : public CollectionData { private: template - iterator findKey(TAdaptedString key) const; + iterator findKey(TAdaptedString key, const ResourceManager* resources) const; }; ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Object/ObjectImpl.hpp b/src/ArduinoJson/Object/ObjectImpl.hpp index efff78b1..891cdb76 100644 --- a/src/ArduinoJson/Object/ObjectImpl.hpp +++ b/src/ArduinoJson/Object/ObjectImpl.hpp @@ -10,24 +10,26 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template -inline VariantData* ObjectData::getMember(TAdaptedString key) const { - return findKey(key).data(); +inline VariantData* ObjectData::getMember( + TAdaptedString key, const ResourceManager* resources) const { + return findKey(key, resources).data(); } template VariantData* ObjectData::getOrAddMember(TAdaptedString key, ResourceManager* resources) { - auto it = findKey(key); + auto it = findKey(key, resources); if (!it.done()) return it.data(); return addMember(key, resources); } template -inline ObjectData::iterator ObjectData::findKey(TAdaptedString key) const { +inline ObjectData::iterator ObjectData::findKey( + TAdaptedString key, const ResourceManager* resources) const { if (key.isNull()) return iterator(); - for (auto it = createIterator(); !it.done(); it.next()) { + for (auto it = createIterator(resources); !it.done(); it.next(resources)) { if (stringEquals(key, adaptString(it.key()))) return it; } @@ -37,7 +39,7 @@ inline ObjectData::iterator ObjectData::findKey(TAdaptedString key) const { template inline void ObjectData::removeMember(TAdaptedString key, ResourceManager* resources) { - remove(findKey(key), resources); + remove(findKey(key, resources), resources); } ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Polyfills/integer.hpp b/src/ArduinoJson/Polyfills/integer.hpp index 2bfce365..b17fea43 100644 --- a/src/ArduinoJson/Polyfills/integer.hpp +++ b/src/ArduinoJson/Polyfills/integer.hpp @@ -11,21 +11,21 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template -struct int_t; +struct uint_t; template <> -struct int_t<8> { - typedef int8_t type; +struct uint_t<8> { + typedef uint8_t type; }; template <> -struct int_t<16> { - typedef int16_t type; +struct uint_t<16> { + typedef uint16_t type; }; template <> -struct int_t<32> { - typedef int32_t type; +struct uint_t<32> { + typedef uint32_t type; }; ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/src/ArduinoJson/Serialization/measure.hpp b/src/ArduinoJson/Serialization/measure.hpp index 928f38f8..35903cdf 100644 --- a/src/ArduinoJson/Serialization/measure.hpp +++ b/src/ArduinoJson/Serialization/measure.hpp @@ -11,7 +11,8 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template