From 218a12ca4691b2571fe956242915d7000c84f476 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Mon, 31 Jul 2023 17:34:17 +0200 Subject: [PATCH] Call `shrinkToFit()` in `deserializeJson()` and `deserializeMsgPack()` --- CHANGELOG.md | 1 + extras/tests/JsonDeserializer/array.cpp | 10 +- .../JsonDeserializer/destination_types.cpp | 40 +++++--- extras/tests/JsonDeserializer/filter.cpp | 28 +++--- extras/tests/JsonDeserializer/input_types.cpp | 1 + extras/tests/JsonDeserializer/misc.cpp | 7 +- extras/tests/JsonDeserializer/object.cpp | 22 ++--- extras/tests/JsonDeserializer/string.cpp | 4 + .../MsgPackDeserializer/destination_types.cpp | 33 +++++-- extras/tests/MsgPackDeserializer/filter.cpp | 93 +++++++++++++++++-- src/ArduinoJson/Configuration.hpp | 11 +++ src/ArduinoJson/Deserialization/Filter.hpp | 11 ++- .../Deserialization/deserialize.hpp | 8 +- src/ArduinoJson/Memory/VariantPoolImpl.hpp | 7 +- 14 files changed, 209 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2393d0b4..83d614b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,3 +25,4 @@ HEAD * Remove `JsonDocument::memoryUsage()` * Remove `JsonDocument::garbageCollect()` * Add `deserializeJson(JsonVariant, ...)` and `deserializeMsgPack(JsonVariant, ...)` (#1226) +* Call `shrinkToFit()` in `deserializeJson()` and `deserializeMsgPack()` diff --git a/extras/tests/JsonDeserializer/array.cpp b/extras/tests/JsonDeserializer/array.cpp index 2c0e4460..997e17ee 100644 --- a/extras/tests/JsonDeserializer/array.cpp +++ b/extras/tests/JsonDeserializer/array.cpp @@ -249,13 +249,14 @@ TEST_CASE("deserialize JSON array") { SECTION("Should clear the JsonArray") { deserializeJson(doc, "[1,2,3,4]"); - deserializeJson(doc, "[]"); - JsonArray arr = doc.as(); + spy.clearLog(); + deserializeJson(doc, "[]"); + + JsonArray arr = doc.as(); REQUIRE(arr.size() == 0); REQUIRE(spy.log() == AllocatorLog{ - Allocate(sizeofPool()), - Deallocate(sizeofPool()), + Deallocate(sizeofArray(4)), }); } } @@ -312,6 +313,7 @@ TEST_CASE("deserialize JSON array under memory constraints") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("1234567")), + Reallocate(sizeofPool(), sizeofArray(1)), }); } } diff --git a/extras/tests/JsonDeserializer/destination_types.cpp b/extras/tests/JsonDeserializer/destination_types.cpp index 20841171..c387572d 100644 --- a/extras/tests/JsonDeserializer/destination_types.cpp +++ b/extras/tests/JsonDeserializer/destination_types.cpp @@ -9,6 +9,9 @@ #include "Allocators.hpp" +using ArduinoJson::detail::sizeofArray; +using ArduinoJson::detail::sizeofObject; + TEST_CASE("deserializeJson(JsonDocument&)") { SpyingAllocator spy; JsonDocument doc(&spy); @@ -23,6 +26,7 @@ TEST_CASE("deserializeJson(JsonDocument&)") { Deallocate(sizeofPool()), Deallocate(sizeofString("hello")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofArray(1)), }); } @@ -39,9 +43,11 @@ TEST_CASE("deserializeJson(JsonVariant)") { REQUIRE(err == DeserializationError::Ok); REQUIRE(doc.as() == "[[42]]"); - REQUIRE(spy.log() == AllocatorLog{ - Deallocate(sizeofString("hello")), - }); + REQUIRE(spy.log() == + AllocatorLog{ + Deallocate(sizeofString("hello")), + Reallocate(sizeofPool(), sizeofArray(1) + sizeofArray(1)), + }); } SECTION("variant is unbound") { @@ -64,17 +70,22 @@ TEST_CASE("deserializeJson(ElementProxy)") { REQUIRE(err == DeserializationError::Ok); REQUIRE(doc.as() == "[[42]]"); - REQUIRE(spy.log() == AllocatorLog{ - Deallocate(sizeofString("hello")), - }); + REQUIRE(spy.log() == + AllocatorLog{ + Deallocate(sizeofString("hello")), + Reallocate(sizeofPool(), sizeofArray(1) + sizeofArray(1)), + }); } - SECTION("element must be created exists") { + SECTION("element must be created") { auto err = deserializeJson(doc[1], "[42]"); REQUIRE(err == DeserializationError::Ok); REQUIRE(doc.as() == "[\"hello\",[42]]"); - REQUIRE(spy.log() == AllocatorLog{}); + REQUIRE(spy.log() == + AllocatorLog{ + Reallocate(sizeofPool(), sizeofArray(2) + sizeofArray(1)), + }); } } @@ -89,9 +100,11 @@ TEST_CASE("deserializeJson(MemberProxy)") { REQUIRE(err == DeserializationError::Ok); REQUIRE(doc.as() == "{\"hello\":[42]}"); - REQUIRE(spy.log() == AllocatorLog{ - Deallocate(sizeofString("world")), - }); + REQUIRE(spy.log() == + AllocatorLog{ + Deallocate(sizeofString("world")), + Reallocate(sizeofPool(), sizeofObject(1) + sizeofArray(1)), + }); } SECTION("member must be created exists") { @@ -99,6 +112,9 @@ TEST_CASE("deserializeJson(MemberProxy)") { REQUIRE(err == DeserializationError::Ok); REQUIRE(doc.as() == "{\"hello\":\"world\",\"value\":[42]}"); - REQUIRE(spy.log() == AllocatorLog{}); + REQUIRE(spy.log() == + AllocatorLog{ + Reallocate(sizeofPool(), sizeofObject(2) + sizeofArray(1)), + }); } } diff --git a/extras/tests/JsonDeserializer/filter.cpp b/extras/tests/JsonDeserializer/filter.cpp index cc1f2a28..8033910a 100644 --- a/extras/tests/JsonDeserializer/filter.cpp +++ b/extras/tests/JsonDeserializer/filter.cpp @@ -711,20 +711,6 @@ TEST_CASE("Filtering") { } } -TEST_CASE("Zero-copy mode") { // issue #1697 - char input[] = "{\"include\":42,\"exclude\":666}"; - - JsonDocument filter; - filter["include"] = true; - - JsonDocument doc; - DeserializationError err = - deserializeJson(doc, input, DeserializationOption::Filter(filter)); - - REQUIRE(err == DeserializationError::Ok); - CHECK(doc.as() == "{\"include\":42}"); -} - TEST_CASE("Overloads") { JsonDocument doc; JsonDocument filter; @@ -815,3 +801,17 @@ TEST_CASE("Overloads") { } #endif } + +TEST_CASE("shrink filter") { + JsonDocument doc; + SpyingAllocator spy; + JsonDocument filter(&spy); + filter["a"] = true; + spy.clearLog(); + + deserializeJson(doc, "{}", DeserializationOption::Filter(filter)); + + REQUIRE(spy.log() == AllocatorLog{ + Reallocate(sizeofPool(), sizeofObject(1)), + }); +} diff --git a/extras/tests/JsonDeserializer/input_types.cpp b/extras/tests/JsonDeserializer/input_types.cpp index 2c57c000..d0ed2f4b 100644 --- a/extras/tests/JsonDeserializer/input_types.cpp +++ b/extras/tests/JsonDeserializer/input_types.cpp @@ -29,6 +29,7 @@ TEST_CASE("deserializeJson(char*)") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("world")), + Reallocate(sizeofPool(), sizeofObject(1)), }); } diff --git a/extras/tests/JsonDeserializer/misc.cpp b/extras/tests/JsonDeserializer/misc.cpp index 41407550..3852cecb 100644 --- a/extras/tests/JsonDeserializer/misc.cpp +++ b/extras/tests/JsonDeserializer/misc.cpp @@ -7,6 +7,8 @@ #include "Allocators.hpp" +using ArduinoJson::detail::sizeofArray; + TEST_CASE("deserializeJson() misc cases") { SpyingAllocator spy; JsonDocument doc(&spy); @@ -35,12 +37,13 @@ TEST_CASE("deserializeJson() misc cases") { SECTION("Should clear the JsonVariant") { deserializeJson(doc, "[1,2,3]"); + spy.clearLog(); + deserializeJson(doc, "{}"); REQUIRE(doc.is()); REQUIRE(spy.log() == AllocatorLog{ - Allocate(sizeofPool()), - Deallocate(sizeofPool()), + Deallocate(sizeofArray(3)), }); } } diff --git a/extras/tests/JsonDeserializer/object.cpp b/extras/tests/JsonDeserializer/object.cpp index eea4a027..db5355d7 100644 --- a/extras/tests/JsonDeserializer/object.cpp +++ b/extras/tests/JsonDeserializer/object.cpp @@ -296,6 +296,7 @@ TEST_CASE("deserialize JSON object") { Deallocate(sizeofString("b")), Deallocate(sizeofString("c")), Deallocate(sizeofStringBuffer()), + Reallocate(sizeofPool(), sizeofObject(2) + sizeofObject(1)), }); } @@ -318,22 +319,17 @@ TEST_CASE("deserialize JSON object") { SECTION("Should clear the JsonObject") { deserializeJson(doc, "{\"hello\":\"world\"}"); + spy.clearLog(); + deserializeJson(doc, "{}"); - JsonObject obj = doc.as(); REQUIRE(doc.is()); - REQUIRE(obj.size() == 0); - REQUIRE(spy.log() == - AllocatorLog{ - Allocate(sizeofStringBuffer()), - Reallocate(sizeofStringBuffer(), sizeofString("hello")), - Allocate(sizeofPool()), - Allocate(sizeofStringBuffer()), - Reallocate(sizeofStringBuffer(), sizeofString("world")), - Deallocate(sizeofPool()), - Deallocate(sizeofString("hello")), - Deallocate(sizeofString("world")), - }); + REQUIRE(doc.size() == 0); + REQUIRE(spy.log() == AllocatorLog{ + Deallocate(sizeofObject(1)), + Deallocate(sizeofString("hello")), + Deallocate(sizeofString("world")), + }); } SECTION("Issue #1335") { diff --git a/extras/tests/JsonDeserializer/string.cpp b/extras/tests/JsonDeserializer/string.cpp index 54b92207..e64daf4d 100644 --- a/extras/tests/JsonDeserializer/string.cpp +++ b/extras/tests/JsonDeserializer/string.cpp @@ -120,6 +120,7 @@ TEST_CASE("Allocation of the key fails") { Reallocate(sizeofStringBuffer(), sizeofString("hello")), Allocate(sizeofPool()), AllocateFail(sizeofStringBuffer()), + ReallocateFail(sizeofPool(), sizeofObject(1)), }); } @@ -141,6 +142,7 @@ TEST_CASE("Allocation of the key fails") { Reallocate(sizeofStringBuffer(), sizeofString("hello")), Allocate(sizeofPool()), AllocateFail(sizeofStringBuffer()), + ReallocateFail(sizeofPool(), sizeofObject(1)), }); } } @@ -171,6 +173,7 @@ TEST_CASE("Deduplicate values") { Reallocate(sizeofStringBuffer(), sizeofString("example")), Allocate(sizeofStringBuffer()), Deallocate(sizeofStringBuffer()), + Reallocate(sizeofPool(), sizeofArray(2)), }); } @@ -190,5 +193,6 @@ TEST_CASE("Deduplicate keys") { Reallocate(sizeofStringBuffer(), sizeofString("example")), Allocate(sizeofStringBuffer()), Deallocate(sizeofStringBuffer()), + Reallocate(sizeofPool(), sizeofArray(2) + 2 * sizeofObject(1)), }); } diff --git a/extras/tests/MsgPackDeserializer/destination_types.cpp b/extras/tests/MsgPackDeserializer/destination_types.cpp index b0a7aa39..eea1c154 100644 --- a/extras/tests/MsgPackDeserializer/destination_types.cpp +++ b/extras/tests/MsgPackDeserializer/destination_types.cpp @@ -9,6 +9,9 @@ #include "Allocators.hpp" +using ArduinoJson::detail::sizeofArray; +using ArduinoJson::detail::sizeofObject; + TEST_CASE("deserializeMsgPack(JsonDocument&)") { SpyingAllocator spy; JsonDocument doc(&spy); @@ -23,6 +26,7 @@ TEST_CASE("deserializeMsgPack(JsonDocument&)") { Deallocate(sizeofPool()), Deallocate(sizeofString("hello")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofArray(1)), }); } @@ -39,9 +43,11 @@ TEST_CASE("deserializeMsgPack(JsonVariant)") { REQUIRE(err == DeserializationError::Ok); REQUIRE(doc.as() == "[[42]]"); - REQUIRE(spy.log() == AllocatorLog{ - Deallocate(sizeofString("hello")), - }); + REQUIRE(spy.log() == + AllocatorLog{ + Deallocate(sizeofString("hello")), + Reallocate(sizeofPool(), sizeofArray(1) + sizeofArray(1)), + }); } SECTION("variant is unbound") { @@ -64,9 +70,11 @@ TEST_CASE("deserializeMsgPack(ElementProxy)") { REQUIRE(err == DeserializationError::Ok); REQUIRE(doc.as() == "[[42]]"); - REQUIRE(spy.log() == AllocatorLog{ - Deallocate(sizeofString("hello")), - }); + REQUIRE(spy.log() == + AllocatorLog{ + Deallocate(sizeofString("hello")), + Reallocate(sizeofPool(), sizeofArray(1) + sizeofArray(1)), + }); } SECTION("element must be created exists") { @@ -74,7 +82,10 @@ TEST_CASE("deserializeMsgPack(ElementProxy)") { REQUIRE(err == DeserializationError::Ok); REQUIRE(doc.as() == "[\"hello\",[42]]"); - REQUIRE(spy.log() == AllocatorLog{}); + REQUIRE(spy.log() == + AllocatorLog{ + Reallocate(sizeofPool(), sizeofArray(2) + sizeofArray(1)), + }); } } @@ -91,14 +102,18 @@ TEST_CASE("deserializeMsgPack(MemberProxy)") { REQUIRE(doc.as() == "{\"hello\":[42]}"); REQUIRE(spy.log() == AllocatorLog{ Deallocate(sizeofString("world")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } - SECTION("member must be created exists") { + SECTION("member must be created") { auto err = deserializeMsgPack(doc["value"], "\x91\x2A"); REQUIRE(err == DeserializationError::Ok); REQUIRE(doc.as() == "{\"hello\":\"world\",\"value\":[42]}"); - REQUIRE(spy.log() == AllocatorLog{}); + REQUIRE(spy.log() == + AllocatorLog{ + Reallocate(sizeofPool(), sizeofObject(2) + sizeofArray(1)), + }); } } diff --git a/extras/tests/MsgPackDeserializer/filter.cpp b/extras/tests/MsgPackDeserializer/filter.cpp index e2d5fdea..ff63ef74 100644 --- a/extras/tests/MsgPackDeserializer/filter.cpp +++ b/extras/tests/MsgPackDeserializer/filter.cpp @@ -80,6 +80,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -105,6 +106,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -119,6 +121,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -133,6 +136,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -147,6 +151,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -161,6 +166,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -175,6 +181,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -189,6 +196,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -203,6 +211,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -218,6 +227,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -233,6 +243,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -249,6 +260,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -265,6 +277,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -280,6 +293,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -296,6 +310,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -310,6 +325,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -324,6 +340,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -338,6 +355,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -353,6 +371,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -367,6 +386,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -381,6 +401,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -396,6 +417,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -410,6 +432,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -425,6 +448,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -443,6 +467,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -458,6 +483,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -475,6 +501,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -494,6 +521,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -511,6 +539,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -528,6 +557,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -545,6 +575,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -562,6 +593,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -581,6 +613,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -598,6 +631,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -615,6 +649,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } @@ -632,6 +667,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofObject(1)), }); } } @@ -662,6 +698,8 @@ TEST_CASE("deserializeMsgPack() filter") { Reallocate(sizeofStringBuffer(), sizeofString("measure")), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2) + sizeofArray(2) + + 2 * sizeofObject(1)), }); } @@ -686,6 +724,8 @@ TEST_CASE("deserializeMsgPack() filter") { Reallocate(sizeofStringBuffer(), sizeofString("measure")), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2) + sizeofArray(2) + + 2 * sizeofObject(1)), }); } @@ -710,6 +750,8 @@ TEST_CASE("deserializeMsgPack() filter") { Reallocate(sizeofStringBuffer(), sizeofString("measure")), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2) + sizeofArray(2) + + 2 * sizeofObject(1)), }); } @@ -726,6 +768,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -742,6 +785,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -758,6 +802,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -774,6 +819,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -790,6 +836,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -806,6 +853,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -822,6 +870,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -839,6 +888,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -857,6 +907,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -873,6 +924,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -889,6 +941,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -906,6 +959,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -924,6 +978,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -941,6 +996,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -959,6 +1015,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -975,6 +1032,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1004,6 +1062,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1021,6 +1080,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1040,6 +1100,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1061,6 +1122,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } } @@ -1091,6 +1153,7 @@ TEST_CASE("deserializeMsgPack() filter") { CHECK(doc.as() == "[1,2,3]"); CHECK(spy.log() == AllocatorLog{ Allocate(sizeofPool()), + Reallocate(sizeofPool(), sizeofArray(3)), }); } } @@ -1121,6 +1184,7 @@ TEST_CASE("deserializeMsgPack() filter") { Reallocate(sizeofStringBuffer(), sizeofString("measure")), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2) + sizeofObject(1)), }); } @@ -1143,6 +1207,7 @@ TEST_CASE("deserializeMsgPack() filter") { Reallocate(sizeofStringBuffer(), sizeofString("measure")), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2) + sizeofObject(1)), }); } @@ -1166,6 +1231,7 @@ TEST_CASE("deserializeMsgPack() filter") { Reallocate(sizeofStringBuffer(), sizeofString("measure")), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2) + sizeofObject(1)), }); } @@ -1182,6 +1248,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1198,6 +1265,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1214,6 +1282,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1230,6 +1299,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1246,6 +1316,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1262,6 +1333,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1278,6 +1350,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1294,6 +1367,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1312,6 +1386,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1328,6 +1403,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1344,6 +1420,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1360,6 +1437,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1373,12 +1451,12 @@ TEST_CASE("deserializeMsgPack() filter") { CHECK(doc.as() == "{\"onlyobj\":null,\"include\":42}"); CHECK(spy.log() == AllocatorLog{ - // string builder's buffer Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("onlyarr")), Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1390,12 +1468,12 @@ TEST_CASE("deserializeMsgPack() filter") { CHECK(doc.as() == "{\"onlyobj\":null,\"include\":42}"); CHECK(spy.log() == AllocatorLog{ - // string builder's buffer Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("onlyarr")), Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1409,12 +1487,12 @@ TEST_CASE("deserializeMsgPack() filter") { CHECK(doc.as() == "{\"onlyobj\":null,\"include\":42}"); CHECK(spy.log() == AllocatorLog{ - // string builder's buffer Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("onlyarr")), Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1426,12 +1504,12 @@ TEST_CASE("deserializeMsgPack() filter") { CHECK(doc.as() == "{\"onlyobj\":null,\"include\":42}"); CHECK(spy.log() == AllocatorLog{ - // string builder's buffer Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("onlyarr")), Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1456,12 +1534,12 @@ TEST_CASE("deserializeMsgPack() filter") { CHECK(spy.log() == AllocatorLog{ - // string builder's buffer Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("onlyarr")), Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1473,12 +1551,12 @@ TEST_CASE("deserializeMsgPack() filter") { CHECK(doc.as() == "{\"onlyobj\":null,\"include\":42}"); CHECK(spy.log() == AllocatorLog{ - // string builder's buffer Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("onlyarr")), Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1492,12 +1570,12 @@ TEST_CASE("deserializeMsgPack() filter") { CHECK(doc.as() == "{\"onlyobj\":null,\"include\":42}"); CHECK(spy.log() == AllocatorLog{ - // string builder's buffer Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("onlyarr")), Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } @@ -1517,6 +1595,7 @@ TEST_CASE("deserializeMsgPack() filter") { Allocate(sizeofPool()), Allocate(sizeofStringBuffer()), Reallocate(sizeofStringBuffer(), sizeofString("include")), + Reallocate(sizeofPool(), sizeofObject(2)), }); } } diff --git a/src/ArduinoJson/Configuration.hpp b/src/ArduinoJson/Configuration.hpp index 6869a323..3e68861a 100644 --- a/src/ArduinoJson/Configuration.hpp +++ b/src/ArduinoJson/Configuration.hpp @@ -110,6 +110,17 @@ # define ARDUINOJSON_INITIAL_POOL_COUNT 4 #endif +// Automatically call shrinkToFit() from deserializeXxx() +// Disabled by default on 8-bit platforms because it's not worth the increase in +// code size +#ifndef ARDUINOJSON_AUTO_SHRINK +# if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ <= 2 +# define ARDUINOJSON_AUTO_SHRINK 0 +# else +# define ARDUINOJSON_AUTO_SHRINK 1 +# endif +#endif + #ifdef ARDUINO // Enable support for Arduino's String class diff --git a/src/ArduinoJson/Deserialization/Filter.hpp b/src/ArduinoJson/Deserialization/Filter.hpp index 39883027..3cd0c6ad 100644 --- a/src/ArduinoJson/Deserialization/Filter.hpp +++ b/src/ArduinoJson/Deserialization/Filter.hpp @@ -4,14 +4,21 @@ #pragma once -#include +#include +#include ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE namespace DeserializationOption { class Filter { public: - explicit Filter(JsonVariantConst v) : variant_(v) {} +#if ARDUINOJSON_AUTO_SHRINK + explicit Filter(JsonDocument& doc) : variant_(doc) { + doc.shrinkToFit(); + } +#endif + + explicit Filter(JsonVariantConst variant) : variant_(variant) {} bool allow() const { return variant_; diff --git a/src/ArduinoJson/Deserialization/deserialize.hpp b/src/ArduinoJson/Deserialization/deserialize.hpp index 17f44cbe..bd3e9108 100644 --- a/src/ArduinoJson/Deserialization/deserialize.hpp +++ b/src/ArduinoJson/Deserialization/deserialize.hpp @@ -43,8 +43,12 @@ DeserializationError doDeserialize(TDestination&& dst, TReader reader, return DeserializationError::NoMemory; auto resources = VariantAttorney::getResourceManager(dst); dst.clear(); - return TDeserializer(resources, reader) - .parse(*data, options.filter, options.nestingLimit); + auto err = TDeserializer(resources, reader) + .parse(*data, options.filter, options.nestingLimit); +#if ARDUINOJSON_AUTO_SHRINK + resources->shrinkToFit(); +#endif + return err; } template