forked from bblanchon/ArduinoJson
Rename MemoryPool
to ResourceManager
This commit is contained in:
@ -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)
|
||||||
|
@ -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") {
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
||||||
|
@ -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"
|
||||||
)
|
)
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
51
extras/tests/ResourceManager/allocVariant.cpp
Normal file
51
extras/tests/ResourceManager/allocVariant.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
69
extras/tests/ResourceManager/saveString.cpp
Normal file
69
extras/tests/ResourceManager/saveString.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
35
extras/tests/ResourceManager/size.cpp
Normal file
35
extras/tests/ResourceManager/size.cpp
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
@ -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_;
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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_;
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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_;
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user