forked from bblanchon/ArduinoJson
Added BasicJsonDocument
to support custom allocator (issue #876)
This commit is contained in:
@ -8,6 +8,7 @@ HEAD
|
|||||||
* Added overflow handling in `JsonVariant::as<T>()` and `JsonVariant::is<T>()`.
|
* Added overflow handling in `JsonVariant::as<T>()` and `JsonVariant::is<T>()`.
|
||||||
- `as<T>()` returns `0` if the integer `T` overflows
|
- `as<T>()` returns `0` if the integer `T` overflows
|
||||||
- `is<T>()` returns `false` if the integer `T` overflows
|
- `is<T>()` returns `false` if the integer `T` overflows
|
||||||
|
* Added `BasicJsonDocument` to support custom allocator (issue #876)
|
||||||
|
|
||||||
v6.9.1 (2019-03-01)
|
v6.9.1 (2019-03-01)
|
||||||
------
|
------
|
||||||
|
@ -50,6 +50,7 @@ typedef ARDUINOJSON_NAMESPACE::String JsonString;
|
|||||||
typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
|
typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
|
||||||
typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
|
typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
|
||||||
typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
|
typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
|
||||||
|
using ARDUINOJSON_NAMESPACE::BasicJsonDocument;
|
||||||
using ARDUINOJSON_NAMESPACE::copyArray;
|
using ARDUINOJSON_NAMESPACE::copyArray;
|
||||||
using ARDUINOJSON_NAMESPACE::DeserializationError;
|
using ARDUINOJSON_NAMESPACE::DeserializationError;
|
||||||
using ARDUINOJSON_NAMESPACE::deserializeJson;
|
using ARDUINOJSON_NAMESPACE::deserializeJson;
|
||||||
|
89
src/ArduinoJson/Document/BasicJsonDocument.hpp
Normal file
89
src/ArduinoJson/Document/BasicJsonDocument.hpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2019
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonDocument.hpp"
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
template <typename TAllocator>
|
||||||
|
class AllocatorOwner {
|
||||||
|
protected:
|
||||||
|
AllocatorOwner() {}
|
||||||
|
AllocatorOwner(const AllocatorOwner& src) : _allocator(src._allocator) {}
|
||||||
|
AllocatorOwner(TAllocator allocator) : _allocator(allocator) {}
|
||||||
|
|
||||||
|
void* allocate(size_t n) {
|
||||||
|
return _allocator.allocate(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(void* p) {
|
||||||
|
_allocator.deallocate(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TAllocator _allocator;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TAllocator>
|
||||||
|
class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
||||||
|
public:
|
||||||
|
explicit BasicJsonDocument(size_t capa, TAllocator allocator = TAllocator())
|
||||||
|
: AllocatorOwner<TAllocator>(allocator), JsonDocument(allocPool(capa)) {}
|
||||||
|
|
||||||
|
BasicJsonDocument(const BasicJsonDocument& src)
|
||||||
|
: AllocatorOwner<TAllocator>(src),
|
||||||
|
JsonDocument(allocPool(src.memoryUsage())) {
|
||||||
|
set(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
BasicJsonDocument(const T& src,
|
||||||
|
typename enable_if<IsVisitable<T>::value>::type* = 0)
|
||||||
|
: JsonDocument(allocPool(src.memoryUsage())) {
|
||||||
|
set(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
// disambiguate
|
||||||
|
BasicJsonDocument(VariantRef src)
|
||||||
|
: JsonDocument(allocPool(src.memoryUsage())) {
|
||||||
|
set(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
~BasicJsonDocument() {
|
||||||
|
freePool();
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicJsonDocument& operator=(const BasicJsonDocument& src) {
|
||||||
|
reallocPoolIfTooSmall(src.memoryUsage());
|
||||||
|
set(src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
BasicJsonDocument& operator=(const T& src) {
|
||||||
|
reallocPoolIfTooSmall(src.memoryUsage());
|
||||||
|
set(src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MemoryPool allocPool(size_t requiredSize) {
|
||||||
|
size_t capa = addPadding(requiredSize);
|
||||||
|
return MemoryPool(reinterpret_cast<char*>(this->allocate(capa)), capa);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reallocPoolIfTooSmall(size_t requiredSize) {
|
||||||
|
if (requiredSize <= capacity()) return;
|
||||||
|
freePool();
|
||||||
|
replacePool(allocPool(addPadding(requiredSize)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void freePool() {
|
||||||
|
this->deallocate(memoryPool().buffer());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -4,66 +4,22 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "JsonDocument.hpp"
|
#include "BasicJsonDocument.hpp"
|
||||||
|
|
||||||
#include <stdlib.h> // malloc, free
|
#include <stdlib.h> // malloc, free
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
class DynamicJsonDocument : public JsonDocument {
|
struct DefaultAllocator {
|
||||||
public:
|
void* allocate(size_t n) {
|
||||||
explicit DynamicJsonDocument(size_t capa) : JsonDocument(allocPool(capa)) {}
|
return malloc(n);
|
||||||
|
|
||||||
DynamicJsonDocument(const DynamicJsonDocument& src)
|
|
||||||
: JsonDocument(allocPool(src.memoryUsage())) {
|
|
||||||
set(src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
void deallocate(void* p) {
|
||||||
DynamicJsonDocument(const T& src,
|
free(p);
|
||||||
typename enable_if<IsVisitable<T>::value>::type* = 0)
|
|
||||||
: JsonDocument(allocPool(src.memoryUsage())) {
|
|
||||||
set(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
// disambiguate
|
|
||||||
DynamicJsonDocument(VariantRef src)
|
|
||||||
: JsonDocument(allocPool(src.memoryUsage())) {
|
|
||||||
set(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
~DynamicJsonDocument() {
|
|
||||||
freePool();
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument& operator=(const DynamicJsonDocument& src) {
|
|
||||||
reallocPoolIfTooSmall(src.memoryUsage());
|
|
||||||
set(src);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
DynamicJsonDocument& operator=(const T& src) {
|
|
||||||
reallocPoolIfTooSmall(src.memoryUsage());
|
|
||||||
set(src);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
MemoryPool allocPool(size_t requiredSize) {
|
|
||||||
size_t capa = addPadding(requiredSize);
|
|
||||||
return MemoryPool(reinterpret_cast<char*>(malloc(capa)), capa);
|
|
||||||
}
|
|
||||||
|
|
||||||
void reallocPoolIfTooSmall(size_t requiredSize) {
|
|
||||||
if (requiredSize <= capacity()) return;
|
|
||||||
freePool();
|
|
||||||
replacePool(allocPool(addPadding(requiredSize)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void freePool() {
|
|
||||||
free(memoryPool().buffer());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument;
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
49
test/JsonDocument/BasicJsonDocument.cpp
Normal file
49
test/JsonDocument/BasicJsonDocument.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2019
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <stdlib.h> // malloc, free
|
||||||
|
#include <catch.hpp>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using ARDUINOJSON_NAMESPACE::addPadding;
|
||||||
|
|
||||||
|
class SpyingAllocator {
|
||||||
|
public:
|
||||||
|
SpyingAllocator(std::ostream& log) : _log(log) {}
|
||||||
|
|
||||||
|
void* allocate(size_t n) {
|
||||||
|
_log << "A" << n;
|
||||||
|
return malloc(n);
|
||||||
|
}
|
||||||
|
void deallocate(void* p) {
|
||||||
|
_log << "F";
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SpyingAllocator& operator=(const SpyingAllocator& src);
|
||||||
|
|
||||||
|
std::ostream& _log;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef BasicJsonDocument<SpyingAllocator> MyJsonDocument;
|
||||||
|
|
||||||
|
TEST_CASE("BasicJsonDocument") {
|
||||||
|
std::stringstream log;
|
||||||
|
|
||||||
|
SECTION("Construct/Destruct") {
|
||||||
|
{ MyJsonDocument doc(4096, log); }
|
||||||
|
REQUIRE(log.str() == "A4096F");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Copy construct") {
|
||||||
|
{
|
||||||
|
MyJsonDocument doc1(4096, log);
|
||||||
|
doc1.set(std::string("The size of this string is 32!!"));
|
||||||
|
MyJsonDocument doc2(doc1);
|
||||||
|
}
|
||||||
|
REQUIRE(log.str() == "A4096A32FF");
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
add_executable(JsonDocumentTests
|
add_executable(JsonDocumentTests
|
||||||
add.cpp
|
add.cpp
|
||||||
|
BasicJsonDocument.cpp
|
||||||
createNested.cpp
|
createNested.cpp
|
||||||
DynamicJsonDocument.cpp
|
DynamicJsonDocument.cpp
|
||||||
isNull.cpp
|
isNull.cpp
|
||||||
|
Reference in New Issue
Block a user