8000 DynamicJsonDocument reallocates memory pool is it's too small · java64/ArduinoJson@e20c47c · GitHub
[go: up one dir, main page]

Skip to content

Commit e20c47c

Browse files
committed
DynamicJsonDocument reallocates memory pool is it's too small
1 parent b77b203 commit e20c47c

File tree

3 files changed

+81
-38
lines changed

3 files changed

+81
-38
lines changed

src/ArduinoJson/Document/DynamicJsonDocument.hpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,48 @@ namespace ARDUINOJSON_NAMESPACE {
1313
class DynamicJsonDocument : public JsonDocument {
1414
public:
1515
DynamicJsonDocument(size_t capa = ARDUINOJSON_DEFAULT_POOL_SIZE)
16-
: JsonDocument(alloc(capa), addPadding(capa)) {}
16+
: JsonDocument(allocPool(addPadding(capa))) {}
1717

1818
DynamicJsonDocument(const DynamicJsonDocument& src)
19-
: JsonDocument(alloc(src.memoryUsage()), addPadding(src.memoryUsage())) {
19+
: JsonDocument(allocPool(src.capacity())) {
2020
copy(src);
2121
}
2222

2323
DynamicJsonDocument(const JsonDocument& src)
24-
: JsonDocument(alloc(src.memoryUsage()), addPadding(src.memoryUsage())) {
24+
: JsonDocument(allocPool(src.capacity())) {
2525
copy(src);
2626
}
2727

2828
~DynamicJsonDocument() {
29-
free(memoryPool().buffer());
29+
freePool();
3030
}
3131

3232
DynamicJsonDocument& operator=(const DynamicJsonDocument& src) {
33+
reallocPoolIfTooSmall(src.memoryUsage());
3334
copy(src);
3435
return *this;
3536
}
3637

3738
template <typename T>
3839
DynamicJsonDocument& operator=(const JsonDocument& src) {
40+
reallocPoolIfTooSmall(src.memoryUsage());
3941
copy(src);
4042
return *this;
4143
}
4244

4345
private:
44-
static char* alloc(size_t capa) {
45-
return reinterpret_cast<char*>(malloc(addPadding(capa)));
46+
MemoryPool allocPool(size_t capa) {
47+
return MemoryPool(reinterpret_cast<char*>(malloc(capa)), capa);
48+
}
49+
50+
void reallocPoolIfTooSmall(size_t requiredSize) {
51+
if (requiredSize <= capacity()) return;
52+
freePool();
53+
replacePool(allocPool(addPadding(requiredSize)));
54+
}
55+
56+
void freePool() {
57+
free(memoryPool().buffer());
4658
}
4759
};
4860

src/ArduinoJson/Document/JsonDocument.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ class JsonDocument : public Visitable {
6363
}
6464

6565
protected:
66+
JsonDocument(MemoryPool pool)
67+
: nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT), _pool(pool) {}
68+
6669
JsonDocument(char* buf, size_t capa)
6770
: nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT), _pool(buf, capa) {}
6871

@@ -71,6 +74,10 @@ class JsonDocument : public Visitable {
7174
to<VariantRef>().set(src.as<VariantRef>());
7275
}
7376

77+
void replacePool(MemoryPool pool) {
78+
_pool = pool;
79+
}
80+
7481
private:
7582
VariantRef getVariant() {
7683
return VariantRef(&_pool, &_data);

test/JsonDocument/DynamicJsonDocument.cpp

Lines changed: 56 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -51,29 +51,74 @@ TEST_CASE("DynamicJsonDocument") {
5151
}
5252
}
5353

54+
SECTION("memoryUsage()") {
55+
SECTION("Increases after adding value to array") {
56+
JsonArray arr = doc.to<JsonArray>();
57+
58+
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0));
59+
arr.add(42);
60+
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(1));
61+
arr.add(43);
62+
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(2));
63+
}
64+
65+
SECTION("Increases after adding value to object") {
66+
JsonObject obj = doc.to<JsonObject>();
67+
68+
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
69+
obj["a"] = 1;
70+
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1));
71+
obj["b"] = 2;
72+
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2));
73+
}
74+
}
75+
}
76+
77+
TEST_CASE("DynamicJsonDocument copies") {
5478
SECTION("Copy constructor") {
55-
deserializeJson(doc, "{\"hello\":\"world\"}");
56-
doc.nestingLimit = 42;
79+
DynamicJsonDocument doc1(1234);
80+
deserializeJson(doc1, "{\"hello\":\"world\"}");
81+
doc1.nestingLimit = 42;
5782

58-
DynamicJsonDocument doc2 = doc;
83+
DynamicJsonDocument doc2 = doc1;
5984

6085
std::string json;
6186
serializeJson(doc2, json);
6287
REQUIRE(json == "{\"hello\":\"world\"}");
88+
6389
REQUIRE(doc2.nestingLimit == 42);
90+
REQUIRE(doc2.capacity() == doc1.capacity());
6491
}
6592

66-
SECTION("Copy assignment") {
67-
DynamicJsonDocument doc2;
68-
deserializeJson(doc2, "{\"hello\":\"world\"}");
69-
doc2.nestingLimit = 42;
93+
SECTION("Copy assignment preserves the buffer when capacity is sufficient") {
94+
DynamicJsonDocument doc1(1234);
95+
deserializeJson(doc1, "{\"hello\":\"world\"}");
96+
doc1.nestingLimit = 42;
7097

71-
doc = doc2;
98+
DynamicJsonDocument doc2(doc1.capacity());
99+
doc2 = doc1;
72100

73101
std::string json;
74-
serializeJson(doc, json);
102+
serializeJson(doc2, json);
75103
REQUIRE(json == "{\"hello\":\"world\"}");
76-
REQUIRE(doc.nestingLimit == 42);
104+
REQUIRE(doc2.nestingLimit == 42);
105+
REQUIRE(doc2.cap F438 acity() == doc1.capacity());
106+
}
107+
108+
SECTION("Copy assignment realloc the buffer when capacity is insufficient") {
109+
DynamicJsonDocument doc1(1234);
110+
deserializeJson(doc1, "{\"hello\":\"world\"}");
111+
doc1.nestingLimit = 42;
112+
DynamicJsonDocument doc2(8);
113+
114+
REQUIRE(doc2.capacity() < doc1.memoryUsage());
115+
doc2 = doc1;
116+
REQUIRE(doc2.capacity() >= doc1.memoryUsage());
117+
118+
std::string json;
119+
serializeJson(doc2, json);
120+
REQUIRE(json == "{\"hello\":\"world\"}");
121+
REQUIRE(doc2.nestingLimit == 42);
77122
}
78123

79124
SECTION("Construct from StaticJsonDocument") {
@@ -87,6 +132,7 @@ TEST_CASE("DynamicJsonDocument") {
87132
serializeJson(ddoc, json);
88133
REQUIRE(json == "{\"hello\":\"world\"}");
89134
REQUIRE(ddoc.nestingLimit == 42);
135+
REQUIRE(ddoc.capacity() == sdoc.capacity());
90136
}
91137

92138
SECTION("Assign from StaticJsonDocument") {
@@ -104,26 +150,4 @@ TEST_CASE("DynamicJsonDocument") {
104150
REQUIRE(json == "{\"hello\":\"world\"}");
105151
REQUIRE(ddoc.nestingLimit == 42);
106152
}
107-
108-
SECTION("memoryUsage()") {
109-
SECTION("Increases after adding value to array") {
110-
JsonArray arr = doc.to<JsonArray>();
111-
112-
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0));
113-
arr.add(42);
114-
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(1));
115-
arr.add(43);
116-
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(2));
117-
}
118-
119-
SECTION("Increases after adding value to object") {
120-
JsonObject obj = doc.to<JsonObject>();
121-
122-
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
123-
obj["a"] = 1;
124-
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1));
125-
obj["b"] = 2;
126-
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2));
127-
}
128-
}
129153
}

0 commit comments

Comments
 (0)
0