mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-19 21:42:30 +02:00
VariantPool: store VariantSlot
s instead of char
s
This commit is contained in:
@ -32,15 +32,15 @@ TEST_CASE("JsonDocument assignment") {
|
|||||||
|
|
||||||
SECTION("Copy assignment reallocates when capacity is smaller") {
|
SECTION("Copy assignment reallocates when capacity is smaller") {
|
||||||
JsonDocument doc1(4096, &spyingAllocator);
|
JsonDocument doc1(4096, &spyingAllocator);
|
||||||
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
deserializeJson(doc1, "[{\"hello\":\"world\"}]");
|
||||||
JsonDocument doc2(8, &spyingAllocator);
|
JsonDocument doc2(sizeofArray(1), &spyingAllocator);
|
||||||
spyingAllocator.clearLog();
|
spyingAllocator.clearLog();
|
||||||
|
|
||||||
doc2 = doc1;
|
doc2 = doc1;
|
||||||
|
|
||||||
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
|
REQUIRE(doc2.as<std::string>() == "[{\"hello\":\"world\"}]");
|
||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::Deallocate(8)
|
AllocatorLog() << AllocatorLog::Deallocate(sizeofArray(1))
|
||||||
<< AllocatorLog::Allocate(4096)
|
<< AllocatorLog::Allocate(4096)
|
||||||
<< AllocatorLog::Allocate(sizeofString(5)) // hello
|
<< AllocatorLog::Allocate(sizeofString(5)) // hello
|
||||||
<< AllocatorLog::Allocate(sizeofString(5)) // world
|
<< AllocatorLog::Allocate(sizeofString(5)) // world
|
||||||
@ -68,7 +68,7 @@ TEST_CASE("JsonDocument assignment") {
|
|||||||
{
|
{
|
||||||
JsonDocument doc1(4096, &spyingAllocator);
|
JsonDocument doc1(4096, &spyingAllocator);
|
||||||
doc1.set(std::string("The size of this string is 32!!"));
|
doc1.set(std::string("The size of this string is 32!!"));
|
||||||
JsonDocument doc2(8, &spyingAllocator);
|
JsonDocument doc2(128, &spyingAllocator);
|
||||||
|
|
||||||
doc2 = std::move(doc1);
|
doc2 = std::move(doc1);
|
||||||
|
|
||||||
@ -78,8 +78,8 @@ TEST_CASE("JsonDocument assignment") {
|
|||||||
REQUIRE(spyingAllocator.log() ==
|
REQUIRE(spyingAllocator.log() ==
|
||||||
AllocatorLog() << AllocatorLog::Allocate(4096)
|
AllocatorLog() << AllocatorLog::Allocate(4096)
|
||||||
<< AllocatorLog::Allocate(sizeofString(31))
|
<< AllocatorLog::Allocate(sizeofString(31))
|
||||||
<< AllocatorLog::Allocate(8)
|
<< AllocatorLog::Allocate(128)
|
||||||
<< AllocatorLog::Deallocate(8)
|
<< AllocatorLog::Deallocate(128)
|
||||||
<< AllocatorLog::Deallocate(sizeofString(31))
|
<< AllocatorLog::Deallocate(sizeofString(31))
|
||||||
<< AllocatorLog::Deallocate(4096));
|
<< AllocatorLog::Deallocate(4096));
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "Allocators.hpp"
|
#include "Allocators.hpp"
|
||||||
|
|
||||||
using ArduinoJson::detail::addPadding;
|
using ArduinoJson::detail::addPadding;
|
||||||
|
using ArduinoJson::detail::sizeofObject;
|
||||||
using ArduinoJson::detail::sizeofString;
|
using ArduinoJson::detail::sizeofString;
|
||||||
|
|
||||||
TEST_CASE("JsonDocument constructor") {
|
TEST_CASE("JsonDocument constructor") {
|
||||||
@ -66,8 +67,8 @@ TEST_CASE("JsonDocument constructor") {
|
|||||||
JsonDocument doc2(obj, &spyingAllocator);
|
JsonDocument doc2(obj, &spyingAllocator);
|
||||||
|
|
||||||
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
|
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
|
||||||
REQUIRE(spyingAllocator.log() == AllocatorLog() << AllocatorLog::Allocate(
|
REQUIRE(spyingAllocator.log() ==
|
||||||
addPadding(doc1.memoryUsage())));
|
AllocatorLog() << AllocatorLog::Allocate(sizeofObject(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Construct from JsonArray") {
|
SECTION("Construct from JsonArray") {
|
||||||
@ -89,9 +90,9 @@ TEST_CASE("JsonDocument constructor") {
|
|||||||
JsonDocument doc2(doc1.as<JsonVariant>(), &spyingAllocator);
|
JsonDocument doc2(doc1.as<JsonVariant>(), &spyingAllocator);
|
||||||
|
|
||||||
REQUIRE(doc2.as<std::string>() == "hello");
|
REQUIRE(doc2.as<std::string>() == "hello");
|
||||||
REQUIRE(
|
REQUIRE(spyingAllocator.log() ==
|
||||||
spyingAllocator.log() ==
|
AllocatorLog() << AllocatorLog::Allocate(
|
||||||
AllocatorLog() << AllocatorLog::Allocate(addPadding(doc1.memoryUsage()))
|
sizeofString(5)) // TODO: remove
|
||||||
<< AllocatorLog::Allocate(sizeofString(5)));
|
<< AllocatorLog::Allocate(sizeofString(5)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Copyright © 2014-2023, Benoit BLANCHON
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson/Memory/Alignment.hpp>
|
||||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||||
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
#include <ArduinoJson/Memory/VariantPoolImpl.hpp>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Collection/CollectionData.hpp>
|
#include <ArduinoJson/Collection/CollectionData.hpp>
|
||||||
|
#include <ArduinoJson/Memory/Alignment.hpp>
|
||||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantCompare.hpp>
|
#include <ArduinoJson/Variant/VariantCompare.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/Alignment.hpp>
|
|
||||||
#include <ArduinoJson/Memory/Allocator.hpp>
|
#include <ArduinoJson/Memory/Allocator.hpp>
|
||||||
#include <ArduinoJson/Memory/StringPool.hpp>
|
#include <ArduinoJson/Memory/StringPool.hpp>
|
||||||
#include <ArduinoJson/Memory/VariantPool.hpp>
|
#include <ArduinoJson/Memory/VariantPool.hpp>
|
||||||
@ -22,7 +21,7 @@ class ResourceManager {
|
|||||||
ResourceManager(size_t capa,
|
ResourceManager(size_t capa,
|
||||||
Allocator* allocator = DefaultAllocator::instance())
|
Allocator* allocator = DefaultAllocator::instance())
|
||||||
: allocator_(allocator), overflowed_(false) {
|
: allocator_(allocator), overflowed_(false) {
|
||||||
variantPool_.create(addPadding(capa), allocator);
|
variantPool_.create(capa, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ResourceManager() {
|
~ResourceManager() {
|
||||||
@ -48,8 +47,8 @@ class ResourceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void reallocPool(size_t requiredSize) {
|
void reallocPool(size_t requiredSize) {
|
||||||
size_t capa = addPadding(requiredSize);
|
size_t capa = VariantPool::bytesToSlots(requiredSize);
|
||||||
if (capa == capacity())
|
if (capa == variantPool_.capacity())
|
||||||
return;
|
return;
|
||||||
variantPool_.destroy(allocator_);
|
variantPool_.destroy(allocator_);
|
||||||
variantPool_.create(requiredSize, allocator_);
|
variantPool_.create(requiredSize, allocator_);
|
||||||
@ -57,11 +56,11 @@ class ResourceManager {
|
|||||||
|
|
||||||
// Gets the capacity of the memoryPool in bytes
|
// Gets the capacity of the memoryPool in bytes
|
||||||
size_t capacity() const {
|
size_t capacity() const {
|
||||||
return variantPool_.capacity();
|
return VariantPool::slotsToBytes(variantPool_.capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return variantPool_.usage() + stringPool_.size();
|
return VariantPool::slotsToBytes(variantPool_.usage()) + stringPool_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool overflowed() const {
|
bool overflowed() const {
|
||||||
|
@ -14,7 +14,7 @@ class VariantSlot;
|
|||||||
class VariantPool {
|
class VariantPool {
|
||||||
public:
|
public:
|
||||||
~VariantPool() {
|
~VariantPool() {
|
||||||
ARDUINOJSON_ASSERT(data_ == nullptr);
|
ARDUINOJSON_ASSERT(slots_ == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantPool& operator=(VariantPool&& src) {
|
VariantPool& operator=(VariantPool&& src) {
|
||||||
@ -22,8 +22,8 @@ class VariantPool {
|
|||||||
src.capacity_ = 0;
|
src.capacity_ = 0;
|
||||||
usage_ = src.usage_;
|
usage_ = src.usage_;
|
||||||
src.usage_ = 0;
|
src.usage_ = 0;
|
||||||
data_ = src.data_;
|
slots_ = src.slots_;
|
||||||
src.data_ = nullptr;
|
src.slots_ = nullptr;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,12 +36,13 @@ class VariantPool {
|
|||||||
size_t capacity() const;
|
size_t capacity() const;
|
||||||
size_t usage() const;
|
size_t usage() const;
|
||||||
|
|
||||||
static size_t sizeForCapacity(size_t);
|
static size_t bytesToSlots(size_t);
|
||||||
|
static size_t slotsToBytes(size_t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t capacity_ = 0;
|
size_t capacity_ = 0;
|
||||||
size_t usage_ = 0;
|
size_t usage_ = 0;
|
||||||
char* data_ = nullptr;
|
VariantSlot* slots_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
@ -10,40 +10,40 @@
|
|||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
inline void VariantPool::create(size_t cap, Allocator* allocator) {
|
inline void VariantPool::create(size_t cap, Allocator* allocator) {
|
||||||
ARDUINOJSON_ASSERT(data_ == nullptr);
|
ARDUINOJSON_ASSERT(slots_ == nullptr);
|
||||||
if (!cap)
|
if (!cap)
|
||||||
return;
|
return;
|
||||||
data_ = reinterpret_cast<char*>(allocator->allocate(cap));
|
slots_ = reinterpret_cast<VariantSlot*>(allocator->allocate(cap));
|
||||||
if (data_) {
|
if (slots_) {
|
||||||
capacity_ = cap;
|
capacity_ = bytesToSlots(cap);
|
||||||
usage_ = 0;
|
usage_ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void VariantPool::destroy(Allocator* allocator) {
|
inline void VariantPool::destroy(Allocator* allocator) {
|
||||||
if (data_)
|
if (slots_)
|
||||||
allocator->deallocate(data_);
|
allocator->deallocate(slots_);
|
||||||
data_ = nullptr;
|
slots_ = nullptr;
|
||||||
capacity_ = 0;
|
capacity_ = 0;
|
||||||
usage_ = 0;
|
usage_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ptrdiff_t VariantPool::shrinkToFit(Allocator* allocator) {
|
inline ptrdiff_t VariantPool::shrinkToFit(Allocator* allocator) {
|
||||||
auto originalPool = data_;
|
auto originalPool = slots_;
|
||||||
data_ = reinterpret_cast<char*>(allocator->reallocate(data_, usage_));
|
slots_ = reinterpret_cast<VariantSlot*>(
|
||||||
if (data_)
|
allocator->reallocate(slots_, slotsToBytes(usage_)));
|
||||||
|
if (slots_)
|
||||||
capacity_ = usage_;
|
capacity_ = usage_;
|
||||||
return data_ - originalPool;
|
return reinterpret_cast<char*>(slots_) -
|
||||||
|
reinterpret_cast<char*>(originalPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline VariantSlot* VariantPool::allocVariant() {
|
inline VariantSlot* VariantPool::allocVariant() {
|
||||||
if (!data_)
|
if (!slots_)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (usage_ + sizeof(VariantSlot) > capacity_)
|
if (usage_ + 1 > capacity_)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
auto p = data_ + usage_;
|
return new (&slots_[usage_++]) VariantSlot;
|
||||||
usage_ += sizeof(VariantSlot);
|
|
||||||
return new (p) VariantSlot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t VariantPool::usage() const {
|
inline size_t VariantPool::usage() const {
|
||||||
@ -58,4 +58,12 @@ inline void VariantPool::clear() {
|
|||||||
usage_ = 0;
|
usage_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline size_t VariantPool::bytesToSlots(size_t n) {
|
||||||
|
return n / sizeof(VariantSlot);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t VariantPool::slotsToBytes(size_t n) {
|
||||||
|
return n * sizeof(VariantSlot);
|
||||||
|
}
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
Reference in New Issue
Block a user