mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 08:42:39 +01:00 
			
		
		
		
	Removed the indirection via StringSlot
This commit is contained in:
		| @@ -7,8 +7,8 @@ project(ArduinoJson) | |||||||
|  |  | ||||||
| enable_testing() | enable_testing() | ||||||
|  |  | ||||||
|  | add_definitions(-DARDUINOJSON_DEBUG) | ||||||
| if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") | if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") | ||||||
| 	add_definitions(-DARDUINOJSON_DEBUG) |  | ||||||
| 	add_compile_options(-g -O0) | 	add_compile_options(-g -O0) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,4 +1,6 @@ | |||||||
| Version,Date,JsonParserExample,JsonGeneratorExample | Version,Date,JsonParserExample,JsonGeneratorExample | ||||||
|  | v6.6.0-beta-6-g8217012,2018-11-27,7204,7630 | ||||||
|  | v6.6.0-beta-5-g13cc610,2018-11-27,7264,7850 | ||||||
| v6.6.0-beta-2-g2bd280d,2018-11-16,7872,8446 | v6.6.0-beta-2-g2bd280d,2018-11-16,7872,8446 | ||||||
| v6.6.0-beta,2018-11-13,8380,8916 | v6.6.0-beta,2018-11-13,8380,8916 | ||||||
| v6.5.0-beta,2018-10-13,7384,7874 | v6.5.0-beta,2018-10-13,7384,7874 | ||||||
|   | |||||||
| 
 | 
| @@ -48,8 +48,6 @@ union JsonVariantContent { | |||||||
|   JsonArrayData asArray; |   JsonArrayData asArray; | ||||||
|   JsonObjectData asObject; |   JsonObjectData asObject; | ||||||
|   const char *asString; |   const char *asString; | ||||||
|   struct StringSlot *asOwnedString; |  | ||||||
|   struct StringSlot *asOwnedRaw; |  | ||||||
|   struct { |   struct { | ||||||
|     const char *data; |     const char *data; | ||||||
|     size_t size; |     size_t size; | ||||||
|   | |||||||
| @@ -103,9 +103,9 @@ inline bool objectCopy(JsonObjectData* dst, const JsonObjectData* src, | |||||||
|   for (VariantSlot* s = src->head; s; s = s->next) { |   for (VariantSlot* s = src->head; s; s = s->next) { | ||||||
|     JsonVariantData* var; |     JsonVariantData* var; | ||||||
|     if (s->value.keyIsOwned) |     if (s->value.keyIsOwned) | ||||||
|       var = objectAdd(dst, ZeroTerminatedRamString(s->ownedKey->value), pool); |       var = objectAdd(dst, ZeroTerminatedRamString(s->key), pool); | ||||||
|     else |     else | ||||||
|       var = objectAdd(dst, ZeroTerminatedRamStringConst(s->linkedKey), pool); |       var = objectAdd(dst, ZeroTerminatedRamStringConst(s->key), pool); | ||||||
|     if (!variantCopy(var, &s->value, pool)) return false; |     if (!variantCopy(var, &s->value, pool)) return false; | ||||||
|   } |   } | ||||||
|   return true; |   return true; | ||||||
|   | |||||||
| @@ -13,28 +13,28 @@ namespace ARDUINOJSON_NAMESPACE { | |||||||
|  |  | ||||||
| template <typename TKey> | template <typename TKey> | ||||||
| inline bool slotSetKey(VariantSlot* var, TKey key, MemoryPool* pool) { | inline bool slotSetKey(VariantSlot* var, TKey key, MemoryPool* pool) { | ||||||
|   StringSlot* slot = key.save(pool); |   char* dup = key.save(pool); | ||||||
|   if (!slot) return false; |   if (!dup) return false; | ||||||
|   var->ownedKey = slot; |   var->key = dup; | ||||||
|   var->value.keyIsOwned = true; |   var->value.keyIsOwned = true; | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool slotSetKey(VariantSlot* var, ZeroTerminatedRamStringConst key, | inline bool slotSetKey(VariantSlot* var, ZeroTerminatedRamStringConst key, | ||||||
|                        MemoryPool*) { |                        MemoryPool*) { | ||||||
|   var->linkedKey = key.c_str(); |   var->key = key.c_str(); | ||||||
|   var->value.keyIsOwned = false; |   var->value.keyIsOwned = false; | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool slotSetKey(VariantSlot* var, StringInMemoryPool key, MemoryPool*) { | inline bool slotSetKey(VariantSlot* var, StringInMemoryPool key, MemoryPool*) { | ||||||
|   var->ownedKey = key.slot(); |   var->key = key.c_str(); | ||||||
|   var->value.keyIsOwned = true; |   var->value.keyIsOwned = true; | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline const char* slotGetKey(const VariantSlot* var) { | inline const char* slotGetKey(const VariantSlot* var) { | ||||||
|   return var->value.keyIsOwned ? var->ownedKey->value : var->linkedKey; |   return var->key; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline const VariantSlot* slotAdvance(const VariantSlot* var, size_t distance) { | inline const VariantSlot* slotAdvance(const VariantSlot* var, size_t distance) { | ||||||
|   | |||||||
| @@ -22,9 +22,8 @@ inline T variantAsIntegral(const JsonVariantData* var) { | |||||||
|     case JSON_NEGATIVE_INTEGER: |     case JSON_NEGATIVE_INTEGER: | ||||||
|       return T(~var->content.asInteger + 1); |       return T(~var->content.asInteger + 1); | ||||||
|     case JSON_LINKED_STRING: |     case JSON_LINKED_STRING: | ||||||
|       return parseInteger<T>(var->content.asString); |  | ||||||
|     case JSON_OWNED_STRING: |     case JSON_OWNED_STRING: | ||||||
|       return parseInteger<T>(var->content.asOwnedString->value); |       return parseInteger<T>(var->content.asString); | ||||||
|     case JSON_FLOAT: |     case JSON_FLOAT: | ||||||
|       return T(var->content.asFloat); |       return T(var->content.asFloat); | ||||||
|     default: |     default: | ||||||
| @@ -47,9 +46,8 @@ inline T variantAsFloat(const JsonVariantData* var) { | |||||||
|     case JSON_NEGATIVE_INTEGER: |     case JSON_NEGATIVE_INTEGER: | ||||||
|       return -static_cast<T>(var->content.asInteger); |       return -static_cast<T>(var->content.asInteger); | ||||||
|     case JSON_LINKED_STRING: |     case JSON_LINKED_STRING: | ||||||
|       return parseFloat<T>(var->content.asString); |  | ||||||
|     case JSON_OWNED_STRING: |     case JSON_OWNED_STRING: | ||||||
|       return parseFloat<T>(var->content.asOwnedString->value); |       return parseFloat<T>(var->content.asString); | ||||||
|     case JSON_FLOAT: |     case JSON_FLOAT: | ||||||
|       return static_cast<T>(var->content.asFloat); |       return static_cast<T>(var->content.asFloat); | ||||||
|     default: |     default: | ||||||
| @@ -61,9 +59,8 @@ inline const char* variantAsString(const JsonVariantData* var) { | |||||||
|   if (!var) return 0; |   if (!var) return 0; | ||||||
|   switch (var->type) { |   switch (var->type) { | ||||||
|     case JSON_LINKED_STRING: |     case JSON_LINKED_STRING: | ||||||
|       return var->content.asString; |  | ||||||
|     case JSON_OWNED_STRING: |     case JSON_OWNED_STRING: | ||||||
|       return var->content.asOwnedString->value; |       return var->content.asString; | ||||||
|     default: |     default: | ||||||
|       return 0; |       return 0; | ||||||
|   } |   } | ||||||
| @@ -144,10 +141,11 @@ 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; | ||||||
|   StringSlot* slot = makeString(value.data(), value.size()).save(pool); |   char* dup = makeString(value.data(), value.size()).save(pool); | ||||||
|   if (slot) { |   if (dup) { | ||||||
|     var->type = JSON_OWNED_RAW; |     var->type = JSON_OWNED_RAW; | ||||||
|     var->content.asOwnedRaw = slot; |     var->content.asRaw.data = dup; | ||||||
|  |     var->content.asRaw.size = value.size(); | ||||||
|     return true; |     return true; | ||||||
|   } else { |   } else { | ||||||
|     var->type = JSON_NULL; |     var->type = JSON_NULL; | ||||||
| @@ -158,10 +156,10 @@ 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; | ||||||
|   StringSlot* slot = value.save(pool); |   char* dup = value.save(pool); | ||||||
|   if (slot) { |   if (dup) { | ||||||
|     var->type = JSON_OWNED_STRING; |     var->type = JSON_OWNED_STRING; | ||||||
|     var->content.asOwnedString = slot; |     var->content.asString = dup; | ||||||
|     return true; |     return true; | ||||||
|   } else { |   } else { | ||||||
|     var->type = JSON_NULL; |     var->type = JSON_NULL; | ||||||
| @@ -169,10 +167,10 @@ inline bool variantSetString(JsonVariantData* var, T value, MemoryPool* pool) { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantSetOwnedString(JsonVariantData* var, StringSlot* slot) { | inline bool variantSetOwnedString(JsonVariantData* var, char* s) { | ||||||
|   if (!var) return false; |   if (!var) return false; | ||||||
|   var->type = JSON_OWNED_STRING; |   var->type = JSON_OWNED_STRING; | ||||||
|   var->content.asOwnedString = slot; |   var->content.asString = s; | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -218,12 +216,11 @@ inline bool variantCopy(JsonVariantData* dst, const JsonVariantData* src, | |||||||
|       return objectCopy(variantToObject(dst), &src->content.asObject, pool); |       return objectCopy(variantToObject(dst), &src->content.asObject, pool); | ||||||
|     case JSON_OWNED_STRING: |     case JSON_OWNED_STRING: | ||||||
|       return variantSetString( |       return variantSetString( | ||||||
|           dst, makeString(src->content.asOwnedString->value), pool); |           dst, ZeroTerminatedRamString(src->content.asString), pool); | ||||||
|     case JSON_OWNED_RAW: |     case JSON_OWNED_RAW: | ||||||
|       return variantSetOwnedRaw(dst, |       return variantSetOwnedRaw( | ||||||
|                                 serialized(src->content.asOwnedRaw->value, |           dst, serialized(src->content.asRaw.data, src->content.asRaw.size), | ||||||
|                                            src->content.asOwnedRaw->size), |           pool); | ||||||
|                                 pool); |  | ||||||
|     default: |     default: | ||||||
|       // caution: don't override keyIsOwned |       // caution: don't override keyIsOwned | ||||||
|       dst->type = src->type; |       dst->type = src->type; | ||||||
| @@ -266,16 +263,15 @@ inline bool variantEquals(const JsonVariantData* a, const JsonVariantData* b) { | |||||||
|   if (a->type != b->type) return false; |   if (a->type != b->type) return false; | ||||||
|  |  | ||||||
|   switch (a->type) { |   switch (a->type) { | ||||||
|     case JSON_LINKED_RAW: |  | ||||||
|     case JSON_LINKED_STRING: |     case JSON_LINKED_STRING: | ||||||
|  |     case JSON_OWNED_STRING: | ||||||
|       return !strcmp(a->content.asString, b->content.asString); |       return !strcmp(a->content.asString, b->content.asString); | ||||||
|  |  | ||||||
|  |     case JSON_LINKED_RAW: | ||||||
|     case JSON_OWNED_RAW: |     case JSON_OWNED_RAW: | ||||||
|     case JSON_OWNED_STRING: |       return a->content.asRaw.size == b->content.asRaw.size && | ||||||
|       return a->content.asOwnedString->size == b->content.asOwnedString->size && |              !memcmp(a->content.asRaw.data, b->content.asRaw.data, | ||||||
|              !memcmp(a->content.asOwnedString->value, |                      a->content.asRaw.size); | ||||||
|                      b->content.asOwnedString->value, |  | ||||||
|                      a->content.asOwnedString->size); |  | ||||||
|  |  | ||||||
|     case JSON_BOOLEAN: |     case JSON_BOOLEAN: | ||||||
|     case JSON_POSITIVE_INTEGER: |     case JSON_POSITIVE_INTEGER: | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ class JsonKey { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool isNull() const { |   bool isNull() const { | ||||||
|     return _slot == 0 || _slot->linkedKey == 0; |     return _slot == 0 || _slot->key == 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   friend bool operator==(JsonKey lhs, const char* rhs) { |   friend bool operator==(JsonKey lhs, const char* rhs) { | ||||||
|   | |||||||
| @@ -206,7 +206,8 @@ class JsonVariant : public JsonVariantProxy<JsonVariantData>, | |||||||
|  |  | ||||||
|   // 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()); |     return variantSetOwnedString(_data, | ||||||
|  |                                  value.save(_memoryPool));  // TODO: remove? | ||||||
|   } |   } | ||||||
|   FORCE_INLINE bool set(ZeroTerminatedRamStringConst value) const { |   FORCE_INLINE bool set(ZeroTerminatedRamStringConst value) const { | ||||||
|     return variantSetString(_data, value.c_str()); |     return variantSetString(_data, value.c_str()); | ||||||
|   | |||||||
| @@ -89,15 +89,10 @@ inline void JsonVariantConst::accept(Visitor& visitor) const { | |||||||
|       return visitor.visitObject(JsonObjectConst(&_data->content.asObject)); |       return visitor.visitObject(JsonObjectConst(&_data->content.asObject)); | ||||||
|  |  | ||||||
|     case JSON_LINKED_STRING: |     case JSON_LINKED_STRING: | ||||||
|  |     case JSON_OWNED_STRING: | ||||||
|       return visitor.visitString(_data->content.asString); |       return visitor.visitString(_data->content.asString); | ||||||
|  |  | ||||||
|     case JSON_OWNED_STRING: |  | ||||||
|       return visitor.visitString(_data->content.asOwnedString->value); |  | ||||||
|  |  | ||||||
|     case JSON_OWNED_RAW: |     case JSON_OWNED_RAW: | ||||||
|       return visitor.visitRawJson(_data->content.asOwnedRaw->value, |  | ||||||
|                                   _data->content.asOwnedRaw->size); |  | ||||||
|  |  | ||||||
|     case JSON_LINKED_RAW: |     case JSON_LINKED_RAW: | ||||||
|       return visitor.visitRawJson(_data->content.asRaw.data, |       return visitor.visitRawJson(_data->content.asRaw.data, | ||||||
|                                   _data->content.asRaw.size); |                                   _data->content.asRaw.size); | ||||||
|   | |||||||
| @@ -23,21 +23,6 @@ namespace ARDUINOJSON_NAMESPACE { | |||||||
| //             _left          _right | //             _left          _right | ||||||
|  |  | ||||||
| class MemoryPool { | class MemoryPool { | ||||||
|   class UpdateStringSlotAddress { |  | ||||||
|    public: |  | ||||||
|     UpdateStringSlotAddress(const char* address, size_t offset) |  | ||||||
|         : _address(address), _offset(offset) {} |  | ||||||
|  |  | ||||||
|     void operator()(StringSlot* slot) const { |  | ||||||
|       ARDUINOJSON_ASSERT(slot != NULL); |  | ||||||
|       if (slot->value > _address) slot->value -= _offset; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|    private: |  | ||||||
|     const char* _address; |  | ||||||
|     size_t _offset; |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   MemoryPool(char* buf, size_t capa) |   MemoryPool(char* buf, size_t capa) | ||||||
|       : _begin(buf), |       : _begin(buf), | ||||||
| @@ -66,34 +51,26 @@ class MemoryPool { | |||||||
|     return allocRight<VariantSlot>(); |     return allocRight<VariantSlot>(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   StringSlot* allocFrozenString(size_t n) { |   char* allocFrozenString(size_t n) { | ||||||
|     StringSlot* s = allocStringSlot(); |  | ||||||
|     if (!s) return 0; |  | ||||||
|     if (!canAlloc(n)) return 0; |     if (!canAlloc(n)) return 0; | ||||||
|  |     char* s = _left; | ||||||
|     s->value = _left; |  | ||||||
|     s->size = n; |  | ||||||
|     _left += n; |     _left += n; | ||||||
|     checkInvariants(); |     checkInvariants(); | ||||||
|  |  | ||||||
|     return s; |     return s; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   StringSlot* allocExpandableString() { |   StringSlot allocExpandableString() { | ||||||
|     StringSlot* s = allocStringSlot(); |     StringSlot s; | ||||||
|     if (!s) return 0; |     s.value = _left; | ||||||
|  |     s.size = size_t(_right - _left); | ||||||
|     s->value = _left; |  | ||||||
|     s->size = size_t(_right - _left); |  | ||||||
|     _left = _right; |     _left = _right; | ||||||
|  |  | ||||||
|     checkInvariants(); |     checkInvariants(); | ||||||
|     return s; |     return s; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void freezeString(StringSlot* slot, size_t newSize) { |   void freezeString(StringSlot& s, size_t newSize) { | ||||||
|     _left -= (slot->size - newSize); |     _left -= (s.size - newSize); | ||||||
|     slot->size = newSize; |     s.size = newSize; | ||||||
|     checkInvariants(); |     checkInvariants(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,28 +26,28 @@ class StringBuilder { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void append(char c) { |   void append(char c) { | ||||||
|     if (!_slot) return; |     if (!_slot.value) return; | ||||||
|  |  | ||||||
|     if (_size >= _slot->size) { |     if (_size >= _slot.size) { | ||||||
|       _slot = 0; |       _slot.value = 0; | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     _slot->value[_size++] = c; |     _slot.value[_size++] = c; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   StringType complete() { |   StringType complete() { | ||||||
|     append('\0'); |     append('\0'); | ||||||
|     if (_slot) { |     if (_slot.value) { | ||||||
|       _parent->freezeString(_slot, _size); |       _parent->freezeString(_slot, _size); | ||||||
|     } |     } | ||||||
|     return _slot; |     return _slot.value; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   MemoryPool* _parent; |   MemoryPool* _parent; | ||||||
|   size_t _size; |   size_t _size; | ||||||
|   StringSlot* _slot; |   StringSlot _slot; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -7,14 +7,12 @@ | |||||||
| #include <stddef.h>  // for size_t | #include <stddef.h>  // for size_t | ||||||
| #include "../Configuration.hpp" | #include "../Configuration.hpp" | ||||||
|  |  | ||||||
| #define JSON_STRING_SIZE(SIZE) \ | #define JSON_STRING_SIZE(SIZE) (SIZE) | ||||||
|   (sizeof(ARDUINOJSON_NAMESPACE::StringSlot) + (SIZE)) |  | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| struct StringSlot { | struct StringSlot { | ||||||
|   char *value; |   char *value; | ||||||
|   size_t size; |   size_t size; | ||||||
|   struct StringSlot *next; |  | ||||||
| }; | }; | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -12,10 +12,7 @@ struct VariantSlot { | |||||||
|   JsonVariantData value; |   JsonVariantData value; | ||||||
|   struct VariantSlot* next; |   struct VariantSlot* next; | ||||||
|   struct VariantSlot* prev; |   struct VariantSlot* prev; | ||||||
|   union { |   const char* key; | ||||||
|     const char* linkedKey; |  | ||||||
|     StringSlot* ownedKey; |  | ||||||
|   }; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -12,13 +12,12 @@ class ArduinoString { | |||||||
|  public: |  public: | ||||||
|   ArduinoString(const ::String& str) : _str(&str) {} |   ArduinoString(const ::String& str) : _str(&str) {} | ||||||
|  |  | ||||||
|   template <typename TMemoryPool> |   char* save(MemoryPool* memoryPool) const { | ||||||
|   StringSlot* save(TMemoryPool* memoryPool) const { |  | ||||||
|     if (isNull()) return NULL; |     if (isNull()) return NULL; | ||||||
|     size_t n = _str->length() + 1; |     size_t n = _str->length() + 1; | ||||||
|     StringSlot* slot = memoryPool->allocFrozenString(n); |     char* dup = memoryPool->allocFrozenString(n); | ||||||
|     if (slot) memcpy(slot->value, _str->c_str(), n); |     if (dup) memcpy(dup, _str->c_str(), n); | ||||||
|     return slot; |     return dup; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool isNull() const { |   bool isNull() const { | ||||||
|   | |||||||
| @@ -21,12 +21,11 @@ class FixedSizeFlashString { | |||||||
|     return !_str; |     return !_str; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TMemoryPool> |   char* save(MemoryPool* memoryPool) const { | ||||||
|   StringSlot* save(TMemoryPool* memoryPool) const { |  | ||||||
|     if (!_str) return NULL; |     if (!_str) return NULL; | ||||||
|     StringSlot* slot = memoryPool->allocFrozenString(_size); |     char* dup = memoryPool->allocFrozenString(_size); | ||||||
|     if (!slot) memcpy_P(slot->value, (const char*)_str, _size); |     if (!dup) memcpy_P(dup, (const char*)_str, _size); | ||||||
|     return slot; |     return dup; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t size() const { |   size_t size() const { | ||||||
|   | |||||||
| @@ -23,11 +23,11 @@ class FixedSizeRamString { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TMemoryPool> |   template <typename TMemoryPool> | ||||||
|   StringSlot* save(TMemoryPool* memoryPool) const { |   char* save(TMemoryPool* memoryPool) const { | ||||||
|     if (!_str) return NULL; |     if (!_str) return NULL; | ||||||
|     StringSlot* slot = memoryPool->allocFrozenString(_size); |     char* dup = memoryPool->allocFrozenString(_size); | ||||||
|     if (slot) memcpy(slot->value, _str, _size); |     if (dup) memcpy(dup, _str, _size); | ||||||
|     return slot; |     return dup; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t size() const { |   size_t size() const { | ||||||
|   | |||||||
| @@ -12,12 +12,11 @@ class StlString { | |||||||
|  public: |  public: | ||||||
|   StlString(const std::string& str) : _str(&str) {} |   StlString(const std::string& str) : _str(&str) {} | ||||||
|  |  | ||||||
|   template <typename TMemoryPool> |   char* save(MemoryPool* memoryPool) const { | ||||||
|   StringSlot* save(TMemoryPool* memoryPool) const { |  | ||||||
|     size_t n = _str->length() + 1; |     size_t n = _str->length() + 1; | ||||||
|     StringSlot* slot = memoryPool->allocFrozenString(n); |     char* dup = memoryPool->allocFrozenString(n); | ||||||
|     if (slot) memcpy(slot->value, _str->c_str(), n); |     if (dup) memcpy(dup, _str->c_str(), n); | ||||||
|     return slot; |     return dup; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool isNull() const { |   bool isNull() const { | ||||||
|   | |||||||
| @@ -5,44 +5,35 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include "../Memory/StringSlot.hpp" | #include "../Memory/MemoryPool.hpp" | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| class StringInMemoryPool { | class StringInMemoryPool { | ||||||
|  public: |  public: | ||||||
|   StringInMemoryPool(StringSlot* s = 0) : _slot(s) {} |   StringInMemoryPool(char* s = 0) : _value(s) {} | ||||||
|  |  | ||||||
|   bool equals(const char* expected) const { |   bool equals(const char* expected) const { | ||||||
|     if (!_slot) return expected == 0; |     if (!_value) return expected == 0; | ||||||
|     const char* actual = _slot->value; |     const char* actual = _value; | ||||||
|     if (actual == expected) return true; |     if (actual == expected) return true; | ||||||
|     return strcmp(actual, expected) == 0; |     return strcmp(actual, expected) == 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   char* save(void*) { | ||||||
|  |     return _value; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   bool isNull() const { |   bool isNull() const { | ||||||
|     return !_slot; |     return !_value; | ||||||
|   } |  | ||||||
|  |  | ||||||
|   template <typename TMemoryPool> |  | ||||||
|   StringSlot* save(TMemoryPool*) const { |  | ||||||
|     return _slot; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   size_t size() const { |  | ||||||
|     return _slot->size; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   StringSlot* slot() const { |  | ||||||
|     return _slot; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   const char* c_str() const { |   const char* c_str() const { | ||||||
|     return _slot->value; |     return _value; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   StringSlot* _slot; |   char* _value; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -20,13 +20,12 @@ class ZeroTerminatedFlashString { | |||||||
|     return !_str; |     return !_str; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TMemoryPool> |   char* save(MemoryPool* memoryPool) const { | ||||||
|   StringSlot* save(TMemoryPool* memoryPool) const { |  | ||||||
|     if (!_str) return NULL; |     if (!_str) return NULL; | ||||||
|     size_t n = size() + 1;  // copy the terminator |     size_t n = size() + 1;  // copy the terminator | ||||||
|     StringSlot* slot = memoryPool->allocFrozenString(n); |     char* dup = memoryPool->allocFrozenString(n); | ||||||
|     if (slot) memcpy_P(slot->value, reinterpret_cast<const char*>(_str), n); |     if (dup) memcpy_P(dup, reinterpret_cast<const char*>(_str), n); | ||||||
|     return slot; |     return dup; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t size() const { |   size_t size() const { | ||||||
|   | |||||||
| @@ -14,12 +14,12 @@ class ZeroTerminatedRamString : public ZeroTerminatedRamStringConst { | |||||||
|       : ZeroTerminatedRamStringConst(str) {} |       : ZeroTerminatedRamStringConst(str) {} | ||||||
|  |  | ||||||
|   template <typename TMemoryPool> |   template <typename TMemoryPool> | ||||||
|   StringSlot* save(TMemoryPool* memoryPool) const { |   char* save(TMemoryPool* memoryPool) const { | ||||||
|     if (!_str) return NULL; |     if (!_str) return NULL; | ||||||
|     size_t n = size() + 1; |     size_t n = size() + 1; | ||||||
|     StringSlot* slot = memoryPool->allocFrozenString(n); |     char* dup = memoryPool->allocFrozenString(n); | ||||||
|     if (slot) memcpy(slot->value, _str, n); |     if (dup) memcpy(dup, _str, n); | ||||||
|     return slot; |     return dup; | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -79,12 +79,12 @@ TEST_CASE("JsonVariant with not enough memory") { | |||||||
|   JsonVariant v = doc.to<JsonVariant>(); |   JsonVariant v = doc.to<JsonVariant>(); | ||||||
|  |  | ||||||
|   SECTION("std::string") { |   SECTION("std::string") { | ||||||
|     v.set(std::string("hello")); |     v.set(std::string("hello world!!")); | ||||||
|     REQUIRE(v.isNull()); |     REQUIRE(v.isNull()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("Serialized<std::string>") { |   SECTION("Serialized<std::string>") { | ||||||
|     v.set(serialized(std::string("hello"))); |     v.set(serialized(std::string("hello world!!"))); | ||||||
|     REQUIRE(v.isNull()); |     REQUIRE(v.isNull()); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,26 +9,22 @@ using namespace ARDUINOJSON_NAMESPACE; | |||||||
|  |  | ||||||
| TEST_CASE("MemoryPool::allocFrozenString()") { | TEST_CASE("MemoryPool::allocFrozenString()") { | ||||||
|   const size_t poolCapacity = 64; |   const size_t poolCapacity = 64; | ||||||
|   const size_t longestString = poolCapacity - sizeof(StringSlot); |   const size_t longestString = poolCapacity; | ||||||
|   char buffer[poolCapacity]; |   char buffer[poolCapacity]; | ||||||
|   MemoryPool pool(buffer, poolCapacity); |   MemoryPool pool(buffer, poolCapacity); | ||||||
|  |  | ||||||
|   SECTION("Returns different addresses") { |   SECTION("Returns different addresses") { | ||||||
|     StringSlot *a = pool.allocFrozenString(1); |     char *a = pool.allocFrozenString(1); | ||||||
|     StringSlot *b = pool.allocFrozenString(1); |     char *b = pool.allocFrozenString(1); | ||||||
|     REQUIRE(a != b); |     REQUIRE(a != b); | ||||||
|     REQUIRE(a->value != b->value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("Returns a StringSlot of the right size") { |  | ||||||
|     StringSlot *s = pool.allocFrozenString(12); |  | ||||||
|     REQUIRE(s->size == 12); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("Returns NULL when full") { |   SECTION("Returns NULL when full") { | ||||||
|     pool.allocFrozenString(longestString); |     void *p1 = pool.allocFrozenString(longestString); | ||||||
|     void *p = pool.allocFrozenString(1); |     REQUIRE(p1 != 0); | ||||||
|     REQUIRE(0 == p); |  | ||||||
|  |     void *p2 = pool.allocFrozenString(1); | ||||||
|  |     REQUIRE(p2 == 0); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("Returns NULL when pool is too small") { |   SECTION("Returns NULL when pool is too small") { | ||||||
| @@ -46,22 +42,16 @@ TEST_CASE("MemoryPool::allocFrozenString()") { | |||||||
|     REQUIRE(0 == pool2.allocFrozenString(2)); |     REQUIRE(0 == pool2.allocFrozenString(2)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("Returns aligned pointers") { |  | ||||||
|     REQUIRE(isAligned(pool.allocFrozenString(1))); |  | ||||||
|     REQUIRE(isAligned(pool.allocFrozenString(1))); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("Returns same address after clear()") { |   SECTION("Returns same address after clear()") { | ||||||
|     StringSlot *a = pool.allocFrozenString(1); |     void *a = pool.allocFrozenString(1); | ||||||
|     pool.clear(); |     pool.clear(); | ||||||
|     StringSlot *b = pool.allocFrozenString(1); |     void *b = pool.allocFrozenString(1); | ||||||
|  |  | ||||||
|     REQUIRE(a == b); |     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); |     void *a = pool.allocFrozenString(longestString); | ||||||
|  |  | ||||||
|     REQUIRE(a != 0); |     REQUIRE(a != 0); | ||||||
|   } |   } | ||||||
| @@ -70,7 +60,7 @@ TEST_CASE("MemoryPool::allocFrozenString()") { | |||||||
|     pool.allocFrozenString(longestString); |     pool.allocFrozenString(longestString); | ||||||
|     pool.clear(); |     pool.clear(); | ||||||
|  |  | ||||||
|     StringSlot *a = pool.allocFrozenString(longestString); |     void *a = pool.allocFrozenString(longestString); | ||||||
|  |  | ||||||
|     REQUIRE(a != 0); |     REQUIRE(a != 0); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -28,11 +28,11 @@ TEST_CASE("MemoryPool::size()") { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("Decreases after freezeString()") { |   SECTION("Decreases after freezeString()") { | ||||||
|     StringSlot* a = memoryPool.allocExpandableString(); |     StringSlot a = memoryPool.allocExpandableString(); | ||||||
|     memoryPool.freezeString(a, 1); |     memoryPool.freezeString(a, 1); | ||||||
|     REQUIRE(memoryPool.size() == JSON_STRING_SIZE(1)); |     REQUIRE(memoryPool.size() == JSON_STRING_SIZE(1)); | ||||||
|  |  | ||||||
|     StringSlot* b = memoryPool.allocExpandableString(); |     StringSlot b = memoryPool.allocExpandableString(); | ||||||
|     memoryPool.freezeString(b, 1); |     memoryPool.freezeString(b, 1); | ||||||
|     REQUIRE(memoryPool.size() == 2 * JSON_STRING_SIZE(1)); |     REQUIRE(memoryPool.size() == 2 * JSON_STRING_SIZE(1)); | ||||||
|   } |   } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user