forked from bblanchon/ArduinoJson
DynamicJsonDocument reallocates memory pool is it's too small
This commit is contained in:
@ -13,36 +13,48 @@ namespace ARDUINOJSON_NAMESPACE {
|
|||||||
class DynamicJsonDocument : public JsonDocument {
|
class DynamicJsonDocument : public JsonDocument {
|
||||||
public:
|
public:
|
||||||
DynamicJsonDocument(size_t capa = ARDUINOJSON_DEFAULT_POOL_SIZE)
|
DynamicJsonDocument(size_t capa = ARDUINOJSON_DEFAULT_POOL_SIZE)
|
||||||
: JsonDocument(alloc(capa), addPadding(capa)) {}
|
: JsonDocument(allocPool(addPadding(capa))) {}
|
||||||
|
|
||||||
DynamicJsonDocument(const DynamicJsonDocument& src)
|
DynamicJsonDocument(const DynamicJsonDocument& src)
|
||||||
: JsonDocument(alloc(src.memoryUsage()), addPadding(src.memoryUsage())) {
|
: JsonDocument(allocPool(src.capacity())) {
|
||||||
copy(src);
|
copy(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument(const JsonDocument& src)
|
DynamicJsonDocument(const JsonDocument& src)
|
||||||
: JsonDocument(alloc(src.memoryUsage()), addPadding(src.memoryUsage())) {
|
: JsonDocument(allocPool(src.capacity())) {
|
||||||
copy(src);
|
copy(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
~DynamicJsonDocument() {
|
~DynamicJsonDocument() {
|
||||||
free(memoryPool().buffer());
|
freePool();
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument& operator=(const DynamicJsonDocument& src) {
|
DynamicJsonDocument& operator=(const DynamicJsonDocument& src) {
|
||||||
|
reallocPoolIfTooSmall(src.memoryUsage());
|
||||||
copy(src);
|
copy(src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
DynamicJsonDocument& operator=(const JsonDocument& src) {
|
DynamicJsonDocument& operator=(const JsonDocument& src) {
|
||||||
|
reallocPoolIfTooSmall(src.memoryUsage());
|
||||||
copy(src);
|
copy(src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static char* alloc(size_t capa) {
|
MemoryPool allocPool(size_t capa) {
|
||||||
return reinterpret_cast<char*>(malloc(addPadding(capa)));
|
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());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,6 +63,9 @@ class JsonDocument : public Visitable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
JsonDocument(MemoryPool pool)
|
||||||
|
: nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT), _pool(pool) {}
|
||||||
|
|
||||||
JsonDocument(char* buf, size_t capa)
|
JsonDocument(char* buf, size_t capa)
|
||||||
: nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT), _pool(buf, capa) {}
|
: nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT), _pool(buf, capa) {}
|
||||||
|
|
||||||
@ -71,6 +74,10 @@ class JsonDocument : public Visitable {
|
|||||||
to<VariantRef>().set(src.as<VariantRef>());
|
to<VariantRef>().set(src.as<VariantRef>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void replacePool(MemoryPool pool) {
|
||||||
|
_pool = pool;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VariantRef getVariant() {
|
VariantRef getVariant() {
|
||||||
return VariantRef(&_pool, &_data);
|
return VariantRef(&_pool, &_data);
|
||||||
|
@ -51,60 +51,6 @@ TEST_CASE("DynamicJsonDocument") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Copy constructor") {
|
|
||||||
deserializeJson(doc, "{\"hello\":\"world\"}");
|
|
||||||
doc.nestingLimit = 42;
|
|
||||||
|
|
||||||
DynamicJsonDocument doc2 = doc;
|
|
||||||
|
|
||||||
std::string json;
|
|
||||||
serializeJson(doc2, json);
|
|
||||||
REQUIRE(json == "{\"hello\":\"world\"}");
|
|
||||||
REQUIRE(doc2.nestingLimit == 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Copy assignment") {
|
|
||||||
DynamicJsonDocument doc2;
|
|
||||||
deserializeJson(doc2, "{\"hello\":\"world\"}");
|
|
||||||
doc2.nestingLimit = 42;
|
|
||||||
|
|
||||||
doc = doc2;
|
|
||||||
|
|
||||||
std::string json;
|
|
||||||
serializeJson(doc, json);
|
|
||||||
REQUIRE(json == "{\"hello\":\"world\"}");
|
|
||||||
REQUIRE(doc.nestingLimit == 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Construct from StaticJsonDocument") {
|
|
||||||
StaticJsonDocument<200> sdoc;
|
|
||||||
deserializeJson(sdoc, "{\"hello\":\"world\"}");
|
|
||||||
sdoc.nestingLimit = 42;
|
|
||||||
|
|
||||||
DynamicJsonDocument ddoc = sdoc;
|
|
||||||
|
|
||||||
std::string json;
|
|
||||||
serializeJson(ddoc, json);
|
|
||||||
REQUIRE(json == "{\"hello\":\"world\"}");
|
|
||||||
REQUIRE(ddoc.nestingLimit == 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Assign from StaticJsonDocument") {
|
|
||||||
DynamicJsonDocument ddoc;
|
|
||||||
ddoc.to<JsonVariant>().set(666);
|
|
||||||
|
|
||||||
StaticJsonDocument<200> sdoc;
|
|
||||||
deserializeJson(sdoc, "{\"hello\":\"world\"}");
|
|
||||||
sdoc.nestingLimit = 42;
|
|
||||||
|
|
||||||
ddoc = sdoc;
|
|
||||||
|
|
||||||
std::string json;
|
|
||||||
serializeJson(ddoc, json);
|
|
||||||
REQUIRE(json == "{\"hello\":\"world\"}");
|
|
||||||
REQUIRE(ddoc.nestingLimit == 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("memoryUsage()") {
|
SECTION("memoryUsage()") {
|
||||||
SECTION("Increases after adding value to array") {
|
SECTION("Increases after adding value to array") {
|
||||||
JsonArray arr = doc.to<JsonArray>();
|
JsonArray arr = doc.to<JsonArray>();
|
||||||
@ -127,3 +73,81 @@ TEST_CASE("DynamicJsonDocument") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DynamicJsonDocument copies") {
|
||||||
|
SECTION("Copy constructor") {
|
||||||
|
DynamicJsonDocument doc1(1234);
|
||||||
|
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||||
|
doc1.nestingLimit = 42;
|
||||||
|
|
||||||
|
DynamicJsonDocument doc2 = doc1;
|
||||||
|
|
||||||
|
std::string json;
|
||||||
|
serializeJson(doc2, json);
|
||||||
|
REQUIRE(json == "{\"hello\":\"world\"}");
|
||||||
|
|
||||||
|
REQUIRE(doc2.nestingLimit == 42);
|
||||||
|
REQUIRE(doc2.capacity() == doc1.capacity());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Copy assignment preserves the buffer when capacity is sufficient") {
|
||||||
|
DynamicJsonDocument doc1(1234);
|
||||||
|
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||||
|
doc1.nestingLimit = 42;
|
||||||
|
|
||||||
|
DynamicJsonDocument doc2(doc1.capacity());
|
||||||
|
doc2 = doc1;
|
||||||
|
|
||||||
|
std::string json;
|
||||||
|
serializeJson(doc2, json);
|
||||||
|
REQUIRE(json == "{\"hello\":\"world\"}");
|
||||||
|
REQUIRE(doc2.nestingLimit == 42);
|
||||||
|
REQUIRE(doc2.capacity() == doc1.capacity());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Copy assignment realloc the buffer when capacity is insufficient") {
|
||||||
|
DynamicJsonDocument doc1(1234);
|
||||||
|
deserializeJson(doc1, "{\"hello\":\"world\"}");
|
||||||
|
doc1.nestingLimit = 42;
|
||||||
|
DynamicJsonDocument doc2(8);
|
||||||
|
|
||||||
|
REQUIRE(doc2.capacity() < doc1.memoryUsage());
|
||||||
|
doc2 = doc1;
|
||||||
|
REQUIRE(doc2.capacity() >= doc1.memoryUsage());
|
||||||
|
|
||||||
|
std::string json;
|
||||||
|
serializeJson(doc2, json);
|
||||||
|
REQUIRE(json == "{\"hello\":\"world\"}");
|
||||||
|
REQUIRE(doc2.nestingLimit == 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Construct from StaticJsonDocument") {
|
||||||
|
StaticJsonDocument<200> sdoc;
|
||||||
|
deserializeJson(sdoc, "{\"hello\":\"world\"}");
|
||||||
|
sdoc.nestingLimit = 42;
|
||||||
|
|
||||||
|
DynamicJsonDocument ddoc = sdoc;
|
||||||
|
|
||||||
|
std::string json;
|
||||||
|
serializeJson(ddoc, json);
|
||||||
|
REQUIRE(json == "{\"hello\":\"world\"}");
|
||||||
|
REQUIRE(ddoc.nestingLimit == 42);
|
||||||
|
REQUIRE(ddoc.capacity() == sdoc.capacity());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Assign from StaticJsonDocument") {
|
||||||
|
DynamicJsonDocument ddoc;
|
||||||
|
ddoc.to<JsonVariant>().set(666);
|
||||||
|
|
||||||
|
StaticJsonDocument<200> sdoc;
|
||||||
|
deserializeJson(sdoc, "{\"hello\":\"world\"}");
|
||||||
|
sdoc.nestingLimit = 42;
|
||||||
|
|
||||||
|
ddoc = sdoc;
|
||||||
|
|
||||||
|
std::string json;
|
||||||
|
serializeJson(ddoc, json);
|
||||||
|
REQUIRE(json == "{\"hello\":\"world\"}");
|
||||||
|
REQUIRE(ddoc.nestingLimit == 42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user