forked from bblanchon/ArduinoJson
Add abstract Allocator
class
This commit is contained in:
@ -5,3 +5,4 @@ HEAD
|
|||||||
----
|
----
|
||||||
|
|
||||||
* Remove `StaticJsonDocument`
|
* Remove `StaticJsonDocument`
|
||||||
|
* Add abstract `Allocator` class
|
||||||
|
@ -8,37 +8,50 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
class SpyingAllocator {
|
class SpyingAllocator : public Allocator {
|
||||||
public:
|
public:
|
||||||
SpyingAllocator(const SpyingAllocator& src) : _log(src._log) {}
|
virtual ~SpyingAllocator() {}
|
||||||
SpyingAllocator(std::ostream& log) : _log(log) {}
|
|
||||||
SpyingAllocator& operator=(const SpyingAllocator& src) = delete;
|
|
||||||
|
|
||||||
void* allocate(size_t n) {
|
void* allocate(size_t n) override {
|
||||||
_log << "A" << n;
|
_log << "A" << n;
|
||||||
return malloc(n);
|
return malloc(n);
|
||||||
}
|
}
|
||||||
void deallocate(void* p) {
|
|
||||||
|
void deallocate(void* p) override {
|
||||||
_log << "F";
|
_log << "F";
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* reallocate(void* ptr, size_t n) override {
|
||||||
|
_log << "R" << n;
|
||||||
|
return realloc(ptr, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string log() const {
|
||||||
|
return _log.str();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::ostream& _log;
|
std::ostringstream _log;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ControllableAllocator {
|
class ControllableAllocator : public Allocator {
|
||||||
public:
|
public:
|
||||||
ControllableAllocator() : _enabled(true) {}
|
ControllableAllocator() : _enabled(true) {}
|
||||||
|
virtual ~ControllableAllocator() {}
|
||||||
|
|
||||||
void* allocate(size_t n) {
|
void* allocate(size_t n) override {
|
||||||
return _enabled ? malloc(n) : 0;
|
return _enabled ? malloc(n) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocate(void* p) {
|
void deallocate(void* p) override {
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* reallocate(void* ptr, size_t n) override {
|
||||||
|
return realloc(ptr, n);
|
||||||
|
}
|
||||||
|
|
||||||
void disable() {
|
void disable() {
|
||||||
_enabled = false;
|
_enabled = false;
|
||||||
}
|
}
|
||||||
@ -48,47 +61,48 @@ class ControllableAllocator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TEST_CASE("BasicJsonDocument") {
|
TEST_CASE("BasicJsonDocument") {
|
||||||
std::stringstream log;
|
SpyingAllocator spyingAllocator;
|
||||||
|
ControllableAllocator controllableAllocator;
|
||||||
|
|
||||||
SECTION("Construct/Destruct") {
|
SECTION("Construct/Destruct") {
|
||||||
{ BasicJsonDocument<SpyingAllocator> doc(4096, log); }
|
{ BasicJsonDocument doc(4096, &spyingAllocator); }
|
||||||
REQUIRE(log.str() == "A4096F");
|
REQUIRE(spyingAllocator.log() == "A4096F");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Copy construct") {
|
SECTION("Copy construct") {
|
||||||
{
|
{
|
||||||
BasicJsonDocument<SpyingAllocator> doc1(4096, log);
|
BasicJsonDocument 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!!"));
|
||||||
|
|
||||||
BasicJsonDocument<SpyingAllocator> doc2(doc1);
|
BasicJsonDocument doc2(doc1);
|
||||||
|
|
||||||
REQUIRE(doc1.as<std::string>() == "The size of this string is 32!!");
|
REQUIRE(doc1.as<std::string>() == "The size of this string is 32!!");
|
||||||
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
||||||
REQUIRE(doc2.capacity() == 4096);
|
REQUIRE(doc2.capacity() == 4096);
|
||||||
}
|
}
|
||||||
REQUIRE(log.str() == "A4096A4096FF");
|
REQUIRE(spyingAllocator.log() == "A4096A4096FF");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Move construct") {
|
SECTION("Move construct") {
|
||||||
{
|
{
|
||||||
BasicJsonDocument<SpyingAllocator> doc1(4096, log);
|
BasicJsonDocument 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!!"));
|
||||||
|
|
||||||
BasicJsonDocument<SpyingAllocator> doc2(std::move(doc1));
|
BasicJsonDocument doc2(std::move(doc1));
|
||||||
|
|
||||||
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
||||||
REQUIRE(doc1.as<std::string>() == "null");
|
REQUIRE(doc1.as<std::string>() == "null");
|
||||||
REQUIRE(doc1.capacity() == 0);
|
REQUIRE(doc1.capacity() == 0);
|
||||||
REQUIRE(doc2.capacity() == 4096);
|
REQUIRE(doc2.capacity() == 4096);
|
||||||
}
|
}
|
||||||
REQUIRE(log.str() == "A4096F");
|
REQUIRE(spyingAllocator.log() == "A4096F");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Copy assign larger") {
|
SECTION("Copy assign larger") {
|
||||||
{
|
{
|
||||||
BasicJsonDocument<SpyingAllocator> doc1(4096, log);
|
BasicJsonDocument 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!!"));
|
||||||
BasicJsonDocument<SpyingAllocator> doc2(8, log);
|
BasicJsonDocument doc2(8, &spyingAllocator);
|
||||||
|
|
||||||
doc2 = doc1;
|
doc2 = doc1;
|
||||||
|
|
||||||
@ -96,14 +110,14 @@ TEST_CASE("BasicJsonDocument") {
|
|||||||
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
||||||
REQUIRE(doc2.capacity() == 4096);
|
REQUIRE(doc2.capacity() == 4096);
|
||||||
}
|
}
|
||||||
REQUIRE(log.str() == "A4096A8FA4096FF");
|
REQUIRE(spyingAllocator.log() == "A4096A8FA4096FF");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Copy assign smaller") {
|
SECTION("Copy assign smaller") {
|
||||||
{
|
{
|
||||||
BasicJsonDocument<SpyingAllocator> doc1(1024, log);
|
BasicJsonDocument doc1(1024, &spyingAllocator);
|
||||||
doc1.set(std::string("The size of this string is 32!!"));
|
doc1.set(std::string("The size of this string is 32!!"));
|
||||||
BasicJsonDocument<SpyingAllocator> doc2(4096, log);
|
BasicJsonDocument doc2(4096, &spyingAllocator);
|
||||||
|
|
||||||
doc2 = doc1;
|
doc2 = doc1;
|
||||||
|
|
||||||
@ -111,14 +125,14 @@ TEST_CASE("BasicJsonDocument") {
|
|||||||
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
||||||
REQUIRE(doc2.capacity() == 1024);
|
REQUIRE(doc2.capacity() == 1024);
|
||||||
}
|
}
|
||||||
REQUIRE(log.str() == "A1024A4096FA1024FF");
|
REQUIRE(spyingAllocator.log() == "A1024A4096FA1024FF");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Copy assign same size") {
|
SECTION("Copy assign same size") {
|
||||||
{
|
{
|
||||||
BasicJsonDocument<SpyingAllocator> doc1(1024, log);
|
BasicJsonDocument doc1(1024, &spyingAllocator);
|
||||||
doc1.set(std::string("The size of this string is 32!!"));
|
doc1.set(std::string("The size of this string is 32!!"));
|
||||||
BasicJsonDocument<SpyingAllocator> doc2(1024, log);
|
BasicJsonDocument doc2(1024, &spyingAllocator);
|
||||||
|
|
||||||
doc2 = doc1;
|
doc2 = doc1;
|
||||||
|
|
||||||
@ -126,14 +140,14 @@ TEST_CASE("BasicJsonDocument") {
|
|||||||
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
|
||||||
REQUIRE(doc2.capacity() == 1024);
|
REQUIRE(doc2.capacity() == 1024);
|
||||||
}
|
}
|
||||||
REQUIRE(log.str() == "A1024A1024FF");
|
REQUIRE(spyingAllocator.log() == "A1024A1024FF");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Move assign") {
|
SECTION("Move assign") {
|
||||||
{
|
{
|
||||||
BasicJsonDocument<SpyingAllocator> doc1(4096, log);
|
BasicJsonDocument 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!!"));
|
||||||
BasicJsonDocument<SpyingAllocator> doc2(8, log);
|
BasicJsonDocument doc2(8, &spyingAllocator);
|
||||||
|
|
||||||
doc2 = std::move(doc1);
|
doc2 = std::move(doc1);
|
||||||
|
|
||||||
@ -142,11 +156,11 @@ TEST_CASE("BasicJsonDocument") {
|
|||||||
REQUIRE(doc1.capacity() == 0);
|
REQUIRE(doc1.capacity() == 0);
|
||||||
REQUIRE(doc2.capacity() == 4096);
|
REQUIRE(doc2.capacity() == 4096);
|
||||||
}
|
}
|
||||||
REQUIRE(log.str() == "A4096A8FF");
|
REQUIRE(spyingAllocator.log() == "A4096A8FF");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("garbageCollect()") {
|
SECTION("garbageCollect()") {
|
||||||
BasicJsonDocument<ControllableAllocator> doc(4096);
|
BasicJsonDocument doc(4096, &controllableAllocator);
|
||||||
|
|
||||||
SECTION("when allocation succeeds") {
|
SECTION("when allocation succeeds") {
|
||||||
deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}");
|
deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}");
|
||||||
@ -167,7 +181,7 @@ TEST_CASE("BasicJsonDocument") {
|
|||||||
REQUIRE(doc.capacity() == 4096);
|
REQUIRE(doc.capacity() == 4096);
|
||||||
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2) + 16);
|
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2) + 16);
|
||||||
doc.remove("blanket");
|
doc.remove("blanket");
|
||||||
doc.allocator().disable();
|
controllableAllocator.disable();
|
||||||
|
|
||||||
bool result = doc.garbageCollect();
|
bool result = doc.garbageCollect();
|
||||||
|
|
||||||
|
@ -8,24 +8,25 @@
|
|||||||
#include <stdlib.h> // malloc, free
|
#include <stdlib.h> // malloc, free
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class ArmoredAllocator {
|
class ArmoredAllocator : public Allocator {
|
||||||
public:
|
public:
|
||||||
ArmoredAllocator() : _ptr(0), _size(0) {}
|
ArmoredAllocator() : _ptr(0), _size(0) {}
|
||||||
|
virtual ~ArmoredAllocator() {}
|
||||||
|
|
||||||
void* allocate(size_t size) {
|
void* allocate(size_t size) override {
|
||||||
_ptr = malloc(size);
|
_ptr = malloc(size);
|
||||||
_size = size;
|
_size = size;
|
||||||
return _ptr;
|
return _ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocate(void* ptr) {
|
void deallocate(void* ptr) override {
|
||||||
REQUIRE(ptr == _ptr);
|
REQUIRE(ptr == _ptr);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
_ptr = 0;
|
_ptr = 0;
|
||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* reallocate(void* ptr, size_t new_size) {
|
void* reallocate(void* ptr, size_t new_size) override {
|
||||||
REQUIRE(ptr == _ptr);
|
REQUIRE(ptr == _ptr);
|
||||||
// don't call realloc, instead alloc a new buffer and erase the old one
|
// don't call realloc, instead alloc a new buffer and erase the old one
|
||||||
// this way we make sure we support relocation
|
// this way we make sure we support relocation
|
||||||
@ -42,9 +43,7 @@ class ArmoredAllocator {
|
|||||||
size_t _size;
|
size_t _size;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef BasicJsonDocument<ArmoredAllocator> ShrinkToFitTestDocument;
|
void testShrinkToFit(DynamicJsonDocument& doc, std::string expected_json,
|
||||||
|
|
||||||
void testShrinkToFit(ShrinkToFitTestDocument& doc, std::string expected_json,
|
|
||||||
size_t expected_size) {
|
size_t expected_size) {
|
||||||
// test twice: shrinkToFit() should be idempotent
|
// test twice: shrinkToFit() should be idempotent
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
@ -60,7 +59,8 @@ void testShrinkToFit(ShrinkToFitTestDocument& doc, std::string expected_json,
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("BasicJsonDocument::shrinkToFit()") {
|
TEST_CASE("BasicJsonDocument::shrinkToFit()") {
|
||||||
ShrinkToFitTestDocument doc(4096);
|
ArmoredAllocator armoredAllocator;
|
||||||
|
DynamicJsonDocument doc(4096, &armoredAllocator);
|
||||||
|
|
||||||
SECTION("null") {
|
SECTION("null") {
|
||||||
testShrinkToFit(doc, "null", 0);
|
testShrinkToFit(doc, "null", 0);
|
||||||
|
@ -5,58 +5,60 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Document/JsonDocument.hpp>
|
#include <ArduinoJson/Document/JsonDocument.hpp>
|
||||||
|
#include <ArduinoJson/Memory/Allocator.hpp>
|
||||||
|
|
||||||
|
#include <stdlib.h> // malloc, free
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
// Helper to implement the "base-from-member" idiom
|
// Helper to implement the "base-from-member" idiom
|
||||||
// (we need to store the allocator before constructing JsonDocument)
|
// (we need to store the allocator before constructing JsonDocument)
|
||||||
template <typename TAllocator>
|
|
||||||
class AllocatorOwner {
|
class AllocatorOwner {
|
||||||
public:
|
public:
|
||||||
AllocatorOwner() {}
|
AllocatorOwner(Allocator* allocator) : _allocator(allocator) {}
|
||||||
AllocatorOwner(TAllocator a) : _allocator(a) {}
|
|
||||||
|
|
||||||
void* allocate(size_t size) {
|
void* allocate(size_t size) {
|
||||||
return _allocator.allocate(size);
|
return _allocator->allocate(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocate(void* ptr) {
|
void deallocate(void* ptr) {
|
||||||
if (ptr)
|
if (ptr)
|
||||||
_allocator.deallocate(ptr);
|
_allocator->deallocate(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* reallocate(void* ptr, size_t new_size) {
|
void* reallocate(void* ptr, size_t new_size) {
|
||||||
return _allocator.reallocate(ptr, new_size);
|
return _allocator->reallocate(ptr, new_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
TAllocator& allocator() {
|
Allocator* allocator() {
|
||||||
return _allocator;
|
return _allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TAllocator _allocator;
|
Allocator* _allocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A JsonDocument that uses the provided allocator to allocate its memory pool.
|
// A JsonDocument that uses the provided allocator to allocate its memory pool.
|
||||||
// https://arduinojson.org/v6/api/basicjsondocument/
|
// https://arduinojson.org/v6/api/basicjsondocument/
|
||||||
template <typename TAllocator>
|
class BasicJsonDocument : AllocatorOwner, public JsonDocument {
|
||||||
class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
|
||||||
public:
|
public:
|
||||||
explicit BasicJsonDocument(size_t capa, TAllocator alloc = TAllocator())
|
explicit BasicJsonDocument(
|
||||||
: AllocatorOwner<TAllocator>(alloc), JsonDocument(allocPool(capa)) {}
|
size_t capa, Allocator* alloc = detail::DefaultAllocator::instance())
|
||||||
|
: AllocatorOwner(alloc), JsonDocument(allocPool(capa)) {}
|
||||||
|
|
||||||
// Copy-constructor
|
// Copy-constructor
|
||||||
BasicJsonDocument(const BasicJsonDocument& src)
|
BasicJsonDocument(const BasicJsonDocument& src)
|
||||||
: AllocatorOwner<TAllocator>(src), JsonDocument() {
|
: AllocatorOwner(src), JsonDocument() {
|
||||||
copyAssignFrom(src);
|
copyAssignFrom(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move-constructor
|
// Move-constructor
|
||||||
BasicJsonDocument(BasicJsonDocument&& src) : AllocatorOwner<TAllocator>(src) {
|
BasicJsonDocument(BasicJsonDocument&& src) : AllocatorOwner(src) {
|
||||||
moveAssignFrom(src);
|
moveAssignFrom(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicJsonDocument(const JsonDocument& src) {
|
BasicJsonDocument(const JsonDocument& src)
|
||||||
|
: AllocatorOwner(detail::DefaultAllocator::instance()) {
|
||||||
copyAssignFrom(src);
|
copyAssignFrom(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,13 +72,14 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
|||||||
detail::is_same<T, JsonArrayConst>::value ||
|
detail::is_same<T, JsonArrayConst>::value ||
|
||||||
detail::is_same<T, JsonObject>::value ||
|
detail::is_same<T, JsonObject>::value ||
|
||||||
detail::is_same<T, JsonObjectConst>::value>::type* = 0)
|
detail::is_same<T, JsonObjectConst>::value>::type* = 0)
|
||||||
: JsonDocument(allocPool(src.memoryUsage())) {
|
: BasicJsonDocument(src.memoryUsage()) {
|
||||||
set(src);
|
set(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
// disambiguate
|
// disambiguate
|
||||||
BasicJsonDocument(JsonVariant src)
|
BasicJsonDocument(JsonVariant src)
|
||||||
: JsonDocument(allocPool(src.memoryUsage())) {
|
: AllocatorOwner(detail::DefaultAllocator::instance()),
|
||||||
|
JsonDocument(allocPool(src.memoryUsage())) {
|
||||||
set(src);
|
set(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +135,7 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
using AllocatorOwner<TAllocator>::allocator;
|
using AllocatorOwner::allocator;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::MemoryPool allocPool(size_t requiredSize) {
|
detail::MemoryPool allocPool(size_t requiredSize) {
|
||||||
|
@ -6,27 +6,10 @@
|
|||||||
|
|
||||||
#include <ArduinoJson/Document/BasicJsonDocument.hpp>
|
#include <ArduinoJson/Document/BasicJsonDocument.hpp>
|
||||||
|
|
||||||
#include <stdlib.h> // malloc, free
|
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
// The allocator of DynamicJsonDocument.
|
|
||||||
struct DefaultAllocator {
|
|
||||||
void* allocate(size_t size) {
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocate(void* ptr) {
|
|
||||||
free(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* reallocate(void* ptr, size_t new_size) {
|
|
||||||
return realloc(ptr, new_size);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// A JsonDocument with a memory pool in the heap.
|
// A JsonDocument with a memory pool in the heap.
|
||||||
// https://arduinojson.org/v6/api/dynamicjsondocument/
|
// https://arduinojson.org/v6/api/dynamicjsondocument/
|
||||||
typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument;
|
typedef BasicJsonDocument DynamicJsonDocument;
|
||||||
|
|
||||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
49
src/ArduinoJson/Memory/Allocator.hpp
Normal file
49
src/ArduinoJson/Memory/Allocator.hpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Namespace.hpp>
|
||||||
|
|
||||||
|
#include <stdlib.h> // malloc, free
|
||||||
|
|
||||||
|
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
||||||
|
|
||||||
|
class Allocator {
|
||||||
|
public:
|
||||||
|
virtual void* allocate(size_t size) = 0;
|
||||||
|
virtual void deallocate(void* ptr) = 0;
|
||||||
|
virtual void* reallocate(void* ptr, size_t new_size) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~Allocator() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
class DefaultAllocator : public Allocator {
|
||||||
|
public:
|
||||||
|
void* allocate(size_t size) override {
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(void* ptr) override {
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* reallocate(void* ptr, size_t new_size) override {
|
||||||
|
return realloc(ptr, new_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Allocator* instance() {
|
||||||
|
static DefaultAllocator allocator;
|
||||||
|
return &allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DefaultAllocator() = default;
|
||||||
|
~DefaultAllocator() = default;
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
Reference in New Issue
Block a user