mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 08:42:39 +01:00 
			
		
		
		
	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