mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-29 10:17:39 +02:00
Make VariantSlot
a union
. Include next slot id in VariantData
This commit is contained in:
@ -9,28 +9,28 @@
|
|||||||
|
|
||||||
using namespace ArduinoJson::detail;
|
using namespace ArduinoJson::detail;
|
||||||
|
|
||||||
TEST_CASE("ResourceManager::allocSlot()") {
|
TEST_CASE("ResourceManager::allocVariant()") {
|
||||||
SECTION("Returns different pointer") {
|
SECTION("Returns different pointer") {
|
||||||
ResourceManager resources;
|
ResourceManager resources;
|
||||||
|
|
||||||
VariantSlot* s1 = resources.allocSlot();
|
auto s1 = resources.allocVariant();
|
||||||
REQUIRE(s1 != 0);
|
REQUIRE(s1.data() != nullptr);
|
||||||
VariantSlot* s2 = resources.allocSlot();
|
auto s2 = resources.allocVariant();
|
||||||
REQUIRE(s2 != 0);
|
REQUIRE(s2.data() != nullptr);
|
||||||
|
|
||||||
REQUIRE(s1 != s2);
|
REQUIRE(s1.data() != s2.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Returns the same slot after calling freeSlot()") {
|
SECTION("Returns the same slot after calling freeVariant()") {
|
||||||
ResourceManager resources;
|
ResourceManager resources;
|
||||||
|
|
||||||
auto s1 = resources.allocSlot();
|
auto s1 = resources.allocVariant();
|
||||||
auto s2 = resources.allocSlot();
|
auto s2 = resources.allocVariant();
|
||||||
resources.freeSlot(s1);
|
resources.freeVariant(s1);
|
||||||
resources.freeSlot(s2);
|
resources.freeVariant(s2);
|
||||||
auto s3 = resources.allocSlot();
|
auto s3 = resources.allocVariant();
|
||||||
auto s4 = resources.allocSlot();
|
auto s4 = resources.allocVariant();
|
||||||
auto s5 = resources.allocSlot();
|
auto s5 = resources.allocVariant();
|
||||||
|
|
||||||
REQUIRE(s2.id() != s1.id());
|
REQUIRE(s2.id() != s1.id());
|
||||||
REQUIRE(s3.id() == s2.id());
|
REQUIRE(s3.id() == s2.id());
|
||||||
@ -42,26 +42,26 @@ TEST_CASE("ResourceManager::allocSlot()") {
|
|||||||
SECTION("Returns aligned pointers") {
|
SECTION("Returns aligned pointers") {
|
||||||
ResourceManager resources;
|
ResourceManager resources;
|
||||||
|
|
||||||
REQUIRE(isAligned(resources.allocSlot().operator VariantSlot*()));
|
REQUIRE(isAligned(resources.allocVariant().data()));
|
||||||
REQUIRE(isAligned(resources.allocSlot().operator VariantSlot*()));
|
REQUIRE(isAligned(resources.allocVariant().data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Returns null if pool list allocation fails") {
|
SECTION("Returns null if pool list allocation fails") {
|
||||||
ResourceManager resources(FailingAllocator::instance());
|
ResourceManager resources(FailingAllocator::instance());
|
||||||
|
|
||||||
auto variant = resources.allocSlot();
|
auto variant = resources.allocVariant();
|
||||||
REQUIRE(variant.id() == NULL_SLOT);
|
REQUIRE(variant.id() == NULL_SLOT);
|
||||||
REQUIRE(static_cast<VariantSlot*>(variant) == nullptr);
|
REQUIRE(variant.data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Returns null if pool allocation fails") {
|
SECTION("Returns null if pool allocation fails") {
|
||||||
ResourceManager resources(FailingAllocator::instance());
|
ResourceManager resources(FailingAllocator::instance());
|
||||||
|
|
||||||
resources.allocSlot();
|
resources.allocVariant();
|
||||||
|
|
||||||
auto variant = resources.allocSlot();
|
auto variant = resources.allocVariant();
|
||||||
REQUIRE(variant.id() == NULL_SLOT);
|
REQUIRE(variant.id() == NULL_SLOT);
|
||||||
REQUIRE(static_cast<VariantSlot*>(variant) == nullptr);
|
REQUIRE(variant.data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Try overflow pool counter") {
|
SECTION("Try overflow pool counter") {
|
||||||
@ -73,18 +73,18 @@ TEST_CASE("ResourceManager::allocSlot()") {
|
|||||||
|
|
||||||
// fill all the pools
|
// fill all the pools
|
||||||
for (SlotId i = 0; i < NULL_SLOT; i++) {
|
for (SlotId i = 0; i < NULL_SLOT; i++) {
|
||||||
auto slot = resources.allocSlot();
|
auto slot = resources.allocVariant();
|
||||||
REQUIRE(slot.id() == i); // or != NULL_SLOT
|
REQUIRE(slot.id() == i); // or != NULL_SLOT
|
||||||
REQUIRE(static_cast<VariantSlot*>(slot) != nullptr);
|
REQUIRE(slot.data() != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
REQUIRE(resources.overflowed() == false);
|
REQUIRE(resources.overflowed() == false);
|
||||||
|
|
||||||
// now all allocations should fail
|
// now all allocations should fail
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
auto slot = resources.allocSlot();
|
auto slot = resources.allocVariant();
|
||||||
REQUIRE(slot.id() == NULL_SLOT);
|
REQUIRE(slot.id() == NULL_SLOT);
|
||||||
REQUIRE(static_cast<VariantSlot*>(slot) == nullptr);
|
REQUIRE(slot.data() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
REQUIRE(resources.overflowed() == true);
|
REQUIRE(resources.overflowed() == true);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||||
|
#include <ArduinoJson/Memory/ResourceManagerImpl.hpp>
|
||||||
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
||||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
@ -13,7 +14,7 @@ TEST_CASE("ResourceManager::clear()") {
|
|||||||
ResourceManager resources;
|
ResourceManager resources;
|
||||||
|
|
||||||
SECTION("Discards allocated variants") {
|
SECTION("Discards allocated variants") {
|
||||||
resources.allocSlot();
|
resources.allocVariant();
|
||||||
|
|
||||||
resources.clear();
|
resources.clear();
|
||||||
REQUIRE(resources.size() == 0);
|
REQUIRE(resources.size() == 0);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||||
|
#include <ArduinoJson/Memory/ResourceManagerImpl.hpp>
|
||||||
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ TEST_CASE("ResourceManager::shrinkToFit()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("only one pool") {
|
SECTION("only one pool") {
|
||||||
resources.allocSlot();
|
resources.allocVariant();
|
||||||
|
|
||||||
resources.shrinkToFit();
|
resources.shrinkToFit();
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ TEST_CASE("ResourceManager::shrinkToFit()") {
|
|||||||
for (size_t i = 0;
|
for (size_t i = 0;
|
||||||
i < ARDUINOJSON_POOL_CAPACITY * ARDUINOJSON_INITIAL_POOL_COUNT + 1;
|
i < ARDUINOJSON_POOL_CAPACITY * ARDUINOJSON_INITIAL_POOL_COUNT + 1;
|
||||||
i++)
|
i++)
|
||||||
resources.allocSlot();
|
resources.allocVariant();
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog{
|
AllocatorLog{
|
||||||
Allocate(sizeofPool()) * ARDUINOJSON_INITIAL_POOL_COUNT,
|
Allocate(sizeofPool()) * ARDUINOJSON_INITIAL_POOL_COUNT,
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||||
|
#include <ArduinoJson/Memory/ResourceManagerImpl.hpp>
|
||||||
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
@ -21,10 +22,10 @@ TEST_CASE("ResourceManager::size()") {
|
|||||||
SECTION("Doesn't grow when allocation of second pool fails") {
|
SECTION("Doesn't grow when allocation of second pool fails") {
|
||||||
timebomb.setCountdown(1);
|
timebomb.setCountdown(1);
|
||||||
for (size_t i = 0; i < ARDUINOJSON_POOL_CAPACITY; i++)
|
for (size_t i = 0; i < ARDUINOJSON_POOL_CAPACITY; i++)
|
||||||
resources.allocSlot();
|
resources.allocVariant();
|
||||||
size_t size = resources.size();
|
size_t size = resources.size();
|
||||||
|
|
||||||
resources.allocSlot();
|
resources.allocVariant();
|
||||||
|
|
||||||
REQUIRE(size == resources.size());
|
REQUIRE(size == resources.size());
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <ArduinoJson/Memory/Alignment.hpp>
|
#include <ArduinoJson/Memory/Alignment.hpp>
|
||||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||||
|
#include <ArduinoJson/Memory/ResourceManagerImpl.hpp>
|
||||||
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ using namespace ArduinoJson::detail;
|
|||||||
static void fullPreallocatedPools(ResourceManager& resources) {
|
static void fullPreallocatedPools(ResourceManager& resources) {
|
||||||
for (int i = 0;
|
for (int i = 0;
|
||||||
i < ARDUINOJSON_INITIAL_POOL_COUNT * ARDUINOJSON_POOL_CAPACITY; i++)
|
i < ARDUINOJSON_INITIAL_POOL_COUNT * ARDUINOJSON_POOL_CAPACITY; i++)
|
||||||
resources.allocSlot();
|
resources.allocVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ResourceManager::swap()") {
|
TEST_CASE("ResourceManager::swap()") {
|
||||||
@ -23,13 +24,13 @@ TEST_CASE("ResourceManager::swap()") {
|
|||||||
ResourceManager a(&spy);
|
ResourceManager a(&spy);
|
||||||
ResourceManager b(&spy);
|
ResourceManager b(&spy);
|
||||||
|
|
||||||
auto a1 = a.allocSlot();
|
auto a1 = a.allocVariant();
|
||||||
auto b1 = b.allocSlot();
|
auto b1 = b.allocVariant();
|
||||||
|
|
||||||
swap(a, b);
|
swap(a, b);
|
||||||
|
|
||||||
REQUIRE(a1->data() == b.getSlot(a1.id())->data());
|
REQUIRE(a1.data() == b.getVariant(a1.id()));
|
||||||
REQUIRE(b1->data() == a.getSlot(b1.id())->data());
|
REQUIRE(b1.data() == a.getVariant(b1.id()));
|
||||||
|
|
||||||
REQUIRE(spy.log() == AllocatorLog{
|
REQUIRE(spy.log() == AllocatorLog{
|
||||||
Allocate(sizeofPool()) * 2,
|
Allocate(sizeofPool()) * 2,
|
||||||
@ -42,12 +43,12 @@ TEST_CASE("ResourceManager::swap()") {
|
|||||||
ResourceManager b(&spy);
|
ResourceManager b(&spy);
|
||||||
fullPreallocatedPools(b);
|
fullPreallocatedPools(b);
|
||||||
|
|
||||||
auto a1 = a.allocSlot();
|
auto a1 = a.allocVariant();
|
||||||
auto b1 = b.allocSlot();
|
auto b1 = b.allocVariant();
|
||||||
swap(a, b);
|
swap(a, b);
|
||||||
|
|
||||||
REQUIRE(a1->data() == b.getSlot(a1.id())->data());
|
REQUIRE(a1.data() == b.getVariant(a1.id()));
|
||||||
REQUIRE(b1->data() == a.getSlot(b1.id())->data());
|
REQUIRE(b1.data() == a.getVariant(b1.id()));
|
||||||
|
|
||||||
REQUIRE(spy.log() ==
|
REQUIRE(spy.log() ==
|
||||||
AllocatorLog{
|
AllocatorLog{
|
||||||
@ -63,12 +64,12 @@ TEST_CASE("ResourceManager::swap()") {
|
|||||||
fullPreallocatedPools(a);
|
fullPreallocatedPools(a);
|
||||||
ResourceManager b(&spy);
|
ResourceManager b(&spy);
|
||||||
|
|
||||||
auto a1 = a.allocSlot();
|
auto a1 = a.allocVariant();
|
||||||
auto b1 = b.allocSlot();
|
auto b1 = b.allocVariant();
|
||||||
swap(a, b);
|
swap(a, b);
|
||||||
|
|
||||||
REQUIRE(a1->data() == b.getSlot(a1.id())->data());
|
REQUIRE(a1.data() == b.getVariant(a1.id()));
|
||||||
REQUIRE(b1->data() == a.getSlot(b1.id())->data());
|
REQUIRE(b1.data() == a.getVariant(b1.id()));
|
||||||
|
|
||||||
REQUIRE(spy.log() ==
|
REQUIRE(spy.log() ==
|
||||||
AllocatorLog{
|
AllocatorLog{
|
||||||
@ -85,12 +86,12 @@ TEST_CASE("ResourceManager::swap()") {
|
|||||||
ResourceManager b(&spy);
|
ResourceManager b(&spy);
|
||||||
fullPreallocatedPools(b);
|
fullPreallocatedPools(b);
|
||||||
|
|
||||||
auto a1 = a.allocSlot();
|
auto a1 = a.allocVariant();
|
||||||
auto b1 = b.allocSlot();
|
auto b1 = b.allocVariant();
|
||||||
|
|
||||||
swap(a, b);
|
swap(a, b);
|
||||||
|
|
||||||
REQUIRE(a1->data() == b.getSlot(a1.id())->data());
|
REQUIRE(a1.data() == b.getVariant(a1.id()));
|
||||||
REQUIRE(b1->data() == a.getSlot(b1.id())->data());
|
REQUIRE(b1.data() == a.getVariant(b1.id()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,11 @@ inline ArrayData::iterator ArrayData::at(
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline VariantData* ArrayData::addElement(ResourceManager* resources) {
|
inline VariantData* ArrayData::addElement(ResourceManager* resources) {
|
||||||
auto slot = resources->allocSlot();
|
auto slot = resources->allocVariant();
|
||||||
if (!slot)
|
if (!slot)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
CollectionData::appendOne(slot, resources);
|
CollectionData::appendOne(slot, resources);
|
||||||
return slot->data();
|
return slot.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline VariantData* ArrayData::getOrAddElement(size_t index,
|
inline VariantData* ArrayData::getOrAddElement(size_t index,
|
||||||
@ -58,12 +58,12 @@ inline void ArrayData::removeElement(size_t index, ResourceManager* resources) {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool ArrayData::addValue(T&& value, ResourceManager* resources) {
|
inline bool ArrayData::addValue(T&& value, ResourceManager* resources) {
|
||||||
ARDUINOJSON_ASSERT(resources != nullptr);
|
ARDUINOJSON_ASSERT(resources != nullptr);
|
||||||
auto slot = resources->allocSlot();
|
auto slot = resources->allocVariant();
|
||||||
if (!slot)
|
if (!slot)
|
||||||
return false;
|
return false;
|
||||||
JsonVariant variant(slot->data(), resources);
|
JsonVariant variant(slot.data(), resources);
|
||||||
if (!variant.set(detail::forward<T>(value))) {
|
if (!variant.set(detail::forward<T>(value))) {
|
||||||
resources->freeSlot(slot);
|
resources->freeVariant(slot);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CollectionData::appendOne(slot, resources);
|
CollectionData::appendOne(slot, resources);
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
class VariantData;
|
class VariantData;
|
||||||
class VariantSlot;
|
union VariantSlot;
|
||||||
|
|
||||||
class CollectionIterator {
|
class CollectionIterator {
|
||||||
friend class CollectionData;
|
friend class CollectionData;
|
||||||
@ -58,9 +58,9 @@ class CollectionIterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CollectionIterator(VariantSlot* slot, SlotId slotId);
|
CollectionIterator(VariantData* slot, SlotId slotId);
|
||||||
|
|
||||||
VariantSlot* slot_;
|
VariantData* slot_;
|
||||||
SlotId currentId_, nextId_;
|
SlotId currentId_, nextId_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ class CollectionData {
|
|||||||
using iterator = CollectionIterator;
|
using iterator = CollectionIterator;
|
||||||
|
|
||||||
iterator createIterator(const ResourceManager* resources) const {
|
iterator createIterator(const ResourceManager* resources) const {
|
||||||
return iterator(resources->getSlot(head_), head_);
|
return iterator(resources->getVariant(head_), head_);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size(const ResourceManager*) const;
|
size_t size(const ResourceManager*) const;
|
||||||
@ -98,15 +98,15 @@ class CollectionData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void appendOne(SlotWithId slot, const ResourceManager* resources);
|
void appendOne(VariantWithId slot, const ResourceManager* resources);
|
||||||
void appendPair(SlotWithId key, SlotWithId value,
|
void appendPair(VariantWithId key, VariantWithId value,
|
||||||
const ResourceManager* resources);
|
const ResourceManager* resources);
|
||||||
|
|
||||||
void removeOne(iterator it, ResourceManager* resources);
|
void removeOne(iterator it, ResourceManager* resources);
|
||||||
void removePair(iterator it, ResourceManager* resources);
|
void removePair(iterator it, ResourceManager* resources);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SlotWithId getPreviousSlot(VariantSlot*, const ResourceManager*) const;
|
VariantWithId getPreviousSlot(VariantData*, const ResourceManager*) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const VariantData* collectionToVariant(
|
inline const VariantData* collectionToVariant(
|
||||||
|
@ -12,23 +12,23 @@
|
|||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
inline CollectionIterator::CollectionIterator(VariantSlot* slot, SlotId slotId)
|
inline CollectionIterator::CollectionIterator(VariantData* slot, SlotId slotId)
|
||||||
: slot_(slot), currentId_(slotId) {
|
: slot_(slot), currentId_(slotId) {
|
||||||
nextId_ = slot_ ? slot_->next() : NULL_SLOT;
|
nextId_ = slot_ ? slot_->next() : NULL_SLOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CollectionIterator::next(const ResourceManager* resources) {
|
inline void CollectionIterator::next(const ResourceManager* resources) {
|
||||||
ARDUINOJSON_ASSERT(currentId_ != NULL_SLOT);
|
ARDUINOJSON_ASSERT(currentId_ != NULL_SLOT);
|
||||||
slot_ = resources->getSlot(nextId_);
|
slot_ = resources->getVariant(nextId_);
|
||||||
currentId_ = nextId_;
|
currentId_ = nextId_;
|
||||||
if (slot_)
|
if (slot_)
|
||||||
nextId_ = slot_->next();
|
nextId_ = slot_->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CollectionData::appendOne(SlotWithId slot,
|
inline void CollectionData::appendOne(VariantWithId slot,
|
||||||
const ResourceManager* resources) {
|
const ResourceManager* resources) {
|
||||||
if (tail_ != NULL_SLOT) {
|
if (tail_ != NULL_SLOT) {
|
||||||
auto tail = resources->getSlot(tail_);
|
auto tail = resources->getVariant(tail_);
|
||||||
tail->setNext(slot.id());
|
tail->setNext(slot.id());
|
||||||
tail_ = slot.id();
|
tail_ = slot.id();
|
||||||
} else {
|
} else {
|
||||||
@ -37,12 +37,12 @@ inline void CollectionData::appendOne(SlotWithId slot,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CollectionData::appendPair(SlotWithId key, SlotWithId value,
|
inline void CollectionData::appendPair(VariantWithId key, VariantWithId value,
|
||||||
const ResourceManager* resources) {
|
const ResourceManager* resources) {
|
||||||
key->setNext(value.id());
|
key->setNext(value.id());
|
||||||
|
|
||||||
if (tail_ != NULL_SLOT) {
|
if (tail_ != NULL_SLOT) {
|
||||||
auto tail = resources->getSlot(tail_);
|
auto tail = resources->getVariant(tail_);
|
||||||
tail->setNext(key.id());
|
tail->setNext(key.id());
|
||||||
tail_ = value.id();
|
tail_ = value.id();
|
||||||
} else {
|
} else {
|
||||||
@ -55,24 +55,24 @@ inline void CollectionData::clear(ResourceManager* resources) {
|
|||||||
auto next = head_;
|
auto next = head_;
|
||||||
while (next != NULL_SLOT) {
|
while (next != NULL_SLOT) {
|
||||||
auto currId = next;
|
auto currId = next;
|
||||||
auto slot = resources->getSlot(next);
|
auto slot = resources->getVariant(next);
|
||||||
next = slot->next();
|
next = slot->next();
|
||||||
resources->freeSlot(SlotWithId(slot, currId));
|
resources->freeVariant(VariantWithId(slot, currId));
|
||||||
}
|
}
|
||||||
|
|
||||||
head_ = NULL_SLOT;
|
head_ = NULL_SLOT;
|
||||||
tail_ = NULL_SLOT;
|
tail_ = NULL_SLOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline SlotWithId CollectionData::getPreviousSlot(
|
inline VariantWithId CollectionData::getPreviousSlot(
|
||||||
VariantSlot* target, const ResourceManager* resources) const {
|
VariantData* target, const ResourceManager* resources) const {
|
||||||
auto prev = SlotWithId();
|
auto prev = VariantWithId();
|
||||||
auto currentId = head_;
|
auto currentId = head_;
|
||||||
while (currentId != NULL_SLOT) {
|
while (currentId != NULL_SLOT) {
|
||||||
auto currentSlot = resources->getSlot(currentId);
|
auto currentSlot = resources->getVariant(currentId);
|
||||||
if (currentSlot == target)
|
if (currentSlot == target)
|
||||||
break;
|
break;
|
||||||
prev = SlotWithId(currentSlot, currentId);
|
prev = VariantWithId(currentSlot, currentId);
|
||||||
currentId = currentSlot->next();
|
currentId = currentSlot->next();
|
||||||
}
|
}
|
||||||
return prev;
|
return prev;
|
||||||
@ -90,7 +90,7 @@ inline void CollectionData::removeOne(iterator it, ResourceManager* resources) {
|
|||||||
head_ = next;
|
head_ = next;
|
||||||
if (next == NULL_SLOT)
|
if (next == NULL_SLOT)
|
||||||
tail_ = prev.id();
|
tail_ = prev.id();
|
||||||
resources->freeSlot({it.slot_, it.currentId_});
|
resources->freeVariant({it.slot_, it.currentId_});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CollectionData::removePair(ObjectData::iterator it,
|
inline void CollectionData::removePair(ObjectData::iterator it,
|
||||||
@ -101,11 +101,11 @@ inline void CollectionData::removePair(ObjectData::iterator it,
|
|||||||
auto keySlot = it.slot_;
|
auto keySlot = it.slot_;
|
||||||
|
|
||||||
auto valueId = it.nextId_;
|
auto valueId = it.nextId_;
|
||||||
auto valueSlot = resources->getSlot(valueId);
|
auto valueSlot = resources->getVariant(valueId);
|
||||||
|
|
||||||
// remove value slot
|
// remove value slot
|
||||||
keySlot->setNext(valueSlot->next());
|
keySlot->setNext(valueSlot->next());
|
||||||
resources->freeSlot({valueSlot, valueId});
|
resources->freeVariant({valueSlot, valueId});
|
||||||
|
|
||||||
// remove key slot
|
// remove key slot
|
||||||
removeOne(it, resources);
|
removeOne(it, resources);
|
||||||
|
@ -25,9 +25,9 @@ class JsonSerializer : public VariantDataVisitor<size_t> {
|
|||||||
auto slotId = array.head();
|
auto slotId = array.head();
|
||||||
|
|
||||||
while (slotId != NULL_SLOT) {
|
while (slotId != NULL_SLOT) {
|
||||||
auto slot = resources_->getSlot(slotId);
|
auto slot = resources_->getVariant(slotId);
|
||||||
|
|
||||||
slot->data()->accept(*this);
|
slot->accept(*this);
|
||||||
|
|
||||||
slotId = slot->next();
|
slotId = slot->next();
|
||||||
|
|
||||||
@ -47,8 +47,8 @@ class JsonSerializer : public VariantDataVisitor<size_t> {
|
|||||||
bool isKey = true;
|
bool isKey = true;
|
||||||
|
|
||||||
while (slotId != NULL_SLOT) {
|
while (slotId != NULL_SLOT) {
|
||||||
auto slot = resources_->getSlot(slotId);
|
auto slot = resources_->getVariant(slotId);
|
||||||
slot->data()->accept(*this);
|
slot->accept(*this);
|
||||||
|
|
||||||
slotId = slot->next();
|
slotId = slot->next();
|
||||||
|
|
||||||
|
@ -13,8 +13,10 @@
|
|||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
class VariantSlot;
|
union VariantSlot;
|
||||||
class VariantPool;
|
class VariantPool;
|
||||||
|
class VariantData;
|
||||||
|
class VariantWithId;
|
||||||
|
|
||||||
class ResourceManager {
|
class ResourceManager {
|
||||||
public:
|
public:
|
||||||
@ -49,18 +51,11 @@ class ResourceManager {
|
|||||||
return overflowed_;
|
return overflowed_;
|
||||||
}
|
}
|
||||||
|
|
||||||
SlotWithId allocSlot() {
|
VariantWithId allocVariant();
|
||||||
auto p = variantPools_.allocSlot(allocator_);
|
|
||||||
if (!p)
|
|
||||||
overflowed_ = true;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void freeSlot(SlotWithId slot);
|
void freeVariant(VariantWithId slot);
|
||||||
|
|
||||||
VariantSlot* getSlot(SlotId id) const {
|
VariantData* getVariant(SlotId id) const;
|
||||||
return variantPools_.getSlot(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
StringNode* saveString(TAdaptedString str) {
|
StringNode* saveString(TAdaptedString str) {
|
||||||
|
@ -7,12 +7,26 @@
|
|||||||
#include <ArduinoJson/Collection/CollectionData.hpp>
|
#include <ArduinoJson/Collection/CollectionData.hpp>
|
||||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||||
|
#include <ArduinoJson/Variant/VariantSlot.hpp>
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
inline void ResourceManager::freeSlot(SlotWithId slot) {
|
inline VariantWithId ResourceManager::allocVariant() {
|
||||||
slot->data()->setNull(this);
|
auto p = variantPools_.allocSlot(allocator_);
|
||||||
variantPools_.freeSlot(slot);
|
if (!p) {
|
||||||
|
overflowed_ = true;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return {new (&p->variant) VariantData, p.id()};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ResourceManager::freeVariant(VariantWithId variant) {
|
||||||
|
variant->setNull(this);
|
||||||
|
variantPools_.freeSlot(variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VariantData* ResourceManager::getVariant(SlotId id) const {
|
||||||
|
return reinterpret_cast<VariantData*>(variantPools_.getSlot(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
class VariantSlot;
|
union VariantSlot;
|
||||||
class VariantPool;
|
class VariantPool;
|
||||||
|
|
||||||
class StringPool {
|
class StringPool {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
class VariantSlot;
|
union VariantSlot;
|
||||||
using SlotId = uint_t<ARDUINOJSON_SLOT_ID_SIZE * 8>;
|
using SlotId = uint_t<ARDUINOJSON_SLOT_ID_SIZE * 8>;
|
||||||
using SlotCount = SlotId;
|
using SlotCount = SlotId;
|
||||||
const SlotId NULL_SLOT = SlotId(-1);
|
const SlotId NULL_SLOT = SlotId(-1);
|
||||||
@ -22,11 +22,15 @@ class SlotWithId {
|
|||||||
ARDUINOJSON_ASSERT((slot == nullptr) == (id == NULL_SLOT));
|
ARDUINOJSON_ASSERT((slot == nullptr) == (id == NULL_SLOT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit operator bool() const {
|
||||||
|
return slot_ != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
SlotId id() const {
|
SlotId id() const {
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator VariantSlot*() {
|
VariantSlot* slot() const {
|
||||||
return slot_;
|
return slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ inline SlotWithId VariantPool::allocSlot() {
|
|||||||
return {};
|
return {};
|
||||||
auto index = usage_++;
|
auto index = usage_++;
|
||||||
auto slot = &slots_[index];
|
auto slot = &slots_[index];
|
||||||
return {new (slot) VariantSlot, SlotId(index)};
|
return {slot, SlotId(index)};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline VariantSlot* VariantPool::getSlot(SlotId id) const {
|
inline VariantSlot* VariantPool::getSlot(SlotId id) const {
|
||||||
@ -69,12 +69,12 @@ inline SlotWithId VariantPoolList::allocFromFreeList() {
|
|||||||
ARDUINOJSON_ASSERT(freeList_ != NULL_SLOT);
|
ARDUINOJSON_ASSERT(freeList_ != NULL_SLOT);
|
||||||
auto id = freeList_;
|
auto id = freeList_;
|
||||||
auto slot = getSlot(freeList_);
|
auto slot = getSlot(freeList_);
|
||||||
freeList_ = slot->next();
|
freeList_ = slot->free.next;
|
||||||
return {new (slot) VariantSlot, id};
|
return {slot, id};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void VariantPoolList::freeSlot(SlotWithId slot) {
|
inline void VariantPoolList::freeSlot(SlotWithId slot) {
|
||||||
slot->setNext(freeList_);
|
slot->free.next = freeList_;
|
||||||
freeList_ = slot.id();
|
freeList_ = slot.id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,8 @@ class VariantPoolList {
|
|||||||
auto slot = pools_[poolIndex].allocSlot();
|
auto slot = pools_[poolIndex].allocSlot();
|
||||||
if (!slot)
|
if (!slot)
|
||||||
return {};
|
return {};
|
||||||
return {slot, SlotId(poolIndex * ARDUINOJSON_POOL_CAPACITY + slot.id())};
|
return {slot.slot(),
|
||||||
|
SlotId(poolIndex * ARDUINOJSON_POOL_CAPACITY + slot.id())};
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantPool* addPool(Allocator* allocator) {
|
VariantPool* addPool(Allocator* allocator) {
|
||||||
|
@ -61,8 +61,8 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
|
|||||||
|
|
||||||
auto slotId = array.head();
|
auto slotId = array.head();
|
||||||
while (slotId != NULL_SLOT) {
|
while (slotId != NULL_SLOT) {
|
||||||
auto slot = resources_->getSlot(slotId);
|
auto slot = resources_->getVariant(slotId);
|
||||||
slot->data()->accept(*this);
|
slot->accept(*this);
|
||||||
slotId = slot->next();
|
slotId = slot->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,8 +83,8 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
|
|||||||
|
|
||||||
auto slotId = object.head();
|
auto slotId = object.head();
|
||||||
while (slotId != NULL_SLOT) {
|
while (slotId != NULL_SLOT) {
|
||||||
auto slot = resources_->getSlot(slotId);
|
auto slot = resources_->getVariant(slotId);
|
||||||
slot->data()->accept(*this);
|
slot->accept(*this);
|
||||||
slotId = slot->next();
|
slotId = slot->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,20 +51,20 @@ inline void ObjectData::removeMember(TAdaptedString key,
|
|||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
inline VariantData* ObjectData::addMember(TAdaptedString key,
|
inline VariantData* ObjectData::addMember(TAdaptedString key,
|
||||||
ResourceManager* resources) {
|
ResourceManager* resources) {
|
||||||
auto keySlot = resources->allocSlot();
|
auto keySlot = resources->allocVariant();
|
||||||
if (!keySlot)
|
if (!keySlot)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto valueSlot = resources->allocSlot();
|
auto valueSlot = resources->allocVariant();
|
||||||
if (!valueSlot)
|
if (!valueSlot)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (!keySlot->data()->setString(key, resources))
|
if (!keySlot->setString(key, resources))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
CollectionData::appendPair(keySlot, valueSlot, resources);
|
CollectionData::appendPair(keySlot, valueSlot, resources);
|
||||||
|
|
||||||
return valueSlot->data();
|
return valueSlot.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/StringNode.hpp>
|
#include <ArduinoJson/Memory/StringNode.hpp>
|
||||||
|
#include <ArduinoJson/Memory/VariantPool.hpp>
|
||||||
#include <ArduinoJson/Misc/SerializedValue.hpp>
|
#include <ArduinoJson/Misc/SerializedValue.hpp>
|
||||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||||
#include <ArduinoJson/Strings/JsonString.hpp>
|
#include <ArduinoJson/Strings/JsonString.hpp>
|
||||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
#include <ArduinoJson/Variant/VariantContent.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantSlot.hpp>
|
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
@ -20,9 +20,25 @@ T parseNumber(const char* s);
|
|||||||
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
|
||||||
uint8_t type_;
|
uint8_t type_;
|
||||||
|
SlotId next_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VariantData() : type_(VALUE_IS_NULL) {}
|
// Placement new
|
||||||
|
static void* operator new(size_t, void* p) noexcept {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void operator delete(void*, void*) noexcept {}
|
||||||
|
|
||||||
|
VariantData() : type_(VALUE_IS_NULL), next_(NULL_SLOT) {}
|
||||||
|
|
||||||
|
SlotId next() const {
|
||||||
|
return next_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setNext(SlotId slot) {
|
||||||
|
next_ = slot;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename TVisitor>
|
template <typename TVisitor>
|
||||||
typename TVisitor::result_type accept(TVisitor& visit) const {
|
typename TVisitor::result_type accept(TVisitor& visit) const {
|
||||||
@ -518,4 +534,20 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class VariantWithId : public SlotWithId {
|
||||||
|
public:
|
||||||
|
VariantWithId() {}
|
||||||
|
VariantWithId(VariantData* data, SlotId id)
|
||||||
|
: SlotWithId(reinterpret_cast<VariantSlot*>(data), id) {}
|
||||||
|
|
||||||
|
VariantData* data() {
|
||||||
|
return reinterpret_cast<VariantData*>(slot());
|
||||||
|
}
|
||||||
|
|
||||||
|
VariantData* operator->() {
|
||||||
|
ARDUINOJSON_ASSERT(data() != nullptr);
|
||||||
|
return data();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
@ -7,52 +7,22 @@
|
|||||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||||
#include <ArduinoJson/Polyfills/limits.hpp>
|
#include <ArduinoJson/Polyfills/limits.hpp>
|
||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
struct StringNode;
|
struct StringNode;
|
||||||
|
|
||||||
class VariantSlot {
|
struct FreeSlot {
|
||||||
// CAUTION: same layout as VariantData
|
SlotId next;
|
||||||
// we cannot use composition because it adds padding
|
|
||||||
// (+20% on ESP8266 for example)
|
|
||||||
VariantContent content_;
|
|
||||||
uint8_t type_;
|
|
||||||
SlotId next_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Placement new
|
|
||||||
static void* operator new(size_t, void* p) noexcept {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void operator delete(void*, void*) noexcept {}
|
|
||||||
|
|
||||||
VariantSlot() : type_(0), next_(NULL_SLOT) {
|
|
||||||
(void)type_; // HACK: suppress Clang warning "private field is not used"
|
|
||||||
}
|
|
||||||
|
|
||||||
VariantData* data() {
|
|
||||||
return reinterpret_cast<VariantData*>(&content_);
|
|
||||||
}
|
|
||||||
|
|
||||||
const VariantData* data() const {
|
|
||||||
return reinterpret_cast<const VariantData*>(&content_);
|
|
||||||
}
|
|
||||||
|
|
||||||
SlotId next() const {
|
|
||||||
return next_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setNext(SlotId slot) {
|
|
||||||
next_ = slot;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline VariantData* slotData(VariantSlot* slot) {
|
union VariantSlot {
|
||||||
return reinterpret_cast<VariantData*>(slot);
|
VariantSlot() {}
|
||||||
}
|
|
||||||
|
VariantData variant;
|
||||||
|
FreeSlot free;
|
||||||
|
};
|
||||||
|
|
||||||
// Returns the size (in bytes) of an array with n elements.
|
// Returns the size (in bytes) of an array with n elements.
|
||||||
constexpr size_t sizeofArray(size_t n) {
|
constexpr size_t sizeofArray(size_t n) {
|
||||||
|
Reference in New Issue
Block a user