Rename MemoryPool to ResourceManager

This commit is contained in:
Benoit Blanchon
2023-06-17 16:10:56 +02:00
parent 2a663db3c7
commit 4871380060
36 changed files with 473 additions and 453 deletions

View File

@ -20,7 +20,7 @@ add_subdirectory(JsonDocument)
add_subdirectory(JsonObject) add_subdirectory(JsonObject)
add_subdirectory(JsonSerializer) add_subdirectory(JsonSerializer)
add_subdirectory(JsonVariant) add_subdirectory(JsonVariant)
add_subdirectory(MemoryPool) add_subdirectory(ResourceManager)
add_subdirectory(Misc) add_subdirectory(Misc)
add_subdirectory(MixedConfiguration) add_subdirectory(MixedConfiguration)
add_subdirectory(MsgPackDeserializer) add_subdirectory(MsgPackDeserializer)

View File

@ -308,8 +308,6 @@ TEST_CASE("deserialize JSON array under memory constraints") {
deserializeJson(doc, " [ \"1234567\" ] "); deserializeJson(doc, " [ \"1234567\" ] ");
REQUIRE(sizeofArray(1) + sizeofString(7) == doc.memoryUsage()); REQUIRE(sizeofArray(1) + sizeofString(7) == doc.memoryUsage());
// note: we use a string of 8 bytes to be sure that the MemoryPool
// will not insert bytes to enforce alignement
} }
SECTION("Should clear the JsonArray") { SECTION("Should clear the JsonArray") {

View File

@ -1,51 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Variant/VariantSlot.hpp>
#include <catch.hpp>
#include "Allocators.hpp"
using namespace ArduinoJson::detail;
TEST_CASE("new (pool) VariantSlot()") {
SECTION("Returns different pointer") {
MemoryPool pool(4096);
VariantSlot* s1 = new (&pool) VariantSlot();
REQUIRE(s1 != 0);
VariantSlot* s2 = new (&pool) VariantSlot();
REQUIRE(s2 != 0);
REQUIRE(s1 != s2);
}
SECTION("Returns aligned pointers") {
MemoryPool pool(4096);
REQUIRE(isAligned(new (&pool) VariantSlot()));
REQUIRE(isAligned(new (&pool) VariantSlot()));
}
SECTION("Returns zero if capacity is 0") {
MemoryPool pool(0);
REQUIRE(new (&pool) VariantSlot() == 0);
}
SECTION("Returns zero if buffer is null") {
MemoryPool pool(4096, FailingAllocator::instance());
REQUIRE(new (&pool) VariantSlot() == 0);
}
SECTION("Returns zero if capacity is insufficient") {
MemoryPool pool(sizeof(VariantSlot));
new (&pool) VariantSlot();
REQUIRE(new (&pool) VariantSlot() == 0);
}
}

View File

@ -1,68 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp>
#include <catch.hpp>
#include "Allocators.hpp"
using namespace ArduinoJson::detail;
static StringNode* saveString(MemoryPool& pool, const char* s) {
return pool.saveString(adaptString(s));
}
static StringNode* saveString(MemoryPool& pool, const char* s, size_t n) {
return pool.saveString(adaptString(s, n));
}
TEST_CASE("MemoryPool::saveString()") {
MemoryPool pool(32);
SECTION("Duplicates different strings") {
auto a = saveString(pool, "hello");
auto b = saveString(pool, "world");
REQUIRE(a->data != b->data);
REQUIRE(a->length == 5);
REQUIRE(b->length == 5);
REQUIRE(a->references == 1);
REQUIRE(b->references == 1);
REQUIRE(pool.size() == 2 * sizeofString(5));
}
SECTION("Deduplicates identical strings") {
auto a = saveString(pool, "hello");
auto b = saveString(pool, "hello");
REQUIRE(a == b);
REQUIRE(a->length == 5);
REQUIRE(a->references == 2);
REQUIRE(pool.size() == sizeofString(5));
}
SECTION("Deduplicates identical strings that contain NUL") {
auto a = saveString(pool, "hello\0world", 11);
auto b = saveString(pool, "hello\0world", 11);
REQUIRE(a == b);
REQUIRE(a->length == 11);
REQUIRE(a->references == 2);
REQUIRE(pool.size() == sizeofString(11));
}
SECTION("Don't stop on first NUL") {
auto a = saveString(pool, "hello");
auto b = saveString(pool, "hello\0world", 11);
REQUIRE(a != b);
REQUIRE(a->length == 5);
REQUIRE(b->length == 11);
REQUIRE(a->references == 1);
REQUIRE(b->references == 1);
REQUIRE(pool.size() == sizeofString(5) + sizeofString(11));
}
SECTION("Returns NULL when allocation fails") {
MemoryPool pool2(32, FailingAllocator::instance());
REQUIRE(saveString(pool2, "a") == nullptr);
}
}

View File

@ -1,35 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Variant/VariantSlot.hpp>
#include <catch.hpp>
using namespace ArduinoJson::detail;
TEST_CASE("MemoryPool::capacity()") {
const size_t capacity = 64;
MemoryPool pool(capacity);
REQUIRE(capacity == pool.capacity());
}
TEST_CASE("MemoryPool::size()") {
MemoryPool pool(4096);
SECTION("Initial size is 0") {
REQUIRE(0 == pool.size());
}
SECTION("Doesn't grow when memory pool is full") {
const size_t variantCount = pool.capacity() / sizeof(VariantSlot);
for (size_t i = 0; i < variantCount; i++)
new (&pool) VariantSlot();
size_t size = pool.size();
new (&pool) VariantSlot();
REQUIRE(size == pool.size());
}
}

View File

@ -10,8 +10,8 @@
using namespace ArduinoJson::detail; using namespace ArduinoJson::detail;
static void testCodepoint(uint32_t codepoint, std::string expected) { static void testCodepoint(uint32_t codepoint, std::string expected) {
MemoryPool pool(4096); ResourceManager resources(4096);
StringBuilder str(&pool); StringBuilder str(&resources);
str.startString(); str.startString();
CAPTURE(codepoint); CAPTURE(codepoint);

View File

@ -2,7 +2,7 @@
# Copyright © 2014-2023, Benoit BLANCHON # Copyright © 2014-2023, Benoit BLANCHON
# MIT License # MIT License
add_executable(MemoryPoolTests add_executable(ResourceManagerTests
allocVariant.cpp allocVariant.cpp
clear.cpp clear.cpp
saveString.cpp saveString.cpp
@ -10,9 +10,9 @@ add_executable(MemoryPoolTests
StringBuilder.cpp StringBuilder.cpp
) )
add_test(MemoryPool MemoryPoolTests) add_test(ResourceManager ResourceManagerTests)
set_tests_properties(MemoryPool set_tests_properties(ResourceManager
PROPERTIES PROPERTIES
LABELS "Catch" LABELS "Catch"
) )

View File

@ -12,16 +12,16 @@ using namespace ArduinoJson::detail;
TEST_CASE("StringBuilder") { TEST_CASE("StringBuilder") {
ControllableAllocator controllableAllocator; ControllableAllocator controllableAllocator;
SpyingAllocator spyingAllocator(&controllableAllocator); SpyingAllocator spyingAllocator(&controllableAllocator);
MemoryPool pool(0, &spyingAllocator); ResourceManager resources(0, &spyingAllocator);
SECTION("Empty string") { SECTION("Empty string") {
StringBuilder str(&pool); StringBuilder str(&resources);
str.startString(); str.startString();
str.save(); str.save();
REQUIRE(pool.size() == sizeofString(0)); REQUIRE(resources.size() == sizeofString(0));
REQUIRE(pool.overflowed() == false); REQUIRE(resources.overflowed() == false);
REQUIRE(spyingAllocator.log() == REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31)) AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
<< AllocatorLog::Reallocate(sizeofString(31), << AllocatorLog::Reallocate(sizeofString(31),
@ -29,20 +29,20 @@ TEST_CASE("StringBuilder") {
} }
SECTION("Short string fits in first allocation") { SECTION("Short string fits in first allocation") {
StringBuilder str(&pool); StringBuilder str(&resources);
str.startString(); str.startString();
str.append("hello"); str.append("hello");
REQUIRE(str.isValid() == true); REQUIRE(str.isValid() == true);
REQUIRE(str.str() == "hello"); REQUIRE(str.str() == "hello");
REQUIRE(pool.overflowed() == false); REQUIRE(resources.overflowed() == false);
REQUIRE(spyingAllocator.log() == REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))); AllocatorLog() << AllocatorLog::Allocate(sizeofString(31)));
} }
SECTION("Long string needs reallocation") { SECTION("Long string needs reallocation") {
StringBuilder str(&pool); StringBuilder str(&resources);
str.startString(); str.startString();
str.append( str.append(
@ -53,7 +53,7 @@ TEST_CASE("StringBuilder") {
REQUIRE(str.str() == REQUIRE(str.str() ==
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
"eiusmod tempor incididunt ut labore et dolore magna aliqua."); "eiusmod tempor incididunt ut labore et dolore magna aliqua.");
REQUIRE(pool.overflowed() == false); REQUIRE(resources.overflowed() == false);
REQUIRE(spyingAllocator.log() == REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31)) AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
<< AllocatorLog::Reallocate(sizeofString(31), << AllocatorLog::Reallocate(sizeofString(31),
@ -63,7 +63,7 @@ TEST_CASE("StringBuilder") {
} }
SECTION("Realloc fails") { SECTION("Realloc fails") {
StringBuilder str(&pool); StringBuilder str(&resources);
str.startString(); str.startString();
controllableAllocator.disable(); controllableAllocator.disable();
@ -77,62 +77,62 @@ TEST_CASE("StringBuilder") {
sizeofString(63)) sizeofString(63))
<< AllocatorLog::Deallocate(sizeofString(31))); << AllocatorLog::Deallocate(sizeofString(31)));
REQUIRE(str.isValid() == false); REQUIRE(str.isValid() == false);
REQUIRE(pool.overflowed() == true); REQUIRE(resources.overflowed() == true);
} }
SECTION("Initial allocation fails") { SECTION("Initial allocation fails") {
StringBuilder str(&pool); StringBuilder str(&resources);
controllableAllocator.disable(); controllableAllocator.disable();
str.startString(); str.startString();
REQUIRE(str.isValid() == false); REQUIRE(str.isValid() == false);
REQUIRE(pool.overflowed() == true); REQUIRE(resources.overflowed() == true);
REQUIRE(spyingAllocator.log() == REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31))); AllocatorLog() << AllocatorLog::AllocateFail(sizeofString(31)));
} }
} }
static StringNode* addStringToPool(MemoryPool& pool, const char* s) { static StringNode* addStringToPool(ResourceManager& resources, const char* s) {
StringBuilder str(&pool); StringBuilder str(&resources);
str.startString(); str.startString();
str.append(s); str.append(s);
return str.save(); return str.save();
} }
TEST_CASE("StringBuilder::save() deduplicates strings") { TEST_CASE("StringBuilder::save() deduplicates strings") {
MemoryPool pool(4096); ResourceManager resources(4096);
SECTION("Basic") { SECTION("Basic") {
auto s1 = addStringToPool(pool, "hello"); auto s1 = addStringToPool(resources, "hello");
auto s2 = addStringToPool(pool, "world"); auto s2 = addStringToPool(resources, "world");
auto s3 = addStringToPool(pool, "hello"); auto s3 = addStringToPool(resources, "hello");
REQUIRE(s1 == s3); REQUIRE(s1 == s3);
REQUIRE(s2 != s3); REQUIRE(s2 != s3);
REQUIRE(s1->references == 2); REQUIRE(s1->references == 2);
REQUIRE(s2->references == 1); REQUIRE(s2->references == 1);
REQUIRE(s3->references == 2); REQUIRE(s3->references == 2);
REQUIRE(pool.size() == 2 * sizeofString(5)); REQUIRE(resources.size() == 2 * sizeofString(5));
} }
SECTION("Requires terminator") { SECTION("Requires terminator") {
auto s1 = addStringToPool(pool, "hello world"); auto s1 = addStringToPool(resources, "hello world");
auto s2 = addStringToPool(pool, "hello"); auto s2 = addStringToPool(resources, "hello");
REQUIRE(s2 != s1); REQUIRE(s2 != s1);
REQUIRE(s1->references == 1); REQUIRE(s1->references == 1);
REQUIRE(s2->references == 1); REQUIRE(s2->references == 1);
REQUIRE(pool.size() == sizeofString(11) + sizeofString(5)); REQUIRE(resources.size() == sizeofString(11) + sizeofString(5));
} }
SECTION("Don't overrun") { SECTION("Don't overrun") {
auto s1 = addStringToPool(pool, "hello world"); auto s1 = addStringToPool(resources, "hello world");
auto s2 = addStringToPool(pool, "wor"); auto s2 = addStringToPool(resources, "wor");
REQUIRE(s2 != s1); REQUIRE(s2 != s1);
REQUIRE(s1->references == 1); REQUIRE(s1->references == 1);
REQUIRE(s2->references == 1); REQUIRE(s2->references == 1);
REQUIRE(pool.size() == sizeofString(11) + sizeofString(3)); REQUIRE(resources.size() == sizeofString(11) + sizeofString(3));
} }
} }

View File

@ -0,0 +1,51 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Variant/VariantSlot.hpp>
#include <catch.hpp>
#include "Allocators.hpp"
using namespace ArduinoJson::detail;
TEST_CASE("new (resources) VariantSlot()") {
SECTION("Returns different pointer") {
ResourceManager resources(4096);
VariantSlot* s1 = new (&resources) VariantSlot();
REQUIRE(s1 != 0);
VariantSlot* s2 = new (&resources) VariantSlot();
REQUIRE(s2 != 0);
REQUIRE(s1 != s2);
}
SECTION("Returns aligned pointers") {
ResourceManager resources(4096);
REQUIRE(isAligned(new (&resources) VariantSlot()));
REQUIRE(isAligned(new (&resources) VariantSlot()));
}
SECTION("Returns zero if capacity is 0") {
ResourceManager resources(0);
REQUIRE(new (&resources) VariantSlot() == 0);
}
SECTION("Returns zero if buffer is null") {
ResourceManager resources(4096, FailingAllocator::instance());
REQUIRE(new (&resources) VariantSlot() == 0);
}
SECTION("Returns zero if capacity is insufficient") {
ResourceManager resources(sizeof(VariantSlot));
new (&resources) VariantSlot();
REQUIRE(new (&resources) VariantSlot() == 0);
}
}

View File

@ -2,7 +2,7 @@
// Copyright © 2014-2023, Benoit BLANCHON // Copyright © 2014-2023, Benoit BLANCHON
// MIT License // MIT License
#include <ArduinoJson/Memory/MemoryPool.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp> #include <ArduinoJson/Strings/StringAdapters.hpp>
#include <ArduinoJson/Variant/VariantSlot.hpp> #include <ArduinoJson/Variant/VariantSlot.hpp>
#include <catch.hpp> #include <catch.hpp>
@ -11,22 +11,22 @@ using namespace ArduinoJson::detail;
static const size_t poolCapacity = 512; static const size_t poolCapacity = 512;
TEST_CASE("MemoryPool::clear()") { TEST_CASE("ResourceManager::clear()") {
MemoryPool pool(poolCapacity); ResourceManager resources(poolCapacity);
SECTION("Discards allocated variants") { SECTION("Discards allocated variants") {
new (&pool) VariantSlot(); new (&resources) VariantSlot();
pool.clear(); resources.clear();
REQUIRE(pool.size() == 0); REQUIRE(resources.size() == 0);
} }
SECTION("Discards allocated strings") { SECTION("Discards allocated strings") {
pool.saveString(adaptString("123456789")); resources.saveString(adaptString("123456789"));
REQUIRE(pool.size() == sizeofString(9)); REQUIRE(resources.size() == sizeofString(9));
pool.clear(); resources.clear();
REQUIRE(pool.size() == 0); REQUIRE(resources.size() == 0);
} }
} }

View File

@ -0,0 +1,69 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp>
#include <catch.hpp>
#include "Allocators.hpp"
using namespace ArduinoJson::detail;
static StringNode* saveString(ResourceManager& resources, const char* s) {
return resources.saveString(adaptString(s));
}
static StringNode* saveString(ResourceManager& resources, const char* s,
size_t n) {
return resources.saveString(adaptString(s, n));
}
TEST_CASE("ResourceManager::saveString()") {
ResourceManager resources(32);
SECTION("Duplicates different strings") {
auto a = saveString(resources, "hello");
auto b = saveString(resources, "world");
REQUIRE(a->data != b->data);
REQUIRE(a->length == 5);
REQUIRE(b->length == 5);
REQUIRE(a->references == 1);
REQUIRE(b->references == 1);
REQUIRE(resources.size() == 2 * sizeofString(5));
}
SECTION("Deduplicates identical strings") {
auto a = saveString(resources, "hello");
auto b = saveString(resources, "hello");
REQUIRE(a == b);
REQUIRE(a->length == 5);
REQUIRE(a->references == 2);
REQUIRE(resources.size() == sizeofString(5));
}
SECTION("Deduplicates identical strings that contain NUL") {
auto a = saveString(resources, "hello\0world", 11);
auto b = saveString(resources, "hello\0world", 11);
REQUIRE(a == b);
REQUIRE(a->length == 11);
REQUIRE(a->references == 2);
REQUIRE(resources.size() == sizeofString(11));
}
SECTION("Don't stop on first NUL") {
auto a = saveString(resources, "hello");
auto b = saveString(resources, "hello\0world", 11);
REQUIRE(a != b);
REQUIRE(a->length == 5);
REQUIRE(b->length == 11);
REQUIRE(a->references == 1);
REQUIRE(b->references == 1);
REQUIRE(resources.size() == sizeofString(5) + sizeofString(11));
}
SECTION("Returns NULL when allocation fails") {
ResourceManager pool2(32, FailingAllocator::instance());
REQUIRE(saveString(pool2, "a") == nullptr);
}
}

View File

@ -0,0 +1,35 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2023, Benoit BLANCHON
// MIT License
#include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Variant/VariantSlot.hpp>
#include <catch.hpp>
using namespace ArduinoJson::detail;
TEST_CASE("ResourceManager::capacity()") {
const size_t capacity = 64;
ResourceManager resources(capacity);
REQUIRE(capacity == resources.capacity());
}
TEST_CASE("ResourceManager::size()") {
ResourceManager resources(4096);
SECTION("Initial size is 0") {
REQUIRE(0 == resources.size());
}
SECTION("Doesn't grow when memory pool is full") {
const size_t variantCount = resources.capacity() / sizeof(VariantSlot);
for (size_t i = 0; i < variantCount; i++)
new (&resources) VariantSlot();
size_t size = resources.size();
new (&resources) VariantSlot();
REQUIRE(size == resources.size());
}
}

View File

@ -40,8 +40,8 @@ class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
} }
private: private:
FORCE_INLINE MemoryPool* getPool() const { FORCE_INLINE ResourceManager* getResourceManager() const {
return VariantAttorney::getPool(upstream_); return VariantAttorney::getResourceManager(upstream_);
} }
FORCE_INLINE VariantData* getData() const { FORCE_INLINE VariantData* getData() const {
@ -49,8 +49,9 @@ class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
} }
FORCE_INLINE VariantData* getOrCreateData() const { FORCE_INLINE VariantData* getOrCreateData() const {
return variantGetOrAddElement(VariantAttorney::getOrCreateData(upstream_), return variantGetOrAddElement(
index_, VariantAttorney::getPool(upstream_)); VariantAttorney::getOrCreateData(upstream_), index_,
VariantAttorney::getResourceManager(upstream_));
} }
TUpstream upstream_; TUpstream upstream_;

View File

@ -21,17 +21,19 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
typedef JsonArrayIterator iterator; typedef JsonArrayIterator iterator;
// Constructs an unbound reference. // Constructs an unbound reference.
FORCE_INLINE JsonArray() : data_(0), pool_(0) {} FORCE_INLINE JsonArray() : data_(0), resources_(0) {}
// INTERNAL USE ONLY // INTERNAL USE ONLY
FORCE_INLINE JsonArray(detail::MemoryPool* pool, detail::CollectionData* data) FORCE_INLINE JsonArray(detail::ResourceManager* resources,
: data_(data), pool_(pool) {} detail::CollectionData* data)
: data_(data), resources_(resources) {}
// Returns a JsonVariant pointing to the array. // Returns a JsonVariant pointing to the array.
// https://arduinojson.org/v6/api/jsonvariant/ // https://arduinojson.org/v6/api/jsonvariant/
operator JsonVariant() { operator JsonVariant() {
void* data = data_; // prevent warning cast-align void* data = data_; // prevent warning cast-align
return JsonVariant(pool_, reinterpret_cast<detail::VariantData*>(data)); return JsonVariant(resources_,
reinterpret_cast<detail::VariantData*>(data));
} }
// Returns a read-only reference to the array. // Returns a read-only reference to the array.
@ -44,7 +46,7 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// Returns a reference to the new element. // Returns a reference to the new element.
// https://arduinojson.org/v6/api/jsonarray/add/ // https://arduinojson.org/v6/api/jsonarray/add/
JsonVariant add() const { JsonVariant add() const {
return JsonVariant(pool_, collectionAddElement(data_, pool_)); return JsonVariant(resources_, collectionAddElement(data_, resources_));
} }
// Appends a value to the array. // Appends a value to the array.
@ -66,7 +68,7 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
FORCE_INLINE iterator begin() const { FORCE_INLINE iterator begin() const {
if (!data_) if (!data_)
return iterator(); return iterator();
return iterator(pool_, data_->head()); return iterator(resources_, data_->head());
} }
// Returns an iterator following the last element of the array. // Returns an iterator following the last element of the array.
@ -78,7 +80,7 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// Copies an array. // Copies an array.
// https://arduinojson.org/v6/api/jsonarray/set/ // https://arduinojson.org/v6/api/jsonarray/set/
FORCE_INLINE bool set(JsonArrayConst src) const { FORCE_INLINE bool set(JsonArrayConst src) const {
return collectionCopy(data_, src.data_, pool_); return collectionCopy(data_, src.data_, resources_);
} }
// Compares the content of two arrays. // Compares the content of two arrays.
@ -90,21 +92,21 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// ⚠️ Doesn't release the memory associated with the removed element. // ⚠️ Doesn't release the memory associated with the removed element.
// https://arduinojson.org/v6/api/jsonarray/remove/ // https://arduinojson.org/v6/api/jsonarray/remove/
FORCE_INLINE void remove(iterator it) const { FORCE_INLINE void remove(iterator it) const {
collectionRemove(data_, it.slot_, pool_); collectionRemove(data_, it.slot_, resources_);
} }
// Removes the element at the specified index. // Removes the element at the specified index.
// ⚠️ Doesn't release the memory associated with the removed element. // ⚠️ Doesn't release the memory associated with the removed element.
// https://arduinojson.org/v6/api/jsonarray/remove/ // https://arduinojson.org/v6/api/jsonarray/remove/
FORCE_INLINE void remove(size_t index) const { FORCE_INLINE void remove(size_t index) const {
collectionRemoveElement(data_, index, pool_); collectionRemoveElement(data_, index, resources_);
} }
// Removes all the elements of the array. // Removes all the elements of the array.
// ⚠️ Doesn't release the memory associated with the removed elements. // ⚠️ Doesn't release the memory associated with the removed elements.
// https://arduinojson.org/v6/api/jsonarray/clear/ // https://arduinojson.org/v6/api/jsonarray/clear/
void clear() const { void clear() const {
collectionClear(data_, pool_); collectionClear(data_, resources_);
} }
// Gets or sets the element at the specified index. // Gets or sets the element at the specified index.
@ -158,8 +160,8 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
} }
private: private:
detail::MemoryPool* getPool() const { detail::ResourceManager* getResourceManager() const {
return pool_; return resources_;
} }
detail::VariantData* getData() const { detail::VariantData* getData() const {
@ -171,19 +173,19 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
} }
detail::CollectionData* data_; detail::CollectionData* data_;
detail::MemoryPool* pool_; detail::ResourceManager* resources_;
}; };
template <> template <>
struct Converter<JsonArray> : private detail::VariantAttorney { struct Converter<JsonArray> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) { static void toJson(JsonVariantConst src, JsonVariant dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst)); variantCopyFrom(getData(dst), getData(src), getResourceManager(dst));
} }
static JsonArray fromJson(JsonVariant src) { static JsonArray fromJson(JsonVariant src) {
auto data = getData(src); auto data = getData(src);
auto pool = getPool(src); auto resources = getResourceManager(src);
return JsonArray(pool, data != 0 ? data->asArray() : 0); return JsonArray(resources, data != 0 ? data->asArray() : 0);
} }
static detail::InvalidConversion<JsonVariantConst, JsonArray> fromJson( static detail::InvalidConversion<JsonVariantConst, JsonArray> fromJson(
@ -207,7 +209,8 @@ template <typename TDerived>
template <typename T> template <typename T>
inline typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type inline typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type
VariantRefBase<TDerived>::to() const { VariantRefBase<TDerived>::to() const {
return JsonArray(getPool(), variantToArray(getOrCreateData(), getPool())); return JsonArray(getResourceManager(),
variantToArray(getOrCreateData(), getResourceManager()));
} }
ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -118,7 +118,7 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
template <> template <>
struct Converter<JsonArrayConst> : private detail::VariantAttorney { struct Converter<JsonArrayConst> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) { static void toJson(JsonVariantConst src, JsonVariant dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst)); variantCopyFrom(getData(dst), getData(src), getResourceManager(dst));
} }
static JsonArrayConst fromJson(JsonVariantConst src) { static JsonArrayConst fromJson(JsonVariantConst src) {

View File

@ -11,8 +11,8 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
class VariantPtr { class VariantPtr {
public: public:
VariantPtr(detail::MemoryPool* pool, detail::VariantData* data) VariantPtr(detail::ResourceManager* resources, detail::VariantData* data)
: variant_(pool, data) {} : variant_(resources, data) {}
JsonVariant* operator->() { JsonVariant* operator->() {
return &variant_; return &variant_;
@ -31,15 +31,15 @@ class JsonArrayIterator {
public: public:
JsonArrayIterator() : slot_(0) {} JsonArrayIterator() : slot_(0) {}
explicit JsonArrayIterator(detail::MemoryPool* pool, explicit JsonArrayIterator(detail::ResourceManager* resources,
detail::VariantSlot* slot) detail::VariantSlot* slot)
: pool_(pool), slot_(slot) {} : resources_(resources), slot_(slot) {}
JsonVariant operator*() const { JsonVariant operator*() const {
return JsonVariant(pool_, slot_->data()); return JsonVariant(resources_, slot_->data());
} }
VariantPtr operator->() { VariantPtr operator->() {
return VariantPtr(pool_, slot_->data()); return VariantPtr(resources_, slot_->data());
} }
bool operator==(const JsonArrayIterator& other) const { bool operator==(const JsonArrayIterator& other) const {
@ -61,7 +61,7 @@ class JsonArrayIterator {
} }
private: private:
detail::MemoryPool* pool_; detail::ResourceManager* resources_;
detail::VariantSlot* slot_; detail::VariantSlot* slot_;
}; };

View File

@ -9,10 +9,10 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
inline VariantData* collectionAddElement(CollectionData* array, inline VariantData* collectionAddElement(CollectionData* array,
MemoryPool* pool) { ResourceManager* resources) {
if (!array) if (!array)
return nullptr; return nullptr;
auto slot = new (pool) VariantSlot(); auto slot = new (resources) VariantSlot();
if (!slot) if (!slot)
return nullptr; return nullptr;
array->add(slot); array->add(slot);
@ -21,16 +21,16 @@ inline VariantData* collectionAddElement(CollectionData* array,
template <typename TAdaptedString> template <typename TAdaptedString>
inline VariantData* collectionAddMember(CollectionData* obj, TAdaptedString key, inline VariantData* collectionAddMember(CollectionData* obj, TAdaptedString key,
MemoryPool* pool) { ResourceManager* resources) {
ARDUINOJSON_ASSERT(!key.isNull()); ARDUINOJSON_ASSERT(!key.isNull());
ARDUINOJSON_ASSERT(obj != nullptr); ARDUINOJSON_ASSERT(obj != nullptr);
auto slot = new (pool) VariantSlot(); auto slot = new (resources) VariantSlot();
if (!slot) if (!slot)
return nullptr; return nullptr;
if (key.isLinked()) if (key.isLinked())
slot->setKey(key.data()); slot->setKey(key.data());
else { else {
auto storedKey = pool->saveString(key); auto storedKey = resources->saveString(key);
if (!storedKey) if (!storedKey)
return nullptr; return nullptr;
slot->setKey(storedKey); slot->setKey(storedKey);
@ -39,31 +39,31 @@ inline VariantData* collectionAddMember(CollectionData* obj, TAdaptedString key,
return slot->data(); return slot->data();
} }
inline void collectionClear(CollectionData* c, MemoryPool* pool) { inline void collectionClear(CollectionData* c, ResourceManager* resources) {
if (!c) if (!c)
return; return;
for (auto slot = c->head(); slot; slot = slot->next()) for (auto slot = c->head(); slot; slot = slot->next())
slotRelease(slot, pool); slotRelease(slot, resources);
c->clear(); c->clear();
} }
inline bool collectionCopy(CollectionData* dst, const CollectionData* src, inline bool collectionCopy(CollectionData* dst, const CollectionData* src,
MemoryPool* pool) { ResourceManager* resources) {
if (!dst || !src) if (!dst || !src)
return false; return false;
collectionClear(dst, pool); collectionClear(dst, resources);
for (VariantSlot* s = src->head(); s; s = s->next()) { for (VariantSlot* s = src->head(); s; s = s->next()) {
VariantData* var; VariantData* var;
if (s->key() != 0) { if (s->key() != 0) {
JsonString key(s->key(), JsonString key(s->key(),
s->ownsKey() ? JsonString::Copied : JsonString::Linked); s->ownsKey() ? JsonString::Copied : JsonString::Linked);
var = collectionAddMember(dst, adaptString(key), pool); var = collectionAddMember(dst, adaptString(key), resources);
} else { } else {
var = collectionAddElement(dst, pool); var = collectionAddElement(dst, resources);
} }
if (!variantCopyFrom(var, s->data(), pool)) if (!variantCopyFrom(var, s->data(), resources))
return false; return false;
} }
return true; return true;
@ -78,26 +78,26 @@ inline VariantData* collectionGetMember(const CollectionData* obj,
} }
inline void collectionRemove(CollectionData* data, VariantSlot* slot, inline void collectionRemove(CollectionData* data, VariantSlot* slot,
MemoryPool* pool) { ResourceManager* resources) {
if (!data || !slot) if (!data || !slot)
return; return;
data->remove(slot); data->remove(slot);
slotRelease(slot, pool); slotRelease(slot, resources);
} }
inline void collectionRemoveElement(CollectionData* array, size_t index, inline void collectionRemoveElement(CollectionData* array, size_t index,
MemoryPool* pool) { ResourceManager* resources) {
if (!array) if (!array)
return; return;
collectionRemove(array, array->get(index), pool); collectionRemove(array, array->get(index), resources);
} }
template <typename TAdaptedString> template <typename TAdaptedString>
inline void collectionRemoveMember(CollectionData* obj, TAdaptedString key, inline void collectionRemoveMember(CollectionData* obj, TAdaptedString key,
MemoryPool* pool) { ResourceManager* resources) {
if (!obj) if (!obj)
return; return;
collectionRemove(obj, obj->get(key), pool); collectionRemove(obj, obj->get(key), resources);
} }
ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -23,9 +23,10 @@ struct first_or_void<T, Rest...> {
}; };
template <template <typename> class TDeserializer, typename TReader> template <template <typename> class TDeserializer, typename TReader>
TDeserializer<TReader> makeDeserializer(MemoryPool* pool, TReader reader) { TDeserializer<TReader> makeDeserializer(ResourceManager* resources,
ARDUINOJSON_ASSERT(pool != 0); TReader reader) {
return TDeserializer<TReader>(pool, reader); ARDUINOJSON_ASSERT(resources != 0);
return TDeserializer<TReader>(resources, reader);
} }
template <template <typename> class TDeserializer, typename TStream, template <template <typename> class TDeserializer, typename TStream,
@ -36,10 +37,10 @@ DeserializationError deserialize(JsonDocument& doc, TStream&& input,
Args... args) { Args... args) {
auto reader = makeReader(detail::forward<TStream>(input)); auto reader = makeReader(detail::forward<TStream>(input));
auto data = VariantAttorney::getData(doc); auto data = VariantAttorney::getData(doc);
auto pool = VariantAttorney::getPool(doc); auto resources = VariantAttorney::getResourceManager(doc);
auto options = makeDeserializationOptions(args...); auto options = makeDeserializationOptions(args...);
doc.clear(); doc.clear();
return makeDeserializer<TDeserializer>(pool, reader) return makeDeserializer<TDeserializer>(resources, reader)
.parse(*data, options.filter, options.nestingLimit); .parse(*data, options.filter, options.nestingLimit);
} }
@ -50,10 +51,10 @@ DeserializationError deserialize(JsonDocument& doc, TChar* input,
Size inputSize, Args... args) { Size inputSize, Args... args) {
auto reader = makeReader(input, size_t(inputSize)); auto reader = makeReader(input, size_t(inputSize));
auto data = VariantAttorney::getData(doc); auto data = VariantAttorney::getData(doc);
auto pool = VariantAttorney::getPool(doc); auto resources = VariantAttorney::getResourceManager(doc);
auto options = makeDeserializationOptions(args...); auto options = makeDeserializationOptions(args...);
doc.clear(); doc.clear();
return makeDeserializer<TDeserializer>(pool, reader) return makeDeserializer<TDeserializer>(resources, reader)
.parse(*data, options.filter, options.nestingLimit); .parse(*data, options.filter, options.nestingLimit);
} }

View File

@ -6,7 +6,7 @@
#include <ArduinoJson/Array/ElementProxy.hpp> #include <ArduinoJson/Array/ElementProxy.hpp>
#include <ArduinoJson/Memory/Allocator.hpp> #include <ArduinoJson/Memory/Allocator.hpp>
#include <ArduinoJson/Memory/MemoryPool.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Object/JsonObject.hpp> #include <ArduinoJson/Object/JsonObject.hpp>
#include <ArduinoJson/Object/MemberProxy.hpp> #include <ArduinoJson/Object/MemberProxy.hpp>
#include <ArduinoJson/Polyfills/utility.hpp> #include <ArduinoJson/Polyfills/utility.hpp>
@ -23,16 +23,16 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
public: public:
explicit JsonDocument(size_t capa, explicit JsonDocument(size_t capa,
Allocator* alloc = detail::DefaultAllocator::instance()) Allocator* alloc = detail::DefaultAllocator::instance())
: pool_(capa, alloc) {} : resources_(capa, alloc) {}
// Copy-constructor // Copy-constructor
JsonDocument(const JsonDocument& src) JsonDocument(const JsonDocument& src)
: JsonDocument(src.pool_.capacity(), src.allocator()) { : JsonDocument(src.resources_.capacity(), src.allocator()) {
set(src); set(src);
} }
// Move-constructor // Move-constructor
JsonDocument(JsonDocument&& src) : pool_(0, src.allocator()) { JsonDocument(JsonDocument&& src) : resources_(0, src.allocator()) {
// TODO: use the copy and swap idiom // TODO: use the copy and swap idiom
moveAssignFrom(src); moveAssignFrom(src);
} }
@ -73,20 +73,20 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
template <typename T> template <typename T>
JsonDocument& operator=(const T& src) { JsonDocument& operator=(const T& src) {
size_t requiredSize = src.memoryUsage(); size_t requiredSize = src.memoryUsage();
if (requiredSize > pool_.capacity()) if (requiredSize > resources_.capacity())
pool_.reallocPool(requiredSize); resources_.reallocPool(requiredSize);
set(src); set(src);
return *this; return *this;
} }
Allocator* allocator() const { Allocator* allocator() const {
return pool_.allocator(); return resources_.allocator();
} }
// Reduces the capacity of the memory pool to match the current usage. // Reduces the capacity of the memory pool to match the current usage.
// https://arduinojson.org/v6/api/JsonDocument/shrinktofit/ // https://arduinojson.org/v6/api/JsonDocument/shrinktofit/
void shrinkToFit() { void shrinkToFit() {
auto offset = pool_.shrinkToFit(); auto offset = resources_.shrinkToFit();
data_.movePointers(offset); data_.movePointers(offset);
} }
@ -95,7 +95,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
bool garbageCollect() { bool garbageCollect() {
// make a temporary clone and move assign // make a temporary clone and move assign
JsonDocument tmp(*this); JsonDocument tmp(*this);
if (!tmp.pool_.capacity()) if (!tmp.resources_.capacity())
return false; return false;
moveAssignFrom(tmp); moveAssignFrom(tmp);
return true; return true;
@ -118,7 +118,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Empties the document and resets the memory pool // Empties the document and resets the memory pool
// https://arduinojson.org/v6/api/jsondocument/clear/ // https://arduinojson.org/v6/api/jsondocument/clear/
void clear() { void clear() {
pool_.clear(); resources_.clear();
data_.reset(); data_.reset();
} }
@ -145,13 +145,13 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Returns the number of used bytes in the memory pool. // Returns the number of used bytes in the memory pool.
// https://arduinojson.org/v6/api/jsondocument/memoryusage/ // https://arduinojson.org/v6/api/jsondocument/memoryusage/
size_t memoryUsage() const { size_t memoryUsage() const {
return pool_.size(); return resources_.size();
} }
// Returns trues if the memory pool was too small. // Returns trues if the memory pool was too small.
// https://arduinojson.org/v6/api/jsondocument/overflowed/ // https://arduinojson.org/v6/api/jsondocument/overflowed/
bool overflowed() const { bool overflowed() const {
return pool_.overflowed(); return resources_.overflowed();
} }
// Returns the depth (nesting level) of the array. // Returns the depth (nesting level) of the array.
@ -297,7 +297,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Returns a reference to the new element. // Returns a reference to the new element.
// https://arduinojson.org/v6/api/jsondocument/add/ // https://arduinojson.org/v6/api/jsondocument/add/
FORCE_INLINE JsonVariant add() { FORCE_INLINE JsonVariant add() {
return JsonVariant(&pool_, data_.addElement(&pool_)); return JsonVariant(&resources_, data_.addElement(&resources_));
} }
// Appends a value to the root array. // Appends a value to the root array.
@ -318,7 +318,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// ⚠️ Doesn't release the memory associated with the removed element. // ⚠️ Doesn't release the memory associated with the removed element.
// https://arduinojson.org/v6/api/jsondocument/remove/ // https://arduinojson.org/v6/api/jsondocument/remove/
FORCE_INLINE void remove(size_t index) { FORCE_INLINE void remove(size_t index) {
variantRemoveElement(getData(), index, getPool()); variantRemoveElement(getData(), index, getResourceManager());
} }
// Removes a member of the root object. // Removes a member of the root object.
@ -327,7 +327,8 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
template <typename TChar> template <typename TChar>
FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value>::type FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value>::type
remove(TChar* key) { remove(TChar* key) {
variantRemoveMember(getData(), detail::adaptString(key), getPool()); variantRemoveMember(getData(), detail::adaptString(key),
getResourceManager());
} }
// Removes a member of the root object. // Removes a member of the root object.
@ -337,7 +338,8 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
FORCE_INLINE FORCE_INLINE
typename detail::enable_if<detail::IsString<TString>::value>::type typename detail::enable_if<detail::IsString<TString>::value>::type
remove(const TString& key) { remove(const TString& key) {
variantRemoveMember(getData(), detail::adaptString(key), getPool()); variantRemoveMember(getData(), detail::adaptString(key),
getResourceManager());
} }
FORCE_INLINE operator JsonVariant() { FORCE_INLINE operator JsonVariant() {
@ -350,7 +352,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
private: private:
JsonVariant getVariant() { JsonVariant getVariant() {
return JsonVariant(&pool_, &data_); return JsonVariant(&resources_, &data_);
} }
JsonVariantConst getVariant() const { JsonVariantConst getVariant() const {
@ -358,18 +360,18 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
} }
void copyAssignFrom(const JsonDocument& src) { void copyAssignFrom(const JsonDocument& src) {
pool_.reallocPool(src.pool_.capacity()); resources_.reallocPool(src.resources_.capacity());
set(src); set(src);
} }
void moveAssignFrom(JsonDocument& src) { void moveAssignFrom(JsonDocument& src) {
data_ = src.data_; data_ = src.data_;
src.data_.reset(); src.data_.reset();
pool_ = move(src.pool_); resources_ = move(src.resources_);
} }
detail::MemoryPool* getPool() { detail::ResourceManager* getResourceManager() {
return &pool_; return &resources_;
} }
detail::VariantData* getData() { detail::VariantData* getData() {
@ -384,7 +386,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
return &data_; return &data_;
} }
detail::MemoryPool pool_; detail::ResourceManager resources_;
detail::VariantData data_; detail::VariantData data_;
}; };

View File

@ -9,7 +9,7 @@
#include <ArduinoJson/Json/Latch.hpp> #include <ArduinoJson/Json/Latch.hpp>
#include <ArduinoJson/Json/Utf16.hpp> #include <ArduinoJson/Json/Utf16.hpp>
#include <ArduinoJson/Json/Utf8.hpp> #include <ArduinoJson/Json/Utf8.hpp>
#include <ArduinoJson/Memory/MemoryPool.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Numbers/parseNumber.hpp> #include <ArduinoJson/Numbers/parseNumber.hpp>
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp> #include <ArduinoJson/Polyfills/type_traits.hpp>
@ -21,11 +21,11 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename TReader> template <typename TReader>
class JsonDeserializer { class JsonDeserializer {
public: public:
JsonDeserializer(MemoryPool* pool, TReader reader) JsonDeserializer(ResourceManager* resources, TReader reader)
: stringBuilder_(pool), : stringBuilder_(resources),
foundSomething_(false), foundSomething_(false),
latch_(reader), latch_(reader),
pool_(pool) {} resources_(resources) {}
template <typename TFilter> template <typename TFilter>
DeserializationError parse(VariantData& variant, TFilter filter, DeserializationError parse(VariantData& variant, TFilter filter,
@ -172,7 +172,7 @@ class JsonDeserializer {
for (;;) { for (;;) {
if (elementFilter.allow()) { if (elementFilter.allow()) {
// Allocate slot in array // Allocate slot in array
VariantData* value = collectionAddElement(&array, pool_); VariantData* value = collectionAddElement(&array, resources_);
if (!value) if (!value)
return DeserializationError::NoMemory; return DeserializationError::NoMemory;
@ -279,14 +279,14 @@ class JsonDeserializer {
auto savedKey = stringBuilder_.save(); auto savedKey = stringBuilder_.save();
// Allocate slot in object // Allocate slot in object
slot = new (pool_) VariantSlot(); slot = new (resources_) VariantSlot();
if (!slot) if (!slot)
return DeserializationError::NoMemory; return DeserializationError::NoMemory;
slot->setKey(savedKey); slot->setKey(savedKey);
object.add(slot); object.add(slot);
} else { } else {
slot->data()->setNull(pool_); slot->data()->setNull(resources_);
} }
// Parse value // Parse value
@ -662,7 +662,7 @@ class JsonDeserializer {
StringBuilder stringBuilder_; StringBuilder stringBuilder_;
bool foundSomething_; bool foundSomething_;
Latch<TReader> latch_; Latch<TReader> latch_;
MemoryPool* pool_; ResourceManager* resources_;
char buffer_[64]; // using a member instead of a local variable because it char buffer_[64]; // using a member instead of a local variable because it
// ended in the recursive path after compiler inlined the // ended in the recursive path after compiler inlined the
// code // code

View File

@ -15,22 +15,23 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class MemoryPool { class ResourceManager {
public: public:
MemoryPool(size_t capa, Allocator* allocator = DefaultAllocator::instance()) ResourceManager(size_t capa,
Allocator* allocator = DefaultAllocator::instance())
: allocator_(allocator), overflowed_(false) { : allocator_(allocator), overflowed_(false) {
allocPool(addPadding(capa)); allocPool(addPadding(capa));
} }
~MemoryPool() { ~ResourceManager() {
deallocAllStrings(); deallocAllStrings();
deallocPool(); deallocPool();
} }
MemoryPool(const MemoryPool&) = delete; ResourceManager(const ResourceManager&) = delete;
MemoryPool& operator=(const MemoryPool& src) = delete; ResourceManager& operator=(const ResourceManager& src) = delete;
MemoryPool& operator=(MemoryPool&& src) { ResourceManager& operator=(ResourceManager&& src) {
deallocAllStrings(); deallocAllStrings();
deallocPool(); deallocPool();
allocator_ = src.allocator_; allocator_ = src.allocator_;

View File

@ -4,7 +4,7 @@
#pragma once #pragma once
#include <ArduinoJson/Memory/MemoryPool.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
@ -12,26 +12,26 @@ class StringBuilder {
public: public:
static const size_t initialCapacity = 31; static const size_t initialCapacity = 31;
StringBuilder(MemoryPool* pool) : pool_(pool) {} StringBuilder(ResourceManager* resources) : resources_(resources) {}
~StringBuilder() { ~StringBuilder() {
if (node_) if (node_)
pool_->deallocString(node_); resources_->deallocString(node_);
} }
void startString() { void startString() {
size_ = 0; size_ = 0;
if (!node_) if (!node_)
node_ = pool_->allocString(initialCapacity); node_ = resources_->allocString(initialCapacity);
} }
StringNode* save() { StringNode* save() {
ARDUINOJSON_ASSERT(node_ != nullptr); ARDUINOJSON_ASSERT(node_ != nullptr);
node_->data[size_] = 0; node_->data[size_] = 0;
StringNode* node = pool_->findString(adaptString(node_->data, size_)); StringNode* node = resources_->findString(adaptString(node_->data, size_));
if (!node) { if (!node) {
node = pool_->reallocString(node_, size_); node = resources_->reallocString(node_, size_);
pool_->addStringToList(node); resources_->addStringToList(node);
node_ = nullptr; // next time we need a new string node_ = nullptr; // next time we need a new string
} else { } else {
node->references++; node->references++;
@ -51,7 +51,7 @@ class StringBuilder {
void append(char c) { void append(char c) {
if (node_ && size_ == node_->length) if (node_ && size_ == node_->length)
node_ = pool_->reallocString(node_, size_ * 2U + 1); node_ = resources_->reallocString(node_, size_ * 2U + 1);
if (node_) if (node_)
node_->data[size_++] = c; node_->data[size_++] = c;
} }
@ -71,7 +71,7 @@ class StringBuilder {
} }
private: private:
MemoryPool* pool_; ResourceManager* resources_;
StringNode* node_ = nullptr; StringNode* node_ = nullptr;
size_t size_ = 0; size_t size_ = 0;
}; };

View File

@ -5,7 +5,7 @@
#pragma once #pragma once
#include <ArduinoJson/Deserialization/deserialize.hpp> #include <ArduinoJson/Deserialization/deserialize.hpp>
#include <ArduinoJson/Memory/MemoryPool.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/MsgPack/endianess.hpp> #include <ArduinoJson/MsgPack/endianess.hpp>
#include <ArduinoJson/MsgPack/ieee754.hpp> #include <ArduinoJson/MsgPack/ieee754.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp> #include <ArduinoJson/Polyfills/type_traits.hpp>
@ -16,10 +16,10 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename TReader> template <typename TReader>
class MsgPackDeserializer { class MsgPackDeserializer {
public: public:
MsgPackDeserializer(MemoryPool* pool, TReader reader) MsgPackDeserializer(ResourceManager* resources, TReader reader)
: pool_(pool), : resources_(resources),
reader_(reader), reader_(reader),
stringBuilder_(pool), stringBuilder_(resources),
foundSomething_(false) {} foundSomething_(false) {}
template <typename TFilter> template <typename TFilter>
@ -434,7 +434,7 @@ class MsgPackDeserializer {
if (elementFilter.allow()) { if (elementFilter.allow()) {
ARDUINOJSON_ASSERT(array != 0); ARDUINOJSON_ASSERT(array != 0);
value = collectionAddElement(array, pool_); value = collectionAddElement(array, resources_);
if (!value) if (!value)
return DeserializationError::NoMemory; return DeserializationError::NoMemory;
} else { } else {
@ -495,7 +495,7 @@ class MsgPackDeserializer {
// Save key in memory pool. // Save key in memory pool.
auto savedKey = stringBuilder_.save(); auto savedKey = stringBuilder_.save();
VariantSlot* slot = new (pool_) VariantSlot(); VariantSlot* slot = new (resources_) VariantSlot();
if (!slot) if (!slot)
return DeserializationError::NoMemory; return DeserializationError::NoMemory;
@ -553,7 +553,7 @@ class MsgPackDeserializer {
return skipBytes(size + 1U); return skipBytes(size + 1U);
} }
MemoryPool* pool_; ResourceManager* resources_;
TReader reader_; TReader reader_;
StringBuilder stringBuilder_; StringBuilder stringBuilder_;
bool foundSomething_; bool foundSomething_;

View File

@ -20,15 +20,17 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
typedef JsonObjectIterator iterator; typedef JsonObjectIterator iterator;
// Creates an unbound reference. // Creates an unbound reference.
FORCE_INLINE JsonObject() : data_(0), pool_(0) {} FORCE_INLINE JsonObject() : data_(0), resources_(0) {}
// INTERNAL USE ONLY // INTERNAL USE ONLY
FORCE_INLINE JsonObject(detail::MemoryPool* buf, detail::CollectionData* data) FORCE_INLINE JsonObject(detail::ResourceManager* buf,
: data_(data), pool_(buf) {} detail::CollectionData* data)
: data_(data), resources_(buf) {}
operator JsonVariant() const { operator JsonVariant() const {
void* data = data_; // prevent warning cast-align void* data = data_; // prevent warning cast-align
return JsonVariant(pool_, reinterpret_cast<detail::VariantData*>(data)); return JsonVariant(resources_,
reinterpret_cast<detail::VariantData*>(data));
} }
operator JsonObjectConst() const { operator JsonObjectConst() const {
@ -74,7 +76,7 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
FORCE_INLINE iterator begin() const { FORCE_INLINE iterator begin() const {
if (!data_) if (!data_)
return iterator(); return iterator();
return iterator(pool_, data_->head()); return iterator(resources_, data_->head());
} }
// Returns an iterator following the last key-value pair of the object. // Returns an iterator following the last key-value pair of the object.
@ -87,13 +89,13 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// ⚠️ Doesn't release the memory associated with the removed members. // ⚠️ Doesn't release the memory associated with the removed members.
// https://arduinojson.org/v6/api/jsonobject/clear/ // https://arduinojson.org/v6/api/jsonobject/clear/
void clear() const { void clear() const {
collectionClear(data_, pool_); collectionClear(data_, resources_);
} }
// Copies an object. // Copies an object.
// https://arduinojson.org/v6/api/jsonobject/set/ // https://arduinojson.org/v6/api/jsonobject/set/
FORCE_INLINE bool set(JsonObjectConst src) { FORCE_INLINE bool set(JsonObjectConst src) {
return collectionCopy(data_, src.data_, pool_); return collectionCopy(data_, src.data_, resources_);
} }
// Compares the content of two objects. // Compares the content of two objects.
@ -125,7 +127,7 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// ⚠️ Doesn't release the memory associated with the removed member. // ⚠️ Doesn't release the memory associated with the removed member.
// https://arduinojson.org/v6/api/jsonobject/remove/ // https://arduinojson.org/v6/api/jsonobject/remove/
FORCE_INLINE void remove(iterator it) const { FORCE_INLINE void remove(iterator it) const {
collectionRemove(data_, it.slot_, pool_); collectionRemove(data_, it.slot_, resources_);
} }
// Removes the member with the specified key. // Removes the member with the specified key.
@ -133,7 +135,7 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// https://arduinojson.org/v6/api/jsonobject/remove/ // https://arduinojson.org/v6/api/jsonobject/remove/
template <typename TString> template <typename TString>
FORCE_INLINE void remove(const TString& key) const { FORCE_INLINE void remove(const TString& key) const {
collectionRemoveMember(data_, detail::adaptString(key), pool_); collectionRemoveMember(data_, detail::adaptString(key), resources_);
} }
// Removes the member with the specified key. // Removes the member with the specified key.
@ -141,7 +143,7 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// https://arduinojson.org/v6/api/jsonobject/remove/ // https://arduinojson.org/v6/api/jsonobject/remove/
template <typename TChar> template <typename TChar>
FORCE_INLINE void remove(TChar* key) const { FORCE_INLINE void remove(TChar* key) const {
collectionRemoveMember(data_, detail::adaptString(key), pool_); collectionRemoveMember(data_, detail::adaptString(key), resources_);
} }
// Returns true if the object contains the specified key. // Returns true if the object contains the specified key.
@ -187,8 +189,8 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
} }
private: private:
detail::MemoryPool* getPool() const { detail::ResourceManager* getResourceManager() const {
return pool_; return resources_;
} }
detail::VariantData* getData() const { detail::VariantData* getData() const {
@ -201,23 +203,23 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
template <typename TAdaptedString> template <typename TAdaptedString>
void removeMember(TAdaptedString key) const { void removeMember(TAdaptedString key) const {
collectionRemove(data_, data_->get(key), pool_); collectionRemove(data_, data_->get(key), resources_);
} }
detail::CollectionData* data_; detail::CollectionData* data_;
detail::MemoryPool* pool_; detail::ResourceManager* resources_;
}; };
template <> template <>
struct Converter<JsonObject> : private detail::VariantAttorney { struct Converter<JsonObject> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) { static void toJson(JsonVariantConst src, JsonVariant dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst)); variantCopyFrom(getData(dst), getData(src), getResourceManager(dst));
} }
static JsonObject fromJson(JsonVariant src) { static JsonObject fromJson(JsonVariant src) {
auto data = getData(src); auto data = getData(src);
auto pool = getPool(src); auto resources = getResourceManager(src);
return JsonObject(pool, data != 0 ? data->asObject() : 0); return JsonObject(resources, data != 0 ? data->asObject() : 0);
} }
static detail::InvalidConversion<JsonVariantConst, JsonObject> fromJson( static detail::InvalidConversion<JsonVariantConst, JsonObject> fromJson(
@ -241,7 +243,8 @@ template <typename TDerived>
template <typename T> template <typename T>
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type
VariantRefBase<TDerived>::to() const { VariantRefBase<TDerived>::to() const {
return JsonObject(getPool(), variantToObject(getOrCreateData(), getPool())); return JsonObject(getResourceManager(),
variantToObject(getOrCreateData(), getResourceManager()));
} }
ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -134,7 +134,7 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
template <> template <>
struct Converter<JsonObjectConst> : private detail::VariantAttorney { struct Converter<JsonObjectConst> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) { static void toJson(JsonVariantConst src, JsonVariant dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst)); variantCopyFrom(getData(dst), getData(src), getResourceManager(dst));
} }
static JsonObjectConst fromJson(JsonVariantConst src) { static JsonObjectConst fromJson(JsonVariantConst src) {

View File

@ -11,8 +11,8 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
class JsonPairPtr { class JsonPairPtr {
public: public:
JsonPairPtr(detail::MemoryPool* pool, detail::VariantSlot* slot) JsonPairPtr(detail::ResourceManager* resources, detail::VariantSlot* slot)
: pair_(pool, slot) {} : pair_(resources, slot) {}
const JsonPair* operator->() const { const JsonPair* operator->() const {
return &pair_; return &pair_;
@ -32,15 +32,15 @@ class JsonObjectIterator {
public: public:
JsonObjectIterator() : slot_(0) {} JsonObjectIterator() : slot_(0) {}
explicit JsonObjectIterator(detail::MemoryPool* pool, explicit JsonObjectIterator(detail::ResourceManager* resources,
detail::VariantSlot* slot) detail::VariantSlot* slot)
: pool_(pool), slot_(slot) {} : resources_(resources), slot_(slot) {}
JsonPair operator*() const { JsonPair operator*() const {
return JsonPair(pool_, slot_); return JsonPair(resources_, slot_);
} }
JsonPairPtr operator->() { JsonPairPtr operator->() {
return JsonPairPtr(pool_, slot_); return JsonPairPtr(resources_, slot_);
} }
bool operator==(const JsonObjectIterator& other) const { bool operator==(const JsonObjectIterator& other) const {
@ -62,7 +62,7 @@ class JsonObjectIterator {
} }
private: private:
detail::MemoryPool* pool_; detail::ResourceManager* resources_;
detail::VariantSlot* slot_; detail::VariantSlot* slot_;
}; };

View File

@ -15,11 +15,11 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
class JsonPair { class JsonPair {
public: public:
// INTERNAL USE ONLY // INTERNAL USE ONLY
JsonPair(detail::MemoryPool* pool, detail::VariantSlot* slot) { JsonPair(detail::ResourceManager* resources, detail::VariantSlot* slot) {
if (slot) { if (slot) {
key_ = JsonString(slot->key(), slot->ownsKey() ? JsonString::Copied key_ = JsonString(slot->key(), slot->ownsKey() ? JsonString::Copied
: JsonString::Linked); : JsonString::Linked);
value_ = JsonVariant(pool, slot->data()); value_ = JsonVariant(resources, slot->data());
} }
} }

View File

@ -41,8 +41,8 @@ class MemberProxy
} }
private: private:
FORCE_INLINE MemoryPool* getPool() const { FORCE_INLINE ResourceManager* getResourceManager() const {
return VariantAttorney::getPool(upstream_); return VariantAttorney::getResourceManager(upstream_);
} }
FORCE_INLINE VariantData* getData() const { FORCE_INLINE VariantData* getData() const {
@ -51,9 +51,9 @@ class MemberProxy
} }
FORCE_INLINE VariantData* getOrCreateData() const { FORCE_INLINE VariantData* getOrCreateData() const {
return variantGetOrAddMember(VariantAttorney::getOrCreateData(upstream_), return variantGetOrAddMember(
adaptString(key_), VariantAttorney::getOrCreateData(upstream_), adaptString(key_),
VariantAttorney::getPool(upstream_)); VariantAttorney::getResourceManager(upstream_));
} }
private: private:

View File

@ -42,7 +42,7 @@ struct Converter<
: private detail::VariantAttorney { : private detail::VariantAttorney {
static void toJson(T src, JsonVariant dst) { static void toJson(T src, JsonVariant dst) {
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
variantSetInteger(getData(dst), src, getPool(dst)); variantSetInteger(getData(dst), src, getResourceManager(dst));
} }
static T fromJson(JsonVariantConst src) { static T fromJson(JsonVariantConst src) {
@ -78,7 +78,7 @@ struct Converter<T, typename detail::enable_if<detail::is_enum<T>::value>::type>
template <> template <>
struct Converter<bool> : private detail::VariantAttorney { struct Converter<bool> : private detail::VariantAttorney {
static void toJson(bool src, JsonVariant dst) { static void toJson(bool src, JsonVariant dst) {
variantSetBoolean(getData(dst), src, getPool(dst)); variantSetBoolean(getData(dst), src, getResourceManager(dst));
} }
static bool fromJson(JsonVariantConst src) { static bool fromJson(JsonVariantConst src) {
@ -97,7 +97,8 @@ struct Converter<
T, typename detail::enable_if<detail::is_floating_point<T>::value>::type> T, typename detail::enable_if<detail::is_floating_point<T>::value>::type>
: private detail::VariantAttorney { : private detail::VariantAttorney {
static void toJson(T src, JsonVariant dst) { static void toJson(T src, JsonVariant dst) {
variantSetFloat(getData(dst), static_cast<JsonFloat>(src), getPool(dst)); variantSetFloat(getData(dst), static_cast<JsonFloat>(src),
getResourceManager(dst));
} }
static T fromJson(JsonVariantConst src) { static T fromJson(JsonVariantConst src) {
@ -114,7 +115,8 @@ struct Converter<
template <> template <>
struct Converter<const char*> : private detail::VariantAttorney { struct Converter<const char*> : private detail::VariantAttorney {
static void toJson(const char* src, JsonVariant dst) { static void toJson(const char* src, JsonVariant dst) {
variantSetString(getData(dst), detail::adaptString(src), getPool(dst)); variantSetString(getData(dst), detail::adaptString(src),
getResourceManager(dst));
} }
static const char* fromJson(JsonVariantConst src) { static const char* fromJson(JsonVariantConst src) {
@ -131,7 +133,8 @@ struct Converter<const char*> : private detail::VariantAttorney {
template <> template <>
struct Converter<JsonString> : private detail::VariantAttorney { struct Converter<JsonString> : private detail::VariantAttorney {
static void toJson(JsonString src, JsonVariant dst) { static void toJson(JsonString src, JsonVariant dst) {
variantSetString(getData(dst), detail::adaptString(src), getPool(dst)); variantSetString(getData(dst), detail::adaptString(src),
getResourceManager(dst));
} }
static JsonString fromJson(JsonVariantConst src) { static JsonString fromJson(JsonVariantConst src) {
@ -150,8 +153,8 @@ inline typename detail::enable_if<detail::IsString<T>::value>::type
convertToJson(const T& src, JsonVariant dst) { convertToJson(const T& src, JsonVariant dst) {
using namespace detail; using namespace detail;
auto data = VariantAttorney::getData(dst); auto data = VariantAttorney::getData(dst);
auto pool = VariantAttorney::getPool(dst); auto resources = VariantAttorney::getResourceManager(dst);
variantSetString(data, adaptString(src), pool); variantSetString(data, adaptString(src), resources);
} }
// SerializedValue<std::string> // SerializedValue<std::string>
@ -160,14 +163,14 @@ convertToJson(const T& src, JsonVariant dst) {
template <typename T> template <typename T>
struct Converter<SerializedValue<T>> : private detail::VariantAttorney { struct Converter<SerializedValue<T>> : private detail::VariantAttorney {
static void toJson(SerializedValue<T> src, JsonVariant dst) { static void toJson(SerializedValue<T> src, JsonVariant dst) {
variantSetRawString(getData(dst), src, getPool(dst)); variantSetRawString(getData(dst), src, getResourceManager(dst));
} }
}; };
template <> template <>
struct Converter<decltype(nullptr)> : private detail::VariantAttorney { struct Converter<decltype(nullptr)> : private detail::VariantAttorney {
static void toJson(decltype(nullptr), JsonVariant dst) { static void toJson(decltype(nullptr), JsonVariant dst) {
variantSetNull(getData(dst), getPool(dst)); variantSetNull(getData(dst), getResourceManager(dst));
} }
static decltype(nullptr) fromJson(JsonVariantConst) { static decltype(nullptr) fromJson(JsonVariantConst) {
return nullptr; return nullptr;
@ -181,9 +184,9 @@ struct Converter<decltype(nullptr)> : private detail::VariantAttorney {
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM #if ARDUINOJSON_ENABLE_ARDUINO_STREAM
namespace detail { namespace detail {
class MemoryPoolPrint : public Print { class StringBuilderPrint : public Print {
public: public:
MemoryPoolPrint(MemoryPool* pool) : copier_(pool) { StringBuilderPrint(ResourceManager* resources) : copier_(resources) {
copier_.startString(); copier_.startString();
} }
@ -216,11 +219,11 @@ class MemoryPoolPrint : public Print {
} // namespace detail } // namespace detail
inline void convertToJson(const ::Printable& src, JsonVariant dst) { inline void convertToJson(const ::Printable& src, JsonVariant dst) {
auto pool = detail::VariantAttorney::getPool(dst); auto resources = detail::VariantAttorney::getResourceManager(dst);
auto data = detail::VariantAttorney::getData(dst); auto data = detail::VariantAttorney::getData(dst);
if (!pool || !data) if (!resources || !data)
return; return;
detail::MemoryPoolPrint print(pool); detail::StringBuilderPrint print(resources);
src.printTo(print); src.printTo(print);
if (print.overflowed()) { if (print.overflowed()) {
data->setNull(); data->setNull();

View File

@ -16,15 +16,15 @@ class JsonVariant : public detail::VariantRefBase<JsonVariant>,
public: public:
// Creates an unbound reference. // Creates an unbound reference.
JsonVariant() : data_(0), pool_(0) {} JsonVariant() : data_(0), resources_(0) {}
// INTERNAL USE ONLY // INTERNAL USE ONLY
JsonVariant(detail::MemoryPool* pool, detail::VariantData* data) JsonVariant(detail::ResourceManager* resources, detail::VariantData* data)
: data_(data), pool_(pool) {} : data_(data), resources_(resources) {}
private: private:
FORCE_INLINE detail::MemoryPool* getPool() const { FORCE_INLINE detail::ResourceManager* getResourceManager() const {
return pool_; return resources_;
} }
FORCE_INLINE detail::VariantData* getData() const { FORCE_INLINE detail::VariantData* getData() const {
@ -36,13 +36,14 @@ class JsonVariant : public detail::VariantRefBase<JsonVariant>,
} }
detail::VariantData* data_; detail::VariantData* data_;
detail::MemoryPool* pool_; detail::ResourceManager* resources_;
}; };
template <> template <>
struct Converter<JsonVariant> : private detail::VariantAttorney { struct Converter<JsonVariant> : private detail::VariantAttorney {
static void toJson(JsonVariant src, JsonVariant dst) { static void toJson(JsonVariant src, JsonVariant dst) {
detail::variantCopyFrom(getData(dst), getData(src), getPool(dst)); detail::variantCopyFrom(getData(dst), getData(src),
getResourceManager(dst));
} }
static JsonVariant fromJson(JsonVariant src) { static JsonVariant fromJson(JsonVariant src) {
@ -65,7 +66,7 @@ struct Converter<JsonVariant> : private detail::VariantAttorney {
template <> template <>
struct Converter<JsonVariantConst> : private detail::VariantAttorney { struct Converter<JsonVariantConst> : private detail::VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) { static void toJson(JsonVariantConst src, JsonVariant dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst)); variantCopyFrom(getData(dst), getData(src), getResourceManager(dst));
} }
static JsonVariantConst fromJson(JsonVariantConst src) { static JsonVariantConst fromJson(JsonVariantConst src) {
@ -84,25 +85,26 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
template <typename TDerived> template <typename TDerived>
inline JsonVariant VariantRefBase<TDerived>::add() const { inline JsonVariant VariantRefBase<TDerived>::add() const {
return JsonVariant(getPool(), return JsonVariant(
variantAddElement(getOrCreateData(), getPool())); getResourceManager(),
variantAddElement(getOrCreateData(), getResourceManager()));
} }
template <typename TDerived> template <typename TDerived>
inline JsonVariant VariantRefBase<TDerived>::getVariant() const { inline JsonVariant VariantRefBase<TDerived>::getVariant() const {
return JsonVariant(getPool(), getData()); return JsonVariant(getResourceManager(), getData());
} }
template <typename TDerived> template <typename TDerived>
inline JsonVariant VariantRefBase<TDerived>::getOrCreateVariant() const { inline JsonVariant VariantRefBase<TDerived>::getOrCreateVariant() const {
return JsonVariant(getPool(), getOrCreateData()); return JsonVariant(getResourceManager(), getOrCreateData());
} }
template <typename TDerived> template <typename TDerived>
template <typename T> template <typename T>
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type
VariantRefBase<TDerived>::to() const { VariantRefBase<TDerived>::to() const {
variantSetNull(getOrCreateData(), getPool()); variantSetNull(getOrCreateData(), getResourceManager());
return *this; return *this;
} }

View File

@ -7,7 +7,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> // for uint8_t #include <stdint.h> // for uint8_t
#include <ArduinoJson/Memory/MemoryPool.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp> #include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/IsString.hpp> #include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp> #include <ArduinoJson/Strings/StringAdapters.hpp>

View File

@ -18,11 +18,11 @@ inline size_t slotSize(const VariantSlot* var) {
return n; return n;
} }
inline void slotRelease(VariantSlot* slot, MemoryPool* pool) { inline void slotRelease(VariantSlot* slot, ResourceManager* resources) {
ARDUINOJSON_ASSERT(slot != nullptr); ARDUINOJSON_ASSERT(slot != nullptr);
if (slot->ownsKey()) if (slot->ownsKey())
pool->dereferenceString(slot->key()); resources->dereferenceString(slot->key());
slot->data()->setNull(pool); slot->data()->setNull(resources);
} }
ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -30,8 +30,8 @@ class VariantAttorney {
public: public:
template <typename TClient> template <typename TClient>
FORCE_INLINE static MemoryPool* getPool(TClient& client) { FORCE_INLINE static ResourceManager* getResourceManager(TClient& client) {
return client.getPool(); return client.getResourceManager();
} }
template <typename TClient> template <typename TClient>

View File

@ -14,14 +14,15 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
VariantData* collectionAddElement(CollectionData* array, MemoryPool* pool); VariantData* collectionAddElement(CollectionData* array,
ResourceManager* resources);
bool collectionCopy(CollectionData* dst, const CollectionData* src, bool collectionCopy(CollectionData* dst, const CollectionData* src,
MemoryPool* pool); ResourceManager* resources);
void collectionRemoveElement(CollectionData* data, size_t index, void collectionRemoveElement(CollectionData* data, size_t index,
MemoryPool* pool); ResourceManager* resources);
template <typename T> template <typename T>
T parseNumber(const char* s); T parseNumber(const char* s);
void slotRelease(VariantSlot* slot, MemoryPool* pool); void slotRelease(VariantSlot* slot, ResourceManager* resources);
class VariantData { class VariantData {
VariantContent content_; // must be first to allow cast from array to variant VariantContent content_; // must be first to allow cast from array to variant
@ -68,9 +69,9 @@ class VariantData {
} }
} }
VariantData* addElement(MemoryPool* pool) { VariantData* addElement(ResourceManager* resources) {
auto array = isNull() ? &toArray() : asArray(); auto array = isNull() ? &toArray() : asArray();
return collectionAddElement(array, pool); return collectionAddElement(array, resources);
} }
bool asBoolean() const { bool asBoolean() const {
@ -172,20 +173,20 @@ class VariantData {
} }
} }
bool copyFrom(const VariantData* src, MemoryPool* pool) { bool copyFrom(const VariantData* src, ResourceManager* resources) {
release(pool); release(resources);
if (!src) { if (!src) {
setNull(); setNull();
return true; return true;
} }
switch (src->type()) { switch (src->type()) {
case VALUE_IS_ARRAY: case VALUE_IS_ARRAY:
return collectionCopy(&toArray(), src->asArray(), pool); return collectionCopy(&toArray(), src->asArray(), resources);
case VALUE_IS_OBJECT: case VALUE_IS_OBJECT:
return collectionCopy(&toObject(), src->asObject(), pool); return collectionCopy(&toObject(), src->asObject(), resources);
case VALUE_IS_OWNED_STRING: { case VALUE_IS_OWNED_STRING: {
auto str = adaptString(src->asString()); auto str = adaptString(src->asString());
auto dup = pool->saveString(str); auto dup = resources->saveString(str);
if (!dup) if (!dup)
return false; return false;
setOwnedString(dup); setOwnedString(dup);
@ -193,7 +194,7 @@ class VariantData {
} }
case VALUE_IS_RAW_STRING: { case VALUE_IS_RAW_STRING: {
auto str = adaptString(src->asRawString()); auto str = adaptString(src->asRawString());
auto dup = pool->saveString(str); auto dup = resources->saveString(str);
if (!dup) if (!dup)
return false; return false;
setRawString(dup); setRawString(dup);
@ -221,7 +222,7 @@ class VariantData {
return slotData(object->get(key)); return slotData(object->get(key));
} }
VariantData* getOrAddElement(size_t index, MemoryPool* pool) { VariantData* getOrAddElement(size_t index, ResourceManager* resources) {
auto array = isNull() ? &toArray() : asArray(); auto array = isNull() ? &toArray() : asArray();
if (!array) if (!array)
return nullptr; return nullptr;
@ -233,7 +234,7 @@ class VariantData {
if (!slot) if (!slot)
index++; index++;
while (index > 0) { while (index > 0) {
slot = new (pool) VariantSlot(); slot = new (resources) VariantSlot();
if (!slot) if (!slot)
return nullptr; return nullptr;
array->add(slot); array->add(slot);
@ -243,7 +244,7 @@ class VariantData {
} }
template <typename TAdaptedString> template <typename TAdaptedString>
VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool) { VariantData* getOrAddMember(TAdaptedString key, ResourceManager* resources) {
if (key.isNull()) if (key.isNull())
return nullptr; return nullptr;
auto obj = isNull() ? &toObject() : asObject(); auto obj = isNull() ? &toObject() : asObject();
@ -252,7 +253,7 @@ class VariantData {
auto slot = obj->get(key); auto slot = obj->get(key);
if (slot) if (slot)
return slot->data(); return slot->data();
return collectionAddMember(obj, key, pool); return collectionAddMember(obj, key, resources);
} }
bool isArray() const { bool isArray() const {
@ -334,13 +335,13 @@ class VariantData {
flags_ = uint8_t((flags_ & OWNED_KEY_BIT) | (src.flags_ & ~OWNED_KEY_BIT)); flags_ = uint8_t((flags_ & OWNED_KEY_BIT) | (src.flags_ & ~OWNED_KEY_BIT));
} }
void removeElement(size_t index, MemoryPool* pool) { void removeElement(size_t index, ResourceManager* resources) {
collectionRemoveElement(asArray(), index, pool); collectionRemoveElement(asArray(), index, resources);
} }
template <typename TAdaptedString> template <typename TAdaptedString>
void removeMember(TAdaptedString key, MemoryPool* pool) { void removeMember(TAdaptedString key, ResourceManager* resources) {
collectionRemoveMember(asObject(), key, pool); collectionRemoveMember(asObject(), key, resources);
} }
void reset() { void reset() {
@ -352,8 +353,8 @@ class VariantData {
content_.asBoolean = value; content_.asBoolean = value;
} }
void setBoolean(bool value, MemoryPool* pool) { void setBoolean(bool value, ResourceManager* resources) {
release(pool); release(resources);
setBoolean(value); setBoolean(value);
} }
@ -362,8 +363,8 @@ class VariantData {
content_.asFloat = value; content_.asFloat = value;
} }
void setFloat(JsonFloat value, MemoryPool* pool) { void setFloat(JsonFloat value, ResourceManager* resources) {
release(pool); release(resources);
setFloat(value); setFloat(value);
} }
@ -380,8 +381,8 @@ class VariantData {
} }
template <typename T> template <typename T>
void setInteger(T value, MemoryPool* pool) { void setInteger(T value, ResourceManager* resources) {
release(pool); release(resources);
setInteger(value); setInteger(value);
} }
@ -389,8 +390,8 @@ class VariantData {
setType(VALUE_IS_NULL); setType(VALUE_IS_NULL);
} }
void setNull(MemoryPool* pool) { void setNull(ResourceManager* resources) {
release(pool); release(resources);
setNull(); setNull();
} }
@ -401,9 +402,9 @@ class VariantData {
} }
template <typename T> template <typename T>
void setRawString(SerializedValue<T> value, MemoryPool* pool) { void setRawString(SerializedValue<T> value, ResourceManager* resources) {
release(pool); release(resources);
auto dup = pool->saveString(adaptString(value.data(), value.size())); auto dup = resources->saveString(adaptString(value.data(), value.size()));
if (dup) if (dup)
setRawString(dup); setRawString(dup);
else else
@ -411,8 +412,8 @@ class VariantData {
} }
template <typename TAdaptedString> template <typename TAdaptedString>
void setString(TAdaptedString value, MemoryPool* pool) { void setString(TAdaptedString value, ResourceManager* resources) {
setNull(pool); setNull(resources);
if (value.isNull()) if (value.isNull())
return; return;
@ -422,7 +423,7 @@ class VariantData {
return; return;
} }
auto dup = pool->saveString(value); auto dup = resources->saveString(value);
if (dup) if (dup)
setOwnedString(dup); setOwnedString(dup);
} }
@ -449,8 +450,8 @@ class VariantData {
return content_.asCollection; return content_.asCollection;
} }
CollectionData& toArray(MemoryPool* pool) { CollectionData& toArray(ResourceManager* resources) {
release(pool); release(resources);
return toArray(); return toArray();
} }
@ -460,8 +461,8 @@ class VariantData {
return content_.asCollection; return content_.asCollection;
} }
CollectionData& toObject(MemoryPool* pool) { CollectionData& toObject(ResourceManager* resources) {
release(pool); release(resources);
return toObject(); return toObject();
} }
@ -470,14 +471,14 @@ class VariantData {
} }
private: private:
void release(MemoryPool* pool) { void release(ResourceManager* resources) {
if (flags_ & OWNED_VALUE_BIT) if (flags_ & OWNED_VALUE_BIT)
pool->dereferenceString(content_.asOwnedString->data); resources->dereferenceString(content_.asOwnedString->data);
auto c = asCollection(); auto c = asCollection();
if (c) { if (c) {
for (auto slot = c->head(); slot; slot = slot->next()) for (auto slot = c->head(); slot; slot = slot->next())
slotRelease(slot, pool); slotRelease(slot, resources);
} }
} }
@ -497,16 +498,17 @@ typename TVisitor::result_type variantAccept(const VariantData* var,
} }
inline bool variantCopyFrom(VariantData* dst, const VariantData* src, inline bool variantCopyFrom(VariantData* dst, const VariantData* src,
MemoryPool* pool) { ResourceManager* resources) {
if (!dst) if (!dst)
return false; return false;
return dst->copyFrom(src, pool); return dst->copyFrom(src, resources);
} }
inline VariantData* variantAddElement(VariantData* var, MemoryPool* pool) { inline VariantData* variantAddElement(VariantData* var,
ResourceManager* resources) {
if (!var) if (!var)
return nullptr; return nullptr;
return var->addElement(pool); return var->addElement(resources);
} }
inline VariantData* variantGetElement(const VariantData* var, size_t index) { inline VariantData* variantGetElement(const VariantData* var, size_t index) {
@ -521,18 +523,18 @@ VariantData* variantGetMember(const VariantData* var, TAdaptedString key) {
} }
inline VariantData* variantGetOrAddElement(VariantData* var, size_t index, inline VariantData* variantGetOrAddElement(VariantData* var, size_t index,
MemoryPool* pool) { ResourceManager* resources) {
if (!var) if (!var)
return nullptr; return nullptr;
return var->getOrAddElement(index, pool); return var->getOrAddElement(index, resources);
} }
template <typename TAdaptedString> template <typename TAdaptedString>
VariantData* variantGetOrAddMember(VariantData* var, TAdaptedString key, VariantData* variantGetOrAddMember(VariantData* var, TAdaptedString key,
MemoryPool* pool) { ResourceManager* resources) {
if (!var) if (!var)
return nullptr; return nullptr;
return var->getOrAddMember(key, pool); return var->getOrAddMember(key, resources);
} }
inline bool variantIsNull(const VariantData* var) { inline bool variantIsNull(const VariantData* var) {
@ -548,76 +550,79 @@ inline size_t variantNesting(const VariantData* var) {
} }
inline void variantRemoveElement(VariantData* var, size_t index, inline void variantRemoveElement(VariantData* var, size_t index,
MemoryPool* pool) { ResourceManager* resources) {
if (!var) if (!var)
return; return;
var->removeElement(index, pool); var->removeElement(index, resources);
} }
template <typename TAdaptedString> template <typename TAdaptedString>
void variantRemoveMember(VariantData* var, TAdaptedString key, void variantRemoveMember(VariantData* var, TAdaptedString key,
MemoryPool* pool) { ResourceManager* resources) {
if (!var) if (!var)
return; return;
var->removeMember(key, pool); var->removeMember(key, resources);
} }
inline void variantSetBoolean(VariantData* var, bool value, MemoryPool* pool) { inline void variantSetBoolean(VariantData* var, bool value,
ResourceManager* resources) {
if (!var) if (!var)
return; return;
var->setBoolean(value, pool); var->setBoolean(value, resources);
} }
inline void variantSetFloat(VariantData* var, JsonFloat value, inline void variantSetFloat(VariantData* var, JsonFloat value,
MemoryPool* pool) { ResourceManager* resources) {
if (!var) if (!var)
return; return;
var->setFloat(value, pool); var->setFloat(value, resources);
} }
template <typename T> template <typename T>
void variantSetInteger(VariantData* var, T value, MemoryPool* pool) { void variantSetInteger(VariantData* var, T value, ResourceManager* resources) {
if (!var) if (!var)
return; return;
var->setInteger(value, pool); var->setInteger(value, resources);
} }
inline void variantSetNull(VariantData* var, MemoryPool* pool) { inline void variantSetNull(VariantData* var, ResourceManager* resources) {
if (!var) if (!var)
return; return;
var->setNull(pool); var->setNull(resources);
} }
template <typename T> template <typename T>
void variantSetRawString(VariantData* var, SerializedValue<T> value, void variantSetRawString(VariantData* var, SerializedValue<T> value,
MemoryPool* pool) { ResourceManager* resources) {
if (!var) if (!var)
return; return;
var->setRawString(value, pool); var->setRawString(value, resources);
} }
template <typename TAdaptedString> template <typename TAdaptedString>
void variantSetString(VariantData* var, TAdaptedString value, void variantSetString(VariantData* var, TAdaptedString value,
MemoryPool* pool) { ResourceManager* resources) {
if (!var) if (!var)
return; return;
var->setString(value, pool); var->setString(value, resources);
} }
inline size_t variantSize(const VariantData* var) { inline size_t variantSize(const VariantData* var) {
return var != 0 ? var->size() : 0; return var != 0 ? var->size() : 0;
} }
inline CollectionData* variantToArray(VariantData* var, MemoryPool* pool) { inline CollectionData* variantToArray(VariantData* var,
ResourceManager* resources) {
if (!var) if (!var)
return 0; return 0;
return &var->toArray(pool); return &var->toArray(resources);
} }
inline CollectionData* variantToObject(VariantData* var, MemoryPool* pool) { inline CollectionData* variantToObject(VariantData* var,
ResourceManager* resources) {
if (!var) if (!var)
return 0; return 0;
return &var->toObject(pool); return &var->toObject(resources);
} }
ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_END_PRIVATE_NAMESPACE

View File

@ -30,7 +30,7 @@ class VariantRefBase : public VariantTag {
// ⚠️ Doesn't release the memory associated with the previous value. // ⚠️ Doesn't release the memory associated with the previous value.
// https://arduinojson.org/v6/api/jsonvariant/clear/ // https://arduinojson.org/v6/api/jsonvariant/clear/
FORCE_INLINE void clear() const { FORCE_INLINE void clear() const {
variantSetNull(getOrCreateData(), getPool()); variantSetNull(getOrCreateData(), getResourceManager());
} }
// Returns true if the value is null or the reference is unbound. // Returns true if the value is null or the reference is unbound.
@ -112,7 +112,7 @@ class VariantRefBase : public VariantTag {
VariantData* data = getOrCreateData(); VariantData* data = getOrCreateData();
if (!data) if (!data)
return; return;
variantSetNull(data, getPool()); variantSetNull(data, getResourceManager());
const VariantData* targetData = VariantAttorney::getData(target); const VariantData* targetData = VariantAttorney::getData(target);
if (targetData) if (targetData)
*data = *targetData; *data = *targetData;
@ -123,8 +123,8 @@ class VariantRefBase : public VariantTag {
template <typename T> template <typename T>
FORCE_INLINE bool set(const T& value) const { FORCE_INLINE bool set(const T& value) const {
Converter<T>::toJson(value, getOrCreateVariant()); Converter<T>::toJson(value, getOrCreateVariant());
MemoryPool* pool = getPool(); auto resources = getResourceManager();
return pool && !pool->overflowed(); return resources && !resources->overflowed();
} }
// Copies the specified value. // Copies the specified value.
@ -132,8 +132,8 @@ class VariantRefBase : public VariantTag {
template <typename T> template <typename T>
FORCE_INLINE bool set(T* value) const { FORCE_INLINE bool set(T* value) const {
Converter<T*>::toJson(value, getOrCreateVariant()); Converter<T*>::toJson(value, getOrCreateVariant());
MemoryPool* pool = getPool(); auto resources = getResourceManager();
return pool && !pool->overflowed(); return resources && !resources->overflowed();
} }
// Returns the size of the array or object. // Returns the size of the array or object.
@ -178,7 +178,7 @@ class VariantRefBase : public VariantTag {
// ⚠️ Doesn't release the memory associated with the removed element. // ⚠️ Doesn't release the memory associated with the removed element.
// https://arduinojson.org/v6/api/jsonvariant/remove/ // https://arduinojson.org/v6/api/jsonvariant/remove/
FORCE_INLINE void remove(size_t index) const { FORCE_INLINE void remove(size_t index) const {
variantRemoveElement(getData(), index, getPool()); variantRemoveElement(getData(), index, getResourceManager());
} }
// Removes a member of the object. // Removes a member of the object.
@ -187,7 +187,7 @@ class VariantRefBase : public VariantTag {
template <typename TChar> template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove( FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
TChar* key) const { TChar* key) const {
variantRemoveMember(getData(), adaptString(key), getPool()); variantRemoveMember(getData(), adaptString(key), getResourceManager());
} }
// Removes a member of the object. // Removes a member of the object.
@ -196,7 +196,7 @@ class VariantRefBase : public VariantTag {
template <typename TString> template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove( FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString& key) const { const TString& key) const {
variantRemoveMember(getData(), adaptString(key), getPool()); variantRemoveMember(getData(), adaptString(key), getResourceManager());
} }
// Creates an array and appends it to the array. // Creates an array and appends it to the array.
@ -266,8 +266,8 @@ class VariantRefBase : public VariantTag {
return static_cast<const TDerived&>(*this); return static_cast<const TDerived&>(*this);
} }
FORCE_INLINE MemoryPool* getPool() const { FORCE_INLINE ResourceManager* getResourceManager() const {
return VariantAttorney::getPool(derived()); return VariantAttorney::getResourceManager(derived());
} }
FORCE_INLINE VariantData* getData() const { FORCE_INLINE VariantData* getData() const {

View File

@ -4,7 +4,7 @@
#pragma once #pragma once
#include <ArduinoJson/Memory/MemoryPool.hpp> #include <ArduinoJson/Memory/ResourceManager.hpp>
#include <ArduinoJson/Polyfills/integer.hpp> #include <ArduinoJson/Polyfills/integer.hpp>
#include <ArduinoJson/Polyfills/limits.hpp> #include <ArduinoJson/Polyfills/limits.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp> #include <ArduinoJson/Polyfills/type_traits.hpp>
@ -26,11 +26,11 @@ class VariantSlot {
const char* key_; const char* key_;
public: public:
static void* operator new(size_t size, MemoryPool* pool) noexcept { static void* operator new(size_t size, ResourceManager* resources) noexcept {
return pool->allocFromPool(size); return resources->allocFromPool(size);
} }
static void operator delete(void*, MemoryPool*) noexcept { static void operator delete(void*, ResourceManager*) noexcept {
// we cannot release memory from the pool // we cannot release memory from the pool
} }