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 {
|
||||
public:
|
||||
DynamicJsonDocument(size_t capa = ARDUINOJSON_DEFAULT_POOL_SIZE)
|
||||
: JsonDocument(alloc(capa), addPadding(capa)) {}
|
||||
: JsonDocument(allocPool(addPadding(capa))) {}
|
||||
|
||||
DynamicJsonDocument(const DynamicJsonDocument& src)
|
||||
: JsonDocument(alloc(src.memoryUsage()), addPadding(src.memoryUsage())) {
|
||||
: JsonDocument(allocPool(src.capacity())) {
|
||||
copy(src);
|
||||
}
|
||||
|
||||
DynamicJsonDocument(const JsonDocument& src)
|
||||
: JsonDocument(alloc(src.memoryUsage()), addPadding(src.memoryUsage())) {
|
||||
: JsonDocument(allocPool(src.capacity())) {
|
||||
copy(src);
|
||||
}
|
||||
|
||||
~DynamicJsonDocument() {
|
||||
free(memoryPool().buffer());
|
||||
freePool();
|
||||
}
|
||||
|
||||
DynamicJsonDocument& operator=(const DynamicJsonDocument& src) {
|
||||
reallocPoolIfTooSmall(src.memoryUsage());
|
||||
copy(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DynamicJsonDocument& operator=(const JsonDocument& src) {
|
||||
reallocPoolIfTooSmall(src.memoryUsage());
|
||||
copy(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
static char* alloc(size_t capa) {
|
||||
return reinterpret_cast<char*>(malloc(addPadding(capa)));
|
||||
MemoryPool allocPool(size_t 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:
|
||||
JsonDocument(MemoryPool pool)
|
||||
: nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT), _pool(pool) {}
|
||||
|
||||
JsonDocument(char* buf, size_t capa)
|
||||
: nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT), _pool(buf, capa) {}
|
||||
|
||||
@ -71,6 +74,10 @@ class JsonDocument : public Visitable {
|
||||
to<VariantRef>().set(src.as<VariantRef>());
|
||||
}
|
||||
|
||||
void replacePool(MemoryPool pool) {
|
||||
_pool = pool;
|
||||
}
|
||||
|
||||
private:
|
||||
VariantRef getVariant() {
|
||||
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("Increases after adding value to array") {
|
||||
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