mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Restored the monotonic allocator
This commit is contained in:
		| @@ -5,6 +5,7 @@ HEAD | |||||||
| ---- | ---- | ||||||
|  |  | ||||||
| * Removed the automatic expansion of `DynamicJsonDocument`, it now has a fixed capacity. | * 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) | v6.6.0-beta (2018-11-13) | ||||||
| ----------- | ----------- | ||||||
| @@ -14,7 +15,7 @@ v6.6.0-beta (2018-11-13) | |||||||
| * Replaced `T JsonArray::get<T>(i)` with `JsonVariant JsonArray::get(i)` | * Replaced `T JsonArray::get<T>(i)` with `JsonVariant JsonArray::get(i)` | ||||||
| * Replaced `T JsonObject::get<T>(k)` with `JsonVariant JsonObject::get(k)` | * Replaced `T JsonObject::get<T>(k)` with `JsonVariant JsonObject::get(k)` | ||||||
| * Added `JSON_STRING_SIZE()` | * 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) | * Added `DeserializationError::code()` to be used in switch statements (issue #846) | ||||||
|  |  | ||||||
| v6.5.0-beta (2018-10-13) | v6.5.0-beta (2018-10-13) | ||||||
|   | |||||||
| @@ -42,8 +42,7 @@ inline JsonVariantData* arrayGet(const JsonArrayData* arr, size_t index) { | |||||||
|   return slot ? &slot->value : 0; |   return slot ? &slot->value : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline void arrayRemove(JsonArrayData* arr, VariantSlot* slot, | inline void arrayRemove(JsonArrayData* arr, VariantSlot* slot) { | ||||||
|                         MemoryPool* pool) { |  | ||||||
|   if (!arr || !slot) return; |   if (!arr || !slot) return; | ||||||
|  |  | ||||||
|   if (slot->prev) |   if (slot->prev) | ||||||
| @@ -54,12 +53,10 @@ inline void arrayRemove(JsonArrayData* arr, VariantSlot* slot, | |||||||
|     slot->next->prev = slot->prev; |     slot->next->prev = slot->prev; | ||||||
|   else |   else | ||||||
|     arr->tail = slot->prev; |     arr->tail = slot->prev; | ||||||
|  |  | ||||||
|   slotFree(slot, pool); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| inline void arrayRemove(JsonArrayData* arr, size_t index, MemoryPool* pool) { | inline void arrayRemove(JsonArrayData* arr, size_t index) { | ||||||
|   arrayRemove(arr, arrayGetSlot(arr, index), pool); |   arrayRemove(arr, arrayGetSlot(arr, index)); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline void arrayClear(JsonArrayData* arr) { | inline void arrayClear(JsonArrayData* arr) { | ||||||
| @@ -100,15 +97,4 @@ inline size_t arraySize(const JsonArrayData* arr) { | |||||||
|   if (!arr) return 0; |   if (!arr) return 0; | ||||||
|   return slotSize(arr->head); |   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 | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -76,8 +76,7 @@ inline void objectClear(JsonObjectData* obj) { | |||||||
|   obj->tail = 0; |   obj->tail = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline void objectRemove(JsonObjectData* obj, VariantSlot* slot, | inline void objectRemove(JsonObjectData* obj, VariantSlot* slot) { | ||||||
|                          MemoryPool* pool) { |  | ||||||
|   if (!obj) return; |   if (!obj) return; | ||||||
|   if (!slot) return; |   if (!slot) return; | ||||||
|   if (slot->prev) |   if (slot->prev) | ||||||
| @@ -88,8 +87,6 @@ inline void objectRemove(JsonObjectData* obj, VariantSlot* slot, | |||||||
|     slot->next->prev = slot->prev; |     slot->next->prev = slot->prev; | ||||||
|   else |   else | ||||||
|     obj->tail = slot->prev; |     obj->tail = slot->prev; | ||||||
|  |  | ||||||
|   slotFree(slot, pool); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| inline size_t objectSize(const JsonObjectData* obj) { | inline size_t objectSize(const JsonObjectData* obj) { | ||||||
|   | |||||||
| @@ -61,17 +61,4 @@ inline size_t slotSize(const VariantSlot* var) { | |||||||
|   } |   } | ||||||
|   return n; |   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 | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -12,25 +12,6 @@ | |||||||
| #include "ObjectFunctions.hpp" | #include "ObjectFunctions.hpp" | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | 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 <typename T> | template <typename T> | ||||||
| inline T variantAsIntegral(const JsonVariantData* var) { | inline T variantAsIntegral(const JsonVariantData* var) { | ||||||
|   if (!var) return 0; |   if (!var) return 0; | ||||||
| @@ -116,30 +97,23 @@ inline const JsonObjectData* variantAsObject(const JsonVariantData* var) { | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantSetBoolean(JsonVariantData* var, bool value, | inline bool variantSetBoolean(JsonVariantData* var, bool value) { | ||||||
|                               MemoryPool* pool) { |  | ||||||
|   if (!var) return false; |   if (!var) return false; | ||||||
|   variantFree(var, pool); |  | ||||||
|   var->type = JSON_BOOLEAN; |   var->type = JSON_BOOLEAN; | ||||||
|   var->content.asInteger = static_cast<JsonUInt>(value); |   var->content.asInteger = static_cast<JsonUInt>(value); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantSetFloat(JsonVariantData* var, JsonFloat value, | inline bool variantSetFloat(JsonVariantData* var, JsonFloat value) { | ||||||
|                             MemoryPool* pool) { |  | ||||||
|   if (!var) return false; |   if (!var) return false; | ||||||
|   variantFree(var, pool); |  | ||||||
|   var->type = JSON_FLOAT; |   var->type = JSON_FLOAT; | ||||||
|   var->content.asFloat = value; |   var->content.asFloat = value; | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| inline bool variantSetSignedInteger(JsonVariantData* var, T value, | inline bool variantSetSignedInteger(JsonVariantData* var, T value) { | ||||||
|                                     MemoryPool* pool) { |  | ||||||
|   if (!var) return false; |   if (!var) return false; | ||||||
|   variantFree(var, pool); |  | ||||||
|  |  | ||||||
|   if (value >= 0) { |   if (value >= 0) { | ||||||
|     var->type = JSON_POSITIVE_INTEGER; |     var->type = JSON_POSITIVE_INTEGER; | ||||||
|     var->content.asInteger = static_cast<JsonUInt>(value); |     var->content.asInteger = static_cast<JsonUInt>(value); | ||||||
| @@ -150,20 +124,16 @@ inline bool variantSetSignedInteger(JsonVariantData* var, T value, | |||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantSetUnsignedInteger(JsonVariantData* var, JsonUInt value, | inline bool variantSetUnsignedInteger(JsonVariantData* var, JsonUInt value) { | ||||||
|                                       MemoryPool* pool) { |  | ||||||
|   if (!var) return false; |   if (!var) return false; | ||||||
|   variantFree(var, pool); |  | ||||||
|   var->type = JSON_POSITIVE_INTEGER; |   var->type = JSON_POSITIVE_INTEGER; | ||||||
|   var->content.asInteger = static_cast<JsonUInt>(value); |   var->content.asInteger = static_cast<JsonUInt>(value); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantSetLinkedRaw(JsonVariantData* var, | inline bool variantSetLinkedRaw(JsonVariantData* var, | ||||||
|                                 SerializedValue<const char*> value, |                                 SerializedValue<const char*> value) { | ||||||
|                                 MemoryPool* pool) { |  | ||||||
|   if (!var) return false; |   if (!var) return false; | ||||||
|   variantFree(var, pool); |  | ||||||
|   var->type = JSON_LINKED_RAW; |   var->type = JSON_LINKED_RAW; | ||||||
|   var->content.asRaw.data = value.data(); |   var->content.asRaw.data = value.data(); | ||||||
|   var->content.asRaw.size = value.size(); |   var->content.asRaw.size = value.size(); | ||||||
| @@ -174,7 +144,6 @@ template <typename T> | |||||||
| inline bool variantSetOwnedRaw(JsonVariantData* var, SerializedValue<T> value, | inline bool variantSetOwnedRaw(JsonVariantData* var, SerializedValue<T> value, | ||||||
|                                MemoryPool* pool) { |                                MemoryPool* pool) { | ||||||
|   if (!var) return false; |   if (!var) return false; | ||||||
|   variantFree(var, pool); |  | ||||||
|   StringSlot* slot = makeString(value.data(), value.size()).save(pool); |   StringSlot* slot = makeString(value.data(), value.size()).save(pool); | ||||||
|   if (slot) { |   if (slot) { | ||||||
|     var->type = JSON_OWNED_RAW; |     var->type = JSON_OWNED_RAW; | ||||||
| @@ -189,7 +158,6 @@ inline bool variantSetOwnedRaw(JsonVariantData* var, SerializedValue<T> value, | |||||||
| template <typename T> | template <typename T> | ||||||
| inline bool variantSetString(JsonVariantData* var, T value, MemoryPool* pool) { | inline bool variantSetString(JsonVariantData* var, T value, MemoryPool* pool) { | ||||||
|   if (!var) return false; |   if (!var) return false; | ||||||
|   variantFree(var, pool); |  | ||||||
|   StringSlot* slot = value.save(pool); |   StringSlot* slot = value.save(pool); | ||||||
|   if (slot) { |   if (slot) { | ||||||
|     var->type = JSON_OWNED_STRING; |     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, | inline bool variantSetOwnedString(JsonVariantData* var, StringSlot* slot) { | ||||||
|                                   MemoryPool* pool) { |  | ||||||
|   if (!var) return false; |   if (!var) return false; | ||||||
|   variantFree(var, pool); |  | ||||||
|   var->type = JSON_OWNED_STRING; |   var->type = JSON_OWNED_STRING; | ||||||
|   var->content.asOwnedString = slot; |   var->content.asOwnedString = slot; | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantSetString(JsonVariantData* var, const char* value, | inline bool variantSetString(JsonVariantData* var, const char* value) { | ||||||
|                              MemoryPool* pool) { |  | ||||||
|   if (!var) return false; |   if (!var) return false; | ||||||
|   variantFree(var, pool); |  | ||||||
|   var->type = JSON_LINKED_STRING; |   var->type = JSON_LINKED_STRING; | ||||||
|   var->content.asString = value; |   var->content.asString = value; | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline void variantSetNull(JsonVariantData* var, MemoryPool* pool) { | inline void variantSetNull(JsonVariantData* var) { | ||||||
|   if (!var) return; |   if (!var) return; | ||||||
|   variantFree(var, pool); |  | ||||||
|   var->type = JSON_NULL; |   var->type = JSON_NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonArrayData* variantToArray(JsonVariantData* var, MemoryPool* pool) { | inline JsonArrayData* variantToArray(JsonVariantData* var) { | ||||||
|   if (!var) return 0; |   if (!var) return 0; | ||||||
|   variantFree(var, pool); |  | ||||||
|   var->type = JSON_ARRAY; |   var->type = JSON_ARRAY; | ||||||
|   var->content.asArray.head = 0; |   var->content.asArray.head = 0; | ||||||
|   var->content.asArray.tail = 0; |   var->content.asArray.tail = 0; | ||||||
|   return &var->content.asArray; |   return &var->content.asArray; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonObjectData* variantToObject(JsonVariantData* var, MemoryPool* pool) { | inline JsonObjectData* variantToObject(JsonVariantData* var) { | ||||||
|   if (!var) return 0; |   if (!var) return 0; | ||||||
|   variantFree(var, pool); |  | ||||||
|   var->type = JSON_OBJECT; |   var->type = JSON_OBJECT; | ||||||
|   var->content.asObject.head = 0; |   var->content.asObject.head = 0; | ||||||
|   var->content.asObject.tail = 0; |   var->content.asObject.tail = 0; | ||||||
| @@ -247,16 +208,14 @@ inline bool variantCopy(JsonVariantData* dst, const JsonVariantData* src, | |||||||
|                         MemoryPool* pool) { |                         MemoryPool* pool) { | ||||||
|   if (!dst) return false; |   if (!dst) return false; | ||||||
|   if (!src) { |   if (!src) { | ||||||
|     variantFree(dst, pool); |  | ||||||
|     dst->type = JSON_NULL; |     dst->type = JSON_NULL; | ||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
|   switch (src->type) { |   switch (src->type) { | ||||||
|     case JSON_ARRAY: |     case JSON_ARRAY: | ||||||
|       return arrayCopy(variantToArray(dst, pool), &src->content.asArray, pool); |       return arrayCopy(variantToArray(dst), &src->content.asArray, pool); | ||||||
|     case JSON_OBJECT: |     case JSON_OBJECT: | ||||||
|       return objectCopy(variantToObject(dst, pool), &src->content.asObject, |       return objectCopy(variantToObject(dst), &src->content.asObject, pool); | ||||||
|                         pool); |  | ||||||
|     case JSON_OWNED_STRING: |     case JSON_OWNED_STRING: | ||||||
|       return variantSetString( |       return variantSetString( | ||||||
|           dst, makeString(src->content.asOwnedString->value), pool); |           dst, makeString(src->content.asOwnedString->value), pool); | ||||||
| @@ -266,7 +225,6 @@ inline bool variantCopy(JsonVariantData* dst, const JsonVariantData* src, | |||||||
|                                            src->content.asOwnedRaw->size), |                                            src->content.asOwnedRaw->size), | ||||||
|                                 pool); |                                 pool); | ||||||
|     default: |     default: | ||||||
|       variantFree(dst, pool); |  | ||||||
|       // caution: don't override keyIsOwned |       // caution: don't override keyIsOwned | ||||||
|       dst->type = src->type; |       dst->type = src->type; | ||||||
|       dst->content = src->content; |       dst->content = src->content; | ||||||
|   | |||||||
| @@ -197,12 +197,12 @@ class JsonArray : public JsonArrayProxy<JsonArrayData>, public Visitable { | |||||||
|  |  | ||||||
|   // Removes element at specified position. |   // Removes element at specified position. | ||||||
|   FORCE_INLINE void remove(iterator it) const { |   FORCE_INLINE void remove(iterator it) const { | ||||||
|     arrayRemove(_data, it.internal(), _memoryPool); |     arrayRemove(_data, it.internal()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Removes element at specified index. |   // Removes element at specified index. | ||||||
|   FORCE_INLINE void remove(size_t index) const { |   FORCE_INLINE void remove(size_t index) const { | ||||||
|     arrayRemove(_data, index, _memoryPool); |     arrayRemove(_data, index); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename Visitor> |   template <typename Visitor> | ||||||
|   | |||||||
| @@ -227,7 +227,7 @@ class JsonObject : public JsonObjectProxy<JsonObjectData>, public Visitable { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE void remove(iterator it) const { |   FORCE_INLINE void remove(iterator it) const { | ||||||
|     objectRemove(_data, it.internal(), _memoryPool); |     objectRemove(_data, it.internal()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Removes the specified key and the associated value. |   // Removes the specified key and the associated value. | ||||||
| @@ -282,7 +282,7 @@ class JsonObject : public JsonObjectProxy<JsonObjectData>, public Visitable { | |||||||
|  |  | ||||||
|   template <typename TStringRef> |   template <typename TStringRef> | ||||||
|   FORCE_INLINE void remove_impl(TStringRef key) const { |   FORCE_INLINE void remove_impl(TStringRef key) const { | ||||||
|     objectRemove(_data, objectFindSlot(_data, key), _memoryPool); |     objectRemove(_data, objectFindSlot(_data, key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   MemoryPool* _memoryPool; |   MemoryPool* _memoryPool; | ||||||
|   | |||||||
| @@ -133,7 +133,7 @@ class JsonVariant : public JsonVariantProxy<JsonVariantData>, | |||||||
|  |  | ||||||
|   // set(bool value) |   // set(bool value) | ||||||
|   FORCE_INLINE bool set(bool value) const { |   FORCE_INLINE bool set(bool value) const { | ||||||
|     return variantSetBoolean(_data, value, _memoryPool); |     return variantSetBoolean(_data, value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // set(double value); |   // set(double value); | ||||||
| @@ -142,7 +142,7 @@ class JsonVariant : public JsonVariantProxy<JsonVariantData>, | |||||||
|   FORCE_INLINE bool set( |   FORCE_INLINE bool set( | ||||||
|       T value, |       T value, | ||||||
|       typename enable_if<is_floating_point<T>::value>::type * = 0) const { |       typename enable_if<is_floating_point<T>::value>::type * = 0) const { | ||||||
|     return variantSetFloat(_data, static_cast<JsonFloat>(value), _memoryPool); |     return variantSetFloat(_data, static_cast<JsonFloat>(value)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // set(char) |   // set(char) | ||||||
| @@ -155,7 +155,7 @@ class JsonVariant : public JsonVariantProxy<JsonVariantData>, | |||||||
|       T value, |       T value, | ||||||
|       typename enable_if<is_integral<T>::value && is_signed<T>::value>::type * = |       typename enable_if<is_integral<T>::value && is_signed<T>::value>::type * = | ||||||
|           0) const { |           0) const { | ||||||
|     return variantSetSignedInteger(_data, value, _memoryPool); |     return variantSetSignedInteger(_data, value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // set(unsigned short) |   // set(unsigned short) | ||||||
| @@ -165,13 +165,12 @@ class JsonVariant : public JsonVariantProxy<JsonVariantData>, | |||||||
|   FORCE_INLINE bool set( |   FORCE_INLINE bool set( | ||||||
|       T value, typename enable_if<is_integral<T>::value && |       T value, typename enable_if<is_integral<T>::value && | ||||||
|                                   is_unsigned<T>::value>::type * = 0) const { |                                   is_unsigned<T>::value>::type * = 0) const { | ||||||
|     return variantSetUnsignedInteger(_data, static_cast<JsonUInt>(value), |     return variantSetUnsignedInteger(_data, static_cast<JsonUInt>(value)); | ||||||
|                                      _memoryPool); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // set(SerializedValue<const char *>) |   // set(SerializedValue<const char *>) | ||||||
|   FORCE_INLINE bool set(SerializedValue<const char *> value) const { |   FORCE_INLINE bool set(SerializedValue<const char *> value) const { | ||||||
|     return variantSetLinkedRaw(_data, value, _memoryPool); |     return variantSetLinkedRaw(_data, value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // set(SerializedValue<std::string>) |   // set(SerializedValue<std::string>) | ||||||
| @@ -202,15 +201,15 @@ class JsonVariant : public JsonVariantProxy<JsonVariantData>, | |||||||
|  |  | ||||||
|   // set(const char*); |   // set(const char*); | ||||||
|   FORCE_INLINE bool set(const char *value) const { |   FORCE_INLINE bool set(const char *value) const { | ||||||
|     return variantSetString(_data, value, _memoryPool); |     return variantSetString(_data, value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // for internal use only |   // for internal use only | ||||||
|   FORCE_INLINE bool set(StringInMemoryPool value) const { |   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 { |   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; |   bool set(JsonVariantConst value) const; | ||||||
|   | |||||||
| @@ -53,19 +53,19 @@ JsonVariant::as() const { | |||||||
| template <typename T> | template <typename T> | ||||||
| inline typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type | inline typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type | ||||||
| JsonVariant::to() const { | JsonVariant::to() const { | ||||||
|   return JsonArray(_memoryPool, variantToArray(_data, _memoryPool)); |   return JsonArray(_memoryPool, variantToArray(_data)); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type | typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type | ||||||
| JsonVariant::to() const { | JsonVariant::to() const { | ||||||
|   return JsonObject(_memoryPool, variantToObject(_data, _memoryPool)); |   return JsonObject(_memoryPool, variantToObject(_data)); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type | typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type | ||||||
| JsonVariant::to() const { | JsonVariant::to() const { | ||||||
|   variantSetNull(_data, _memoryPool); |   variantSetNull(_data); | ||||||
|   return *this; |   return *this; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ | |||||||
| #include "../Strings/StringInMemoryPool.hpp" | #include "../Strings/StringInMemoryPool.hpp" | ||||||
| #include "Alignment.hpp" | #include "Alignment.hpp" | ||||||
| #include "MemoryPool.hpp" | #include "MemoryPool.hpp" | ||||||
| #include "SlotList.hpp" |  | ||||||
| #include "StringSlot.hpp" | #include "StringSlot.hpp" | ||||||
| #include "VariantSlot.hpp" | #include "VariantSlot.hpp" | ||||||
|  |  | ||||||
| @@ -60,24 +59,11 @@ class MemoryPool { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t size() const { |   size_t size() const { | ||||||
|     return allocated_bytes() - _freeVariants.size() - _freeStrings.size(); |     return size_t(_left - _begin + _end - _right); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   VariantSlot* allocVariant() { |   VariantSlot* allocVariant() { | ||||||
|     VariantSlot* s = _freeVariants.pop(); |     return allocRight<VariantSlot>(); | ||||||
|     if (s) return s; |  | ||||||
|     return s ? s : allocRight<VariantSlot>(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void freeVariant(VariantSlot* slot) { |  | ||||||
|     freeVariantSlot(slot); |  | ||||||
|     compactRightSide(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void freeString(StringSlot* slot) { |  | ||||||
|     freeStringSlot(slot); |  | ||||||
|     compactLeftSide(slot->value, slot->size); |  | ||||||
|     compactRightSide(); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   StringSlot* allocFrozenString(size_t n) { |   StringSlot* allocFrozenString(size_t n) { | ||||||
| @@ -88,7 +74,6 @@ class MemoryPool { | |||||||
|     s->value = _left; |     s->value = _left; | ||||||
|     s->size = n; |     s->size = n; | ||||||
|     _left += n; |     _left += n; | ||||||
|     _usedString.push(s); |  | ||||||
|     checkInvariants(); |     checkInvariants(); | ||||||
|  |  | ||||||
|     return s; |     return s; | ||||||
| @@ -100,7 +85,6 @@ class MemoryPool { | |||||||
|  |  | ||||||
|     s->value = _left; |     s->value = _left; | ||||||
|     s->size = size_t(_right - _left); |     s->size = size_t(_right - _left); | ||||||
|     _usedString.push(s); |  | ||||||
|     _left = _right; |     _left = _right; | ||||||
|  |  | ||||||
|     checkInvariants(); |     checkInvariants(); | ||||||
| @@ -116,9 +100,6 @@ class MemoryPool { | |||||||
|   void clear() { |   void clear() { | ||||||
|     _left = _begin; |     _left = _begin; | ||||||
|     _right = _end; |     _right = _end; | ||||||
|     _freeVariants.clear(); |  | ||||||
|     _freeStrings.clear(); |  | ||||||
|     _usedString.clear(); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool canAlloc(size_t bytes) const { |   bool canAlloc(size_t bytes) const { | ||||||
| @@ -146,50 +127,10 @@ class MemoryPool { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   size_t allocated_bytes() const { |  | ||||||
|     return size_t(_left - _begin + _end - _right); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   StringSlot* allocStringSlot() { |   StringSlot* allocStringSlot() { | ||||||
|     StringSlot* s = _freeStrings.pop(); |  | ||||||
|     if (s) return s; |  | ||||||
|     return allocRight<StringSlot>(); |     return allocRight<StringSlot>(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   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() { |   void checkInvariants() { | ||||||
|     ARDUINOJSON_ASSERT(_begin <= _left); |     ARDUINOJSON_ASSERT(_begin <= _left); | ||||||
|     ARDUINOJSON_ASSERT(_left <= _right); |     ARDUINOJSON_ASSERT(_left <= _right); | ||||||
| @@ -198,9 +139,6 @@ class MemoryPool { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   char *_begin, *_left, *_right, *_end; |   char *_begin, *_left, *_right, *_end; | ||||||
|   SlotList<VariantSlot> _freeVariants; |  | ||||||
|   SlotList<StringSlot> _freeStrings; |  | ||||||
|   SlotList<StringSlot> _usedString; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -1,67 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include <stddef.h>  // for size_t |  | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { |  | ||||||
|  |  | ||||||
| template <typename TSlot> |  | ||||||
| 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<const TSlot *>(slot)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   template <typename Functor> |  | ||||||
|   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 |  | ||||||
| @@ -116,18 +116,6 @@ TEST_CASE("DynamicJsonDocument") { | |||||||
|       REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(2)); |       REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(2)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     SECTION("Decreases after removing value from array") { |  | ||||||
|       JsonArray arr = doc.to<JsonArray>(); |  | ||||||
|       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") { |     SECTION("Increases after adding value to object") { | ||||||
|       JsonObject obj = doc.to<JsonObject>(); |       JsonObject obj = doc.to<JsonObject>(); | ||||||
|  |  | ||||||
| @@ -137,37 +125,5 @@ TEST_CASE("DynamicJsonDocument") { | |||||||
|       obj["b"] = 2; |       obj["b"] = 2; | ||||||
|       REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2)); |       REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     SECTION("Decreases after removing value from object") { |  | ||||||
|       JsonObject obj = doc.to<JsonObject>(); |  | ||||||
|       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<JsonArray>(); |  | ||||||
|       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<JsonObject>(); |  | ||||||
|       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)); |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -22,17 +22,4 @@ TEST_CASE("JsonObject::createNestedObject()") { | |||||||
|     obj.createNestedObject(vla); |     obj.createNestedObject(vla); | ||||||
|   } |   } | ||||||
| #endif | #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)); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -19,47 +19,18 @@ TEST_CASE("JsonObject::remove()") { | |||||||
|       obj.remove("a"); |       obj.remove("a"); | ||||||
|       serializeJson(obj, result); |       serializeJson(obj, result); | ||||||
|       REQUIRE("{\"b\":1,\"c\":2}" == result); |       REQUIRE("{\"b\":1,\"c\":2}" == result); | ||||||
|       REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2)); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     SECTION("Remove middle") { |     SECTION("Remove middle") { | ||||||
|       obj.remove("b"); |       obj.remove("b"); | ||||||
|       serializeJson(obj, result); |       serializeJson(obj, result); | ||||||
|       REQUIRE("{\"a\":0,\"c\":2}" == result); |       REQUIRE("{\"a\":0,\"c\":2}" == result); | ||||||
|       REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(2)); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     SECTION("Remove last") { |     SECTION("Remove last") { | ||||||
|       obj.remove("c"); |       obj.remove("c"); | ||||||
|       serializeJson(obj, result); |       serializeJson(obj, result); | ||||||
|       REQUIRE("{\"a\":0,\"b\":1}" == 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)); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -141,22 +141,6 @@ TEST_CASE("JsonObject::operator[]") { | |||||||
|     REQUIRE(expectedSize <= doc.memoryUsage()); |     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") { |   SECTION("should ignore null key") { | ||||||
|     // object must have a value to make a call to strcmp() |     // object must have a value to make a call to strcmp() | ||||||
|     obj["dummy"] = 42; |     obj["dummy"] = 42; | ||||||
|   | |||||||
| @@ -13,7 +13,6 @@ add_executable(JsonVariantTests | |||||||
| 	or.cpp | 	or.cpp | ||||||
| 	set.cpp | 	set.cpp | ||||||
| 	subscript.cpp | 	subscript.cpp | ||||||
| 	to.cpp |  | ||||||
| 	undefined.cpp | 	undefined.cpp | ||||||
| ) | ) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -83,23 +83,4 @@ TEST_CASE("JsonVariant::set(JsonVariant)") { | |||||||
|     REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8)); |     REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8)); | ||||||
|     REQUIRE(doc2.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); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -73,62 +73,6 @@ TEST_CASE("JsonVariant and strings") { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("JsonVariant::set() should release string memory") { |  | ||||||
|   DynamicJsonDocument doc; |  | ||||||
|   JsonVariant variant = doc.to<JsonVariant>(); |  | ||||||
|  |  | ||||||
|   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<const char*>") { |  | ||||||
|     variant.set(serialized("[42]")); |  | ||||||
|     REQUIRE(doc.memoryUsage() == 0); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("SerializedValue<std::string>") { |  | ||||||
|     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") { | TEST_CASE("JsonVariant with not enough memory") { | ||||||
|   StaticJsonDocument<1> doc; |   StaticJsonDocument<1> doc; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,32 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2018 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #include <ArduinoJson.h> |  | ||||||
| #include <stdint.h> |  | ||||||
| #include <catch.hpp> |  | ||||||
|  |  | ||||||
| static const char* null = 0; |  | ||||||
|  |  | ||||||
| TEST_CASE("JsonVariant::to<T>() releases string memory") { |  | ||||||
|   DynamicJsonDocument doc; |  | ||||||
|   JsonVariant variant = doc.to<JsonVariant>(); |  | ||||||
|  |  | ||||||
|   variant.set(std::string("hello")); |  | ||||||
|   REQUIRE(doc.memoryUsage() == JSON_STRING_SIZE(6)); |  | ||||||
|  |  | ||||||
|   SECTION("JsonVariant") { |  | ||||||
|     variant.to<JsonVariant>(); |  | ||||||
|     REQUIRE(doc.memoryUsage() == 0); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("JsonArray") { |  | ||||||
|     variant.to<JsonArray>(); |  | ||||||
|     REQUIRE(doc.memoryUsage() == 0); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("JsonObject") { |  | ||||||
|     variant.to<JsonObject>(); |  | ||||||
|     REQUIRE(doc.memoryUsage() == 0); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -60,15 +60,6 @@ TEST_CASE("MemoryPool::allocFrozenString()") { | |||||||
|     REQUIRE(a->value == b->value); |     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") { |   SECTION("Can use full capacity when fresh") { | ||||||
|     StringSlot *a = pool.allocFrozenString(longestString); |     StringSlot *a = pool.allocFrozenString(longestString); | ||||||
|  |  | ||||||
| @@ -84,60 +75,3 @@ TEST_CASE("MemoryPool::allocFrozenString()") { | |||||||
|     REQUIRE(a != 0); |     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); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -21,16 +21,6 @@ TEST_CASE("MemoryPool::allocVariant()") { | |||||||
|     REQUIRE(s1 != s2); |     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") { |   SECTION("Returns aligned pointers") { | ||||||
|     MemoryPool pool(buffer, sizeof(buffer)); |     MemoryPool pool(buffer, sizeof(buffer)); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -28,56 +28,4 @@ TEST_CASE("MemoryPool::clear()") { | |||||||
|  |  | ||||||
|     REQUIRE(memoryPool.size() == 0); |     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")); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -45,41 +45,6 @@ TEST_CASE("MemoryPool::size()") { | |||||||
|     REQUIRE(memoryPool.size() == 2 * JSON_STRING_SIZE(0)); |     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") { |   SECTION("Doesn't grow when memory pool is full") { | ||||||
|     const size_t variantCount = sizeof(buffer) / sizeof(VariantSlot); |     const size_t variantCount = sizeof(buffer) / sizeof(VariantSlot); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user