diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a96f62f..6490e0ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ HEAD ---- * Removed the automatic expansion of `DynamicJsonDocument`, it now has a fixed capacity. +* Restored the monotonic allocator because the code was getting too big v6.6.0-beta (2018-11-13) ----------- @@ -14,7 +15,7 @@ v6.6.0-beta (2018-11-13) * Replaced `T JsonArray::get(i)` with `JsonVariant JsonArray::get(i)` * Replaced `T JsonObject::get(k)` with `JsonVariant JsonObject::get(k)` * Added `JSON_STRING_SIZE()` -* Replacing or removing a value now releases the memory +* ~~Replacing or removing a value now releases the memory~~ * Added `DeserializationError::code()` to be used in switch statements (issue #846) v6.5.0-beta (2018-10-13) diff --git a/src/ArduinoJson/Data/ArrayFunctions.hpp b/src/ArduinoJson/Data/ArrayFunctions.hpp index e11d9eec..c47def36 100644 --- a/src/ArduinoJson/Data/ArrayFunctions.hpp +++ b/src/ArduinoJson/Data/ArrayFunctions.hpp @@ -42,8 +42,7 @@ inline JsonVariantData* arrayGet(const JsonArrayData* arr, size_t index) { return slot ? &slot->value : 0; } -inline void arrayRemove(JsonArrayData* arr, VariantSlot* slot, - MemoryPool* pool) { +inline void arrayRemove(JsonArrayData* arr, VariantSlot* slot) { if (!arr || !slot) return; if (slot->prev) @@ -54,12 +53,10 @@ inline void arrayRemove(JsonArrayData* arr, VariantSlot* slot, slot->next->prev = slot->prev; else arr->tail = slot->prev; - - slotFree(slot, pool); } -inline void arrayRemove(JsonArrayData* arr, size_t index, MemoryPool* pool) { - arrayRemove(arr, arrayGetSlot(arr, index), pool); +inline void arrayRemove(JsonArrayData* arr, size_t index) { + arrayRemove(arr, arrayGetSlot(arr, index)); } inline void arrayClear(JsonArrayData* arr) { @@ -100,15 +97,4 @@ inline size_t arraySize(const JsonArrayData* arr) { if (!arr) return 0; return slotSize(arr->head); } - -inline void arrayFree(JsonArrayData* arr, MemoryPool* pool) { - ARDUINOJSON_ASSERT(arr); - - VariantSlot* cur = arr->head; - while (cur) { - VariantSlot* next = cur->next; - slotFree(cur, pool); - cur = next; - } -} } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Data/ObjectFunctions.hpp b/src/ArduinoJson/Data/ObjectFunctions.hpp index 5604f877..ea8b7f39 100644 --- a/src/ArduinoJson/Data/ObjectFunctions.hpp +++ b/src/ArduinoJson/Data/ObjectFunctions.hpp @@ -76,8 +76,7 @@ inline void objectClear(JsonObjectData* obj) { obj->tail = 0; } -inline void objectRemove(JsonObjectData* obj, VariantSlot* slot, - MemoryPool* pool) { +inline void objectRemove(JsonObjectData* obj, VariantSlot* slot) { if (!obj) return; if (!slot) return; if (slot->prev) @@ -88,8 +87,6 @@ inline void objectRemove(JsonObjectData* obj, VariantSlot* slot, slot->next->prev = slot->prev; else obj->tail = slot->prev; - - slotFree(slot, pool); } inline size_t objectSize(const JsonObjectData* obj) { diff --git a/src/ArduinoJson/Data/SlotFunctions.hpp b/src/ArduinoJson/Data/SlotFunctions.hpp index 006f6f3a..24e45f50 100644 --- a/src/ArduinoJson/Data/SlotFunctions.hpp +++ b/src/ArduinoJson/Data/SlotFunctions.hpp @@ -61,17 +61,4 @@ inline size_t slotSize(const VariantSlot* var) { } return n; } - -void variantFree(JsonVariantData* var, MemoryPool* pool); - -inline void slotFree(VariantSlot* var, MemoryPool* pool) { - ARDUINOJSON_ASSERT(var != 0); - ARDUINOJSON_ASSERT(pool != 0); - - variantFree(&var->value, pool); - - if (var->value.keyIsOwned) pool->freeString(var->ownedKey); - - pool->freeVariant(var); -} } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Data/VariantFunctions.hpp b/src/ArduinoJson/Data/VariantFunctions.hpp index 32ccc56b..67c498ef 100644 --- a/src/ArduinoJson/Data/VariantFunctions.hpp +++ b/src/ArduinoJson/Data/VariantFunctions.hpp @@ -12,25 +12,6 @@ #include "ObjectFunctions.hpp" namespace ARDUINOJSON_NAMESPACE { - -inline void variantFree(JsonVariantData* var, MemoryPool* pool) { - ARDUINOJSON_ASSERT(var != 0); - ARDUINOJSON_ASSERT(pool != 0); - - switch (var->type) { - case JSON_ARRAY: - case JSON_OBJECT: - arrayFree(&var->content.asArray, pool); - break; - case JSON_OWNED_STRING: - case JSON_OWNED_RAW: - pool->freeString(var->content.asOwnedString); - break; - default: - break; - } -} - template inline T variantAsIntegral(const JsonVariantData* var) { if (!var) return 0; @@ -116,30 +97,23 @@ inline const JsonObjectData* variantAsObject(const JsonVariantData* var) { return 0; } -inline bool variantSetBoolean(JsonVariantData* var, bool value, - MemoryPool* pool) { +inline bool variantSetBoolean(JsonVariantData* var, bool value) { if (!var) return false; - variantFree(var, pool); var->type = JSON_BOOLEAN; var->content.asInteger = static_cast(value); return true; } -inline bool variantSetFloat(JsonVariantData* var, JsonFloat value, - MemoryPool* pool) { +inline bool variantSetFloat(JsonVariantData* var, JsonFloat value) { if (!var) return false; - variantFree(var, pool); var->type = JSON_FLOAT; var->content.asFloat = value; return true; } template -inline bool variantSetSignedInteger(JsonVariantData* var, T value, - MemoryPool* pool) { +inline bool variantSetSignedInteger(JsonVariantData* var, T value) { if (!var) return false; - variantFree(var, pool); - if (value >= 0) { var->type = JSON_POSITIVE_INTEGER; var->content.asInteger = static_cast(value); @@ -150,20 +124,16 @@ inline bool variantSetSignedInteger(JsonVariantData* var, T value, return true; } -inline bool variantSetUnsignedInteger(JsonVariantData* var, JsonUInt value, - MemoryPool* pool) { +inline bool variantSetUnsignedInteger(JsonVariantData* var, JsonUInt value) { if (!var) return false; - variantFree(var, pool); var->type = JSON_POSITIVE_INTEGER; var->content.asInteger = static_cast(value); return true; } inline bool variantSetLinkedRaw(JsonVariantData* var, - SerializedValue value, - MemoryPool* pool) { + SerializedValue value) { if (!var) return false; - variantFree(var, pool); var->type = JSON_LINKED_RAW; var->content.asRaw.data = value.data(); var->content.asRaw.size = value.size(); @@ -174,7 +144,6 @@ template inline bool variantSetOwnedRaw(JsonVariantData* var, SerializedValue value, MemoryPool* pool) { if (!var) return false; - variantFree(var, pool); StringSlot* slot = makeString(value.data(), value.size()).save(pool); if (slot) { var->type = JSON_OWNED_RAW; @@ -189,7 +158,6 @@ inline bool variantSetOwnedRaw(JsonVariantData* var, SerializedValue value, template inline bool variantSetString(JsonVariantData* var, T value, MemoryPool* pool) { if (!var) return false; - variantFree(var, pool); StringSlot* slot = value.save(pool); if (slot) { var->type = JSON_OWNED_STRING; @@ -201,42 +169,35 @@ inline bool variantSetString(JsonVariantData* var, T value, MemoryPool* pool) { } } -inline bool variantSetOwnedString(JsonVariantData* var, StringSlot* slot, - MemoryPool* pool) { +inline bool variantSetOwnedString(JsonVariantData* var, StringSlot* slot) { if (!var) return false; - variantFree(var, pool); var->type = JSON_OWNED_STRING; var->content.asOwnedString = slot; return true; } -inline bool variantSetString(JsonVariantData* var, const char* value, - MemoryPool* pool) { +inline bool variantSetString(JsonVariantData* var, const char* value) { if (!var) return false; - variantFree(var, pool); var->type = JSON_LINKED_STRING; var->content.asString = value; return true; } -inline void variantSetNull(JsonVariantData* var, MemoryPool* pool) { +inline void variantSetNull(JsonVariantData* var) { if (!var) return; - variantFree(var, pool); var->type = JSON_NULL; } -inline JsonArrayData* variantToArray(JsonVariantData* var, MemoryPool* pool) { +inline JsonArrayData* variantToArray(JsonVariantData* var) { if (!var) return 0; - variantFree(var, pool); var->type = JSON_ARRAY; var->content.asArray.head = 0; var->content.asArray.tail = 0; return &var->content.asArray; } -inline JsonObjectData* variantToObject(JsonVariantData* var, MemoryPool* pool) { +inline JsonObjectData* variantToObject(JsonVariantData* var) { if (!var) return 0; - variantFree(var, pool); var->type = JSON_OBJECT; var->content.asObject.head = 0; var->content.asObject.tail = 0; @@ -247,16 +208,14 @@ inline bool variantCopy(JsonVariantData* dst, const JsonVariantData* src, MemoryPool* pool) { if (!dst) return false; if (!src) { - variantFree(dst, pool); dst->type = JSON_NULL; return true; } switch (src->type) { case JSON_ARRAY: - return arrayCopy(variantToArray(dst, pool), &src->content.asArray, pool); + return arrayCopy(variantToArray(dst), &src->content.asArray, pool); case JSON_OBJECT: - return objectCopy(variantToObject(dst, pool), &src->content.asObject, - pool); + return objectCopy(variantToObject(dst), &src->content.asObject, pool); case JSON_OWNED_STRING: return variantSetString( dst, makeString(src->content.asOwnedString->value), pool); @@ -266,7 +225,6 @@ inline bool variantCopy(JsonVariantData* dst, const JsonVariantData* src, src->content.asOwnedRaw->size), pool); default: - variantFree(dst, pool); // caution: don't override keyIsOwned dst->type = src->type; dst->content = src->content; diff --git a/src/ArduinoJson/JsonArray.hpp b/src/ArduinoJson/JsonArray.hpp index 23e8b948..55617786 100644 --- a/src/ArduinoJson/JsonArray.hpp +++ b/src/ArduinoJson/JsonArray.hpp @@ -197,12 +197,12 @@ class JsonArray : public JsonArrayProxy, public Visitable { // Removes element at specified position. FORCE_INLINE void remove(iterator it) const { - arrayRemove(_data, it.internal(), _memoryPool); + arrayRemove(_data, it.internal()); } // Removes element at specified index. FORCE_INLINE void remove(size_t index) const { - arrayRemove(_data, index, _memoryPool); + arrayRemove(_data, index); } template diff --git a/src/ArduinoJson/JsonObject.hpp b/src/ArduinoJson/JsonObject.hpp index 1e9fde69..dad1174f 100644 --- a/src/ArduinoJson/JsonObject.hpp +++ b/src/ArduinoJson/JsonObject.hpp @@ -227,7 +227,7 @@ class JsonObject : public JsonObjectProxy, public Visitable { } FORCE_INLINE void remove(iterator it) const { - objectRemove(_data, it.internal(), _memoryPool); + objectRemove(_data, it.internal()); } // Removes the specified key and the associated value. @@ -282,7 +282,7 @@ class JsonObject : public JsonObjectProxy, public Visitable { template FORCE_INLINE void remove_impl(TStringRef key) const { - objectRemove(_data, objectFindSlot(_data, key), _memoryPool); + objectRemove(_data, objectFindSlot(_data, key)); } MemoryPool* _memoryPool; diff --git a/src/ArduinoJson/JsonVariant.hpp b/src/ArduinoJson/JsonVariant.hpp index 1138bcea..6e3de48d 100644 --- a/src/ArduinoJson/JsonVariant.hpp +++ b/src/ArduinoJson/JsonVariant.hpp @@ -133,7 +133,7 @@ class JsonVariant : public JsonVariantProxy, // set(bool value) FORCE_INLINE bool set(bool value) const { - return variantSetBoolean(_data, value, _memoryPool); + return variantSetBoolean(_data, value); } // set(double value); @@ -142,7 +142,7 @@ class JsonVariant : public JsonVariantProxy, FORCE_INLINE bool set( T value, typename enable_if::value>::type * = 0) const { - return variantSetFloat(_data, static_cast(value), _memoryPool); + return variantSetFloat(_data, static_cast(value)); } // set(char) @@ -155,7 +155,7 @@ class JsonVariant : public JsonVariantProxy, T value, typename enable_if::value && is_signed::value>::type * = 0) const { - return variantSetSignedInteger(_data, value, _memoryPool); + return variantSetSignedInteger(_data, value); } // set(unsigned short) @@ -165,13 +165,12 @@ class JsonVariant : public JsonVariantProxy, FORCE_INLINE bool set( T value, typename enable_if::value && is_unsigned::value>::type * = 0) const { - return variantSetUnsignedInteger(_data, static_cast(value), - _memoryPool); + return variantSetUnsignedInteger(_data, static_cast(value)); } // set(SerializedValue) FORCE_INLINE bool set(SerializedValue value) const { - return variantSetLinkedRaw(_data, value, _memoryPool); + return variantSetLinkedRaw(_data, value); } // set(SerializedValue) @@ -202,15 +201,15 @@ class JsonVariant : public JsonVariantProxy, // set(const char*); FORCE_INLINE bool set(const char *value) const { - return variantSetString(_data, value, _memoryPool); + return variantSetString(_data, value); } // for internal use only FORCE_INLINE bool set(StringInMemoryPool value) const { - return variantSetOwnedString(_data, value.slot(), _memoryPool); + return variantSetOwnedString(_data, value.slot()); } FORCE_INLINE bool set(ZeroTerminatedRamStringConst value) const { - return variantSetString(_data, value.c_str(), _memoryPool); + return variantSetString(_data, value.c_str()); } bool set(JsonVariantConst value) const; diff --git a/src/ArduinoJson/JsonVariantImpl.hpp b/src/ArduinoJson/JsonVariantImpl.hpp index ca99bdd7..66e6fdc6 100644 --- a/src/ArduinoJson/JsonVariantImpl.hpp +++ b/src/ArduinoJson/JsonVariantImpl.hpp @@ -53,19 +53,19 @@ JsonVariant::as() const { template inline typename enable_if::value, JsonArray>::type JsonVariant::to() const { - return JsonArray(_memoryPool, variantToArray(_data, _memoryPool)); + return JsonArray(_memoryPool, variantToArray(_data)); } template typename enable_if::value, JsonObject>::type JsonVariant::to() const { - return JsonObject(_memoryPool, variantToObject(_data, _memoryPool)); + return JsonObject(_memoryPool, variantToObject(_data)); } template typename enable_if::value, JsonVariant>::type JsonVariant::to() const { - variantSetNull(_data, _memoryPool); + variantSetNull(_data); return *this; } diff --git a/src/ArduinoJson/Memory/MemoryPool.hpp b/src/ArduinoJson/Memory/MemoryPool.hpp index 0bf24dd3..9d65b7de 100644 --- a/src/ArduinoJson/Memory/MemoryPool.hpp +++ b/src/ArduinoJson/Memory/MemoryPool.hpp @@ -9,7 +9,6 @@ #include "../Strings/StringInMemoryPool.hpp" #include "Alignment.hpp" #include "MemoryPool.hpp" -#include "SlotList.hpp" #include "StringSlot.hpp" #include "VariantSlot.hpp" @@ -60,24 +59,11 @@ class MemoryPool { } size_t size() const { - return allocated_bytes() - _freeVariants.size() - _freeStrings.size(); + return size_t(_left - _begin + _end - _right); } VariantSlot* allocVariant() { - VariantSlot* s = _freeVariants.pop(); - if (s) return s; - return s ? s : allocRight(); - } - - void freeVariant(VariantSlot* slot) { - freeVariantSlot(slot); - compactRightSide(); - } - - void freeString(StringSlot* slot) { - freeStringSlot(slot); - compactLeftSide(slot->value, slot->size); - compactRightSide(); + return allocRight(); } StringSlot* allocFrozenString(size_t n) { @@ -88,7 +74,6 @@ class MemoryPool { s->value = _left; s->size = n; _left += n; - _usedString.push(s); checkInvariants(); return s; @@ -100,7 +85,6 @@ class MemoryPool { s->value = _left; s->size = size_t(_right - _left); - _usedString.push(s); _left = _right; checkInvariants(); @@ -116,9 +100,6 @@ class MemoryPool { void clear() { _left = _begin; _right = _end; - _freeVariants.clear(); - _freeStrings.clear(); - _usedString.clear(); } bool canAlloc(size_t bytes) const { @@ -146,50 +127,10 @@ class MemoryPool { } private: - size_t allocated_bytes() const { - return size_t(_left - _begin + _end - _right); - } - StringSlot* allocStringSlot() { - StringSlot* s = _freeStrings.pop(); - if (s) return s; return allocRight(); } - void freeVariantSlot(VariantSlot* slot) { - _freeVariants.push(slot); - } - - void freeStringSlot(StringSlot* slot) { - _usedString.remove(slot); - _freeStrings.push(slot); - } - - void compactLeftSide(char* holeAddress, size_t holeSize) { - ARDUINOJSON_ASSERT(holeAddress >= _begin); - ARDUINOJSON_ASSERT(holeAddress + holeSize <= _left); - char* holeEnd = holeAddress + holeSize; - memmove(holeAddress, // where the hole begun - holeEnd, // where the hole ended - size_t(_left - holeEnd)); // everything after the hole - _left -= holeSize; - _usedString.forEach(UpdateStringSlotAddress(holeAddress, holeSize)); - checkInvariants(); - } - - void compactRightSide() { - loop: - if (_freeStrings.remove(_right)) { - _right += sizeof(StringSlot); - goto loop; - } - if (_freeVariants.remove(_right)) { - _right += sizeof(VariantSlot); - goto loop; - } - checkInvariants(); - } - void checkInvariants() { ARDUINOJSON_ASSERT(_begin <= _left); ARDUINOJSON_ASSERT(_left <= _right); @@ -198,9 +139,6 @@ class MemoryPool { } char *_begin, *_left, *_right, *_end; - SlotList _freeVariants; - SlotList _freeStrings; - SlotList _usedString; }; } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Memory/SlotList.hpp b/src/ArduinoJson/Memory/SlotList.hpp deleted file mode 100644 index d8a780e4..00000000 --- a/src/ArduinoJson/Memory/SlotList.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#pragma once - -#include // for size_t - -namespace ARDUINOJSON_NAMESPACE { - -template -class SlotList { - public: - SlotList() : _head(0) {} - - TSlot *pop() { - TSlot *slot = _head; - if (slot) _head = slot->next; - return slot; - } - - void push(TSlot *slot) { - slot->next = _head; - _head = slot; - } - - bool remove(const TSlot *slot) { - if (_head == slot) { - _head = slot->next; - return true; - } - - for (TSlot *s = _head; s; s = s->next) { - if (s->next == slot) { - s->next = slot->next; - return true; - } - } - - return false; - } - - bool remove(const void *slot) { - return remove(reinterpret_cast(slot)); - } - - template - void forEach(const Functor &f) { - for (TSlot *s = _head; s; s = s->next) { - f(s); - } - } - - size_t size() const { - size_t sum = 0; - for (TSlot *s = _head; s; s = s->next) sum += sizeof(TSlot); - return sum; - } - - void clear() { - _head = 0; - } - - private: - TSlot *_head; -}; -} // namespace ARDUINOJSON_NAMESPACE diff --git a/test/JsonDocument/DynamicJsonDocument.cpp b/test/JsonDocument/DynamicJsonDocument.cpp index 32643f07..b6fe03ab 100644 --- a/test/JsonDocument/DynamicJsonDocument.cpp +++ b/test/JsonDocument/DynamicJsonDocument.cpp @@ -116,18 +116,6 @@ TEST_CASE("DynamicJsonDocument") { REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(2)); } - SECTION("Decreases after removing value from array") { - JsonArray arr = doc.to(); - arr.add(42); - arr.add(43); - - REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(2)); - arr.remove(1); - REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(1)); - arr.remove(0); - REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0)); - } - SECTION("Increases after adding value to object") { JsonObject obj = doc.to(); @@ -137,37 +125,5 @@ TEST_CASE("DynamicJsonDocument") { obj["b"] = 2; REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2)); } - - SECTION("Decreases after removing value from object") { - JsonObject obj = doc.to(); - obj["a"] = 1; - obj["b"] = 2; - - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2)); - obj.remove("a"); - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1)); - obj.remove("b"); - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0)); - } - - SECTION("Decreases after removing nested object from array") { - JsonArray arr = doc.to(); - JsonObject obj = arr.createNestedObject(); - obj["hello"] = "world"; - - REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1)); - arr.remove(0); - REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0)); - } - - SECTION("Decreases after removing nested array from object") { - JsonObject obj = doc.to(); - JsonArray arr = obj.createNestedArray("hello"); - arr.add("world"); - - REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1)); - obj.remove("hello"); - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0)); - } } } diff --git a/test/JsonObject/createNestedObject.cpp b/test/JsonObject/createNestedObject.cpp index be0ed57e..26e8080c 100644 --- a/test/JsonObject/createNestedObject.cpp +++ b/test/JsonObject/createNestedObject.cpp @@ -22,17 +22,4 @@ TEST_CASE("JsonObject::createNestedObject()") { obj.createNestedObject(vla); } #endif - - SECTION("releases memory from nested object") { - obj.createNestedObject(std::string("a")) - .createNestedObject(std::string("b")) - .set(std::string("c")) - .set(1); - // {"a":{"b":{"c":1}}} - REQUIRE(doc.memoryUsage() == - 3 * JSON_OBJECT_SIZE(1) + 3 * JSON_STRING_SIZE(2)); - - obj.createNestedObject(std::string("a")); - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(2)); - } } diff --git a/test/JsonObject/remove.cpp b/test/JsonObject/remove.cpp index 3af304f9..3c83e7f2 100644 --- a/test/JsonObject/remove.cpp +++ b/test/JsonObject/remove.cpp @@ -19,47 +19,18 @@ TEST_CASE("JsonObject::remove()") { obj.remove("a"); serializeJson(obj, result); REQUIRE("{\"b\":1,\"c\":2}" == result); - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2)); } SECTION("Remove middle") { obj.remove("b"); serializeJson(obj, result); REQUIRE("{\"a\":0,\"c\":2}" == result); - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2)); } SECTION("Remove last") { obj.remove("c"); serializeJson(obj, result); REQUIRE("{\"a\":0,\"b\":1}" == result); - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2)); - } - - SECTION("Release value string memory") { - obj["c"] = std::string("Copy me!"); - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(3) + JSON_STRING_SIZE(9)); - - obj.remove("c"); - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2)); - } - - SECTION("Release key string memory") { - obj[std::string("Copy me!")] = 42; - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(4) + JSON_STRING_SIZE(9)); - - obj.remove("Copy me!"); - - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(3)); - } - - SECTION("Release raw string memory") { - obj["c"] = serialized(std::string("Copy me!")); - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(3) + JSON_STRING_SIZE(8)); - - obj.remove("c"); - - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2)); } } diff --git a/test/JsonObject/subscript.cpp b/test/JsonObject/subscript.cpp index c430de9d..f673a9ee 100644 --- a/test/JsonObject/subscript.cpp +++ b/test/JsonObject/subscript.cpp @@ -141,22 +141,6 @@ TEST_CASE("JsonObject::operator[]") { REQUIRE(expectedSize <= doc.memoryUsage()); } - SECTION("should release string memory when overiding value") { - obj["hello"] = std::string("world"); - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6)); - - obj["hello"] = 42; - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1)); - } - - SECTION("should release nested array memory when overiding value") { - obj.createNestedArray("hello").add("world"); - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(1)); - - obj["hello"] = 42; - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1)); - } - SECTION("should ignore null key") { // object must have a value to make a call to strcmp() obj["dummy"] = 42; diff --git a/test/JsonVariant/CMakeLists.txt b/test/JsonVariant/CMakeLists.txt index 23bed048..c9ec9964 100644 --- a/test/JsonVariant/CMakeLists.txt +++ b/test/JsonVariant/CMakeLists.txt @@ -13,7 +13,6 @@ add_executable(JsonVariantTests or.cpp set.cpp subscript.cpp - to.cpp undefined.cpp ) diff --git a/test/JsonVariant/copy.cpp b/test/JsonVariant/copy.cpp index e79d3b53..b99b998d 100644 --- a/test/JsonVariant/copy.cpp +++ b/test/JsonVariant/copy.cpp @@ -83,23 +83,4 @@ TEST_CASE("JsonVariant::set(JsonVariant)") { REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8)); REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8)); } - - SECTION("releases string memory when replacing with null") { - var1.set(std::string("hello")); - REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(6)); - - var1.set(JsonVariant()); - - REQUIRE(doc1.memoryUsage() == 0); - } - - SECTION("releases string memory when replacing with iteger") { - var1.set(std::string("hello")); - REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(6)); - - var2.set(42); - var1.set(var2); - - REQUIRE(doc1.memoryUsage() == 0); - } } diff --git a/test/JsonVariant/set.cpp b/test/JsonVariant/set.cpp index 7a4ef2e9..b4973dd8 100644 --- a/test/JsonVariant/set.cpp +++ b/test/JsonVariant/set.cpp @@ -73,62 +73,6 @@ TEST_CASE("JsonVariant and strings") { } } -TEST_CASE("JsonVariant::set() should release string memory") { - DynamicJsonDocument doc; - JsonVariant variant = doc.to(); - - variant.set(std::string("hello")); - REQUIRE(doc.memoryUsage() == JSON_STRING_SIZE(6)); - - SECTION("int") { - variant.set(-42); - REQUIRE(doc.memoryUsage() == 0); - } - - SECTION("unsigned int") { - variant.set(42U); - REQUIRE(doc.memoryUsage() == 0); - } - - SECTION("bool") { - variant.set(true); - REQUIRE(doc.memoryUsage() == 0); - } - - SECTION("float") { - variant.set(3.14); - REQUIRE(doc.memoryUsage() == 0); - } - - SECTION("const char*") { - variant.set("hello"); - REQUIRE(doc.memoryUsage() == 0); - } - - SECTION("std::string") { - variant.set(std::string("X")); - REQUIRE(doc.memoryUsage() == JSON_STRING_SIZE(2)); - } - - SECTION("SerializedValue") { - variant.set(serialized("[42]")); - REQUIRE(doc.memoryUsage() == 0); - } - - SECTION("SerializedValue") { - variant.set(serialized(std::string("42"))); - REQUIRE(doc.memoryUsage() == JSON_STRING_SIZE(2)); - } - - SECTION("StringInMemoryPool") { - DeserializationError err = - deserializeJson(doc, std::string("{\"A\":\"hello\",\"A\":\"B\"}")); - REQUIRE(err == DeserializationError::Ok); - // it stores the key twice, but should release "hello" - REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(1) + 3 * JSON_STRING_SIZE(2)); - } -} - TEST_CASE("JsonVariant with not enough memory") { StaticJsonDocument<1> doc; diff --git a/test/JsonVariant/to.cpp b/test/JsonVariant/to.cpp deleted file mode 100644 index 49b76ceb..00000000 --- a/test/JsonVariant/to.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2018 -// MIT License - -#include -#include -#include - -static const char* null = 0; - -TEST_CASE("JsonVariant::to() releases string memory") { - DynamicJsonDocument doc; - JsonVariant variant = doc.to(); - - variant.set(std::string("hello")); - REQUIRE(doc.memoryUsage() == JSON_STRING_SIZE(6)); - - SECTION("JsonVariant") { - variant.to(); - REQUIRE(doc.memoryUsage() == 0); - } - - SECTION("JsonArray") { - variant.to(); - REQUIRE(doc.memoryUsage() == 0); - } - - SECTION("JsonObject") { - variant.to(); - REQUIRE(doc.memoryUsage() == 0); - } -} diff --git a/test/MemoryPool/allocString.cpp b/test/MemoryPool/allocString.cpp index 7955b0ea..1b9c801a 100644 --- a/test/MemoryPool/allocString.cpp +++ b/test/MemoryPool/allocString.cpp @@ -60,15 +60,6 @@ TEST_CASE("MemoryPool::allocFrozenString()") { REQUIRE(a->value == b->value); } - SECTION("Returns same address after freeString()") { - StringSlot *a = pool.allocFrozenString(1); - pool.freeString(a); - StringSlot *b = pool.allocFrozenString(1); - - REQUIRE(a == b); - REQUIRE(a->value == b->value); - } - SECTION("Can use full capacity when fresh") { StringSlot *a = pool.allocFrozenString(longestString); @@ -84,60 +75,3 @@ TEST_CASE("MemoryPool::allocFrozenString()") { REQUIRE(a != 0); } } - -TEST_CASE("MemoryPool::freeString()") { - const size_t poolCapacity = 512; - const size_t longestString = poolCapacity - sizeof(StringSlot); - char buffer[poolCapacity]; - MemoryPool pool(buffer, poolCapacity); - - static const size_t testStringSize = - (poolCapacity - sizeof(StringSlot) * 4 - sizeof(VariantSlot) * 4) / 4; - - SECTION("Restores full capacity") { - StringSlot *strings[4]; - VariantSlot *variants[4]; - - for (int i = 0; i < 4; i++) { - strings[i] = pool.allocFrozenString(testStringSize); - REQUIRE(strings[i] != 0); - variants[i] = pool.allocVariant(); - REQUIRE(variants[i] != 0); - } - - // In random order - pool.freeString(strings[2]); - pool.freeVariant(variants[3]); - pool.freeVariant(variants[0]); - pool.freeString(strings[0]); - pool.freeVariant(variants[1]); - pool.freeString(strings[1]); - pool.freeVariant(variants[2]); - pool.freeString(strings[3]); - - StringSlot *b = pool.allocFrozenString(longestString); - - REQUIRE(b != 0); - REQUIRE(b->size == longestString); - } - - SECTION("Move strings") { - StringSlot *a = pool.allocFrozenString(6); - strcpy(a->value, "hello"); - - StringSlot *b = pool.allocFrozenString(7); - strcpy(b->value, "world!"); - pool.freeString(a); - - REQUIRE(b->size == 7); - REQUIRE(b->value == std::string("world!")); - REQUIRE(a->value == b->value); - } - - SECTION("Accepts non-frozen string") { - StringSlot *a = pool.allocExpandableString(); - pool.freeString(a); - - REQUIRE(pool.size() == 0); - } -} diff --git a/test/MemoryPool/allocVariant.cpp b/test/MemoryPool/allocVariant.cpp index 75edd138..419f8863 100644 --- a/test/MemoryPool/allocVariant.cpp +++ b/test/MemoryPool/allocVariant.cpp @@ -21,16 +21,6 @@ TEST_CASE("MemoryPool::allocVariant()") { REQUIRE(s1 != s2); } - SECTION("Returns same pointer after freeSlot()") { - MemoryPool pool(buffer, sizeof(buffer)); - - VariantSlot* s1 = pool.allocVariant(); - pool.freeVariant(s1); - VariantSlot* s2 = pool.allocVariant(); - - REQUIRE(s1 == s2); - } - SECTION("Returns aligned pointers") { MemoryPool pool(buffer, sizeof(buffer)); diff --git a/test/MemoryPool/clear.cpp b/test/MemoryPool/clear.cpp index 89d72605..aff70485 100644 --- a/test/MemoryPool/clear.cpp +++ b/test/MemoryPool/clear.cpp @@ -28,56 +28,4 @@ TEST_CASE("MemoryPool::clear()") { REQUIRE(memoryPool.size() == 0); } - - SECTION("Purges variant cache") { - VariantSlot* a = memoryPool.allocVariant(); - REQUIRE(a != 0); - VariantSlot* b = memoryPool.allocVariant(); - REQUIRE(b != 0); - - // place slot a in the pool of free slots - memoryPool.freeVariant(a); - memoryPool.clear(); - - REQUIRE(memoryPool.size() == 0); - } - - SECTION("Purges string cache") { - StringSlot* a = memoryPool.allocFrozenString(10); - REQUIRE(a != 0); - StringSlot* b = memoryPool.allocFrozenString(10); - REQUIRE(b != 0); - - // place slot a in the pool of free slots - memoryPool.freeString(a); - memoryPool.clear(); - - REQUIRE(memoryPool.size() == 0); - } - - SECTION("Purges list of string") { - StringSlot* a = memoryPool.allocFrozenString(6); - REQUIRE(a != 0); - strcpy(a->value, "hello"); - - StringSlot* b = memoryPool.allocFrozenString(6); - REQUIRE(b != 0); - strcpy(b->value, "world"); - - memoryPool.clear(); // ACT! - - StringSlot* c = memoryPool.allocFrozenString(2); - REQUIRE(c != 0); - strcpy(c->value, "H"); - - StringSlot* d = memoryPool.allocFrozenString(2); - REQUIRE(d != 0); - strcpy(d->value, "W"); - - // if the memory pool keeps pointer to the old strings - // it will try to compact the strings - memoryPool.freeString(c); - - REQUIRE(d->value == std::string("W")); - } } diff --git a/test/MemoryPool/size.cpp b/test/MemoryPool/size.cpp index 9ab5831d..f6735df8 100644 --- a/test/MemoryPool/size.cpp +++ b/test/MemoryPool/size.cpp @@ -45,41 +45,6 @@ TEST_CASE("MemoryPool::size()") { REQUIRE(memoryPool.size() == 2 * JSON_STRING_SIZE(0)); } - SECTION("Decreases after freeVariant()") { - VariantSlot* a = memoryPool.allocVariant(); - VariantSlot* b = memoryPool.allocVariant(); - - memoryPool.freeVariant(b); - REQUIRE(memoryPool.size() == sizeof(VariantSlot)); - - memoryPool.freeVariant(a); - REQUIRE(memoryPool.size() == 0); - } - - SECTION("Decreases after calling freeString() in order") { - StringSlot* a = memoryPool.allocFrozenString(5); - REQUIRE(a != 0); - StringSlot* b = memoryPool.allocFrozenString(6); - REQUIRE(b != 0); - - memoryPool.freeString(b); - REQUIRE(memoryPool.size() == JSON_STRING_SIZE(5)); - memoryPool.freeString(a); - REQUIRE(memoryPool.size() == 0); - } - - SECTION("Decreases after calling freeString() in reverse order") { - StringSlot* a = memoryPool.allocFrozenString(5); - REQUIRE(a != 0); - StringSlot* b = memoryPool.allocFrozenString(6); - REQUIRE(b != 0); - - memoryPool.freeString(a); - REQUIRE(memoryPool.size() == JSON_STRING_SIZE(6)); - memoryPool.freeString(b); - REQUIRE(memoryPool.size() == 0); - } - SECTION("Doesn't grow when memory pool is full") { const size_t variantCount = sizeof(buffer) / sizeof(VariantSlot);