From b77b203935ec8f76ac6556222e066b23a127d81b Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Fri, 7 Dec 2018 09:16:58 +0100 Subject: [PATCH] Extracted VariantData and CollectionData classes --- CHANGELOG.md | 1 + src/ArduinoJson.hpp | 1 + src/ArduinoJson/Array/ArrayFunctions.hpp | 90 +--- src/ArduinoJson/Array/ArrayIterator.hpp | 25 +- src/ArduinoJson/Array/ArrayRef.hpp | 65 ++- src/ArduinoJson/Collection/CollectionData.hpp | 68 +++ src/ArduinoJson/Collection/CollectionImpl.hpp | 145 +++++++ .../Deserialization/deserialize.hpp | 53 ++- src/ArduinoJson/Document/JsonDocument.hpp | 33 +- src/ArduinoJson/Json/JsonDeserializer.hpp | 63 ++- src/ArduinoJson/Json/JsonSerializer.hpp | 30 +- src/ArduinoJson/Memory/MemoryPool.hpp | 1 - src/ArduinoJson/Memory/StringBuilder.hpp | 5 +- .../MsgPack/MsgPackDeserializer.hpp | 105 +++-- src/ArduinoJson/MsgPack/MsgPackSerializer.hpp | 17 +- src/ArduinoJson/Object/Key.hpp | 2 +- src/ArduinoJson/Object/ObjectFunctions.hpp | 122 ++---- src/ArduinoJson/Object/ObjectIterator.hpp | 21 +- src/ArduinoJson/Object/ObjectRef.hpp | 78 ++-- src/ArduinoJson/Object/Pair.hpp | 8 +- .../Polyfills/type_traits/is_array.hpp | 2 + .../StringStorage/StringCopier.hpp | 6 +- src/ArduinoJson/StringStorage/StringMover.hpp | 6 +- src/ArduinoJson/Strings/ArduinoString.hpp | 4 +- .../Strings/FixedSizeFlashString.hpp | 4 +- .../Strings/FixedSizeRamString.hpp | 5 +- src/ArduinoJson/Strings/StlString.hpp | 4 +- .../Strings/StringInMemoryPool.hpp | 39 -- src/ArduinoJson/Strings/StringTypes.hpp | 2 +- .../Strings/ZeroTerminatedFlashString.hpp | 4 +- .../Strings/ZeroTerminatedRamString.hpp | 5 +- src/ArduinoJson/Variant/SlotFunctions.hpp | 17 +- src/ArduinoJson/Variant/VariantAs.hpp | 9 +- src/ArduinoJson/Variant/VariantAsImpl.hpp | 3 +- src/ArduinoJson/Variant/VariantContent.hpp | 46 +++ src/ArduinoJson/Variant/VariantData.hpp | 343 +++++++++++++--- src/ArduinoJson/Variant/VariantFunctions.hpp | 386 ++++++------------ src/ArduinoJson/Variant/VariantImpl.hpp | 103 ++--- src/ArduinoJson/Variant/VariantRef.hpp | 47 +-- src/ArduinoJson/Variant/VariantSlot.hpp | 54 ++- test/JsonArray/equals.cpp | 20 +- test/JsonObject/equals.cpp | 20 +- test/MemoryPool/StringBuilder.cpp | 18 +- test/MemoryPool/clear.cpp | 16 +- test/MemoryPool/size.cpp | 40 +- 45 files changed, 1129 insertions(+), 1007 deletions(-) create mode 100644 src/ArduinoJson/Collection/CollectionData.hpp create mode 100644 src/ArduinoJson/Collection/CollectionImpl.hpp delete mode 100644 src/ArduinoJson/Strings/StringInMemoryPool.hpp create mode 100644 src/ArduinoJson/Variant/VariantContent.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c17f2bd..a6a9062f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,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 * Reduced the memory usage +* Reduced the code size * Removed spurious files in the Particle library v6.6.0-beta (2018-11-13) diff --git a/src/ArduinoJson.hpp b/src/ArduinoJson.hpp index 07c1565a..70d1bd9f 100644 --- a/src/ArduinoJson.hpp +++ b/src/ArduinoJson.hpp @@ -15,6 +15,7 @@ #include "ArduinoJson/Array/ArrayImpl.hpp" #include "ArduinoJson/Array/ArraySubscript.hpp" +#include "ArduinoJson/Collection/CollectionImpl.hpp" #include "ArduinoJson/Object/ObjectImpl.hpp" #include "ArduinoJson/Object/ObjectSubscript.hpp" #include "ArduinoJson/Variant/VariantAsImpl.hpp" diff --git a/src/ArduinoJson/Array/ArrayFunctions.hpp b/src/ArduinoJson/Array/ArrayFunctions.hpp index 19652b45..f13984a6 100644 --- a/src/ArduinoJson/Array/ArrayFunctions.hpp +++ b/src/ArduinoJson/Array/ArrayFunctions.hpp @@ -4,92 +4,26 @@ #pragma once -#include "../Variant/SlotFunctions.hpp" -#include "../Variant/VariantData.hpp" +#include "../Collection/CollectionData.hpp" namespace ARDUINOJSON_NAMESPACE { -inline VariantData* arrayAdd(ArrayData* arr, MemoryPool* pool) { - if (!arr) return 0; - - VariantSlot* slot = pool->allocVariant(); - if (!slot) return 0; - - slot->init(); - - if (arr->tail) { - slot->attachTo(arr->tail); - arr->tail = slot; - } else { - arr->head = slot; - arr->tail = slot; - } - - return slot->getData(); +inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) { + return arr ? arr->add(pool) : 0; } -inline VariantSlot* arrayGetSlot(const ArrayData* arr, size_t index) { - if (!arr) return 0; - return arr->head->getNext(index); -} - -inline VariantData* arrayGet(const ArrayData* arr, size_t index) { - VariantSlot* slot = arrayGetSlot(arr, index); - return slot ? slot->getData() : 0; -} - -inline void arrayRemove(ArrayData* arr, VariantSlot* slot) { - if (!arr || !slot) return; - - VariantSlot* prev = slot->getPrev(arr->head); - VariantSlot* next = slot->getNext(); - - if (prev) - prev->setNext(next); +template +inline void arrayAccept(const CollectionData *arr, Visitor &visitor) { + if (arr) + visitor.visitArray(*arr); else - arr->head = next; - if (!next) arr->tail = prev; + visitor.visitNull(); } -inline void arrayRemove(ArrayData* arr, size_t index) { - arrayRemove(arr, arrayGetSlot(arr, index)); -} +inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) { + if (lhs == rhs) return true; + if (!lhs || !rhs) return false; -inline void arrayClear(ArrayData* arr) { - if (!arr) return; - arr->head = 0; - arr->tail = 0; -} - -bool variantCopy(VariantData*, const VariantData*, MemoryPool*); - -inline bool arrayCopy(ArrayData* dst, const ArrayData* src, MemoryPool* pool) { - if (!dst || !src) return false; - arrayClear(dst); - for (VariantSlot* s = src->head; s; s = s->getNext()) { - if (!variantCopy(arrayAdd(dst, pool), s->getData(), pool)) return false; - } - return true; -} - -bool variantEquals(const VariantData*, const VariantData*); - -inline bool arrayEquals(const ArrayData* a1, const ArrayData* a2) { - if (a1 == a2) return true; - if (!a1 || !a2) return false; - VariantSlot* s1 = a1->head; - VariantSlot* s2 = a2->head; - for (;;) { - if (s1 == s2) return true; - if (!s1 || !s2) return false; - if (!variantEquals(s1->getData(), s2->getData())) return false; - s1 = s1->getNext(); - s2 = s2->getNext(); - } -} - -inline size_t arraySize(const ArrayData* arr) { - if (!arr) return 0; - return slotSize(arr->head); + return lhs->equalsArray(*rhs); } } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Array/ArrayIterator.hpp b/src/ArduinoJson/Array/ArrayIterator.hpp index 6bc88bbf..84b5bfb0 100644 --- a/src/ArduinoJson/Array/ArrayIterator.hpp +++ b/src/ArduinoJson/Array/ArrayIterator.hpp @@ -11,8 +11,7 @@ namespace ARDUINOJSON_NAMESPACE { class VariantPtr { public: - VariantPtr(MemoryPool *memoryPool, VariantData *data) - : _variant(memoryPool, data) {} + VariantPtr(MemoryPool *pool, VariantData *data) : _variant(pool, data) {} VariantRef *operator->() { return &_variant; @@ -29,14 +28,14 @@ class VariantPtr { class ArrayIterator { public: ArrayIterator() : _slot(0) {} - explicit ArrayIterator(MemoryPool *memoryPool, VariantSlot *slot) - : _memoryPool(memoryPool), _slot(slot) {} + explicit ArrayIterator(MemoryPool *pool, VariantSlot *slot) + : _pool(pool), _slot(slot) {} VariantRef operator*() const { - return VariantRef(_memoryPool, _slot->getData()); + return VariantRef(_pool, _slot->data()); } VariantPtr operator->() { - return VariantPtr(_memoryPool, _slot->getData()); + return VariantPtr(_pool, _slot->data()); } bool operator==(const ArrayIterator &other) const { @@ -48,12 +47,12 @@ class ArrayIterator { } ArrayIterator &operator++() { - _slot = _slot->getNext(); + _slot = _slot->next(); return *this; } ArrayIterator &operator+=(size_t distance) { - _slot = _slot->getNext(distance); + _slot = _slot->next(distance); return *this; } @@ -62,7 +61,7 @@ class ArrayIterator { } private: - MemoryPool *_memoryPool; + MemoryPool *_pool; VariantSlot *_slot; }; @@ -88,10 +87,10 @@ class ArrayConstRefIterator { explicit ArrayConstRefIterator(const VariantSlot *slot) : _slot(slot) {} VariantConstRef operator*() const { - return VariantConstRef(_slot->getData()); + return VariantConstRef(_slot->data()); } VariantConstPtr operator->() { - return VariantConstPtr(_slot->getData()); + return VariantConstPtr(_slot->data()); } bool operator==(const ArrayConstRefIterator &other) const { @@ -103,12 +102,12 @@ class ArrayConstRefIterator { } ArrayConstRefIterator &operator++() { - _slot = _slot->getNext(); + _slot = _slot->next(); return *this; } ArrayConstRefIterator &operator+=(size_t distance) { - _slot = _slot->getNext(distance); + _slot = _slot->next(distance); return *this; } diff --git a/src/ArduinoJson/Array/ArrayRef.hpp b/src/ArduinoJson/Array/ArrayRef.hpp index 2fc6695c..23059ffb 100644 --- a/src/ArduinoJson/Array/ArrayRef.hpp +++ b/src/ArduinoJson/Array/ArrayRef.hpp @@ -21,16 +21,21 @@ class ArraySubscript; template class ArrayRefBase { public: + template + FORCE_INLINE void accept(Visitor& visitor) const { + arrayAccept(_data, visitor); + } + FORCE_INLINE bool isNull() const { return _data == 0; } FORCE_INLINE VariantConstRef operator[](size_t index) const { - return VariantConstRef(arrayGet(_data, index)); + return VariantConstRef(_data ? _data->get(index) : 0); } FORCE_INLINE size_t size() const { - return arraySize(_data); + return _data ? _data->size() : 0; } protected: @@ -38,24 +43,17 @@ class ArrayRefBase { TData* _data; }; -class ArrayConstRef : public ArrayRefBase, public Visitable { +class ArrayConstRef : public ArrayRefBase, + public Visitable { friend class ArrayRef; - typedef ArrayRefBase base_type; + typedef ArrayRefBase base_type; public: typedef ArrayConstRefIterator iterator; - template - FORCE_INLINE void accept(Visitor& visitor) const { - if (_data) - visitor.visitArray(*this); - else - visitor.visitNull(); - } - FORCE_INLINE iterator begin() const { if (!_data) return iterator(); - return iterator(_data->head); + return iterator(_data->head()); } FORCE_INLINE iterator end() const { @@ -63,25 +61,25 @@ class ArrayConstRef : public ArrayRefBase, public Visitable { } FORCE_INLINE ArrayConstRef() : base_type(0) {} - FORCE_INLINE ArrayConstRef(const ArrayData* data) : base_type(data) {} + FORCE_INLINE ArrayConstRef(const CollectionData* data) : base_type(data) {} FORCE_INLINE bool operator==(ArrayConstRef rhs) const { return arrayEquals(_data, rhs._data); } }; -class ArrayRef : public ArrayRefBase, public Visitable { - typedef ArrayRefBase base_type; +class ArrayRef : public ArrayRefBase, public Visitable { + typedef ArrayRefBase base_type; public: typedef ArrayIterator iterator; - FORCE_INLINE ArrayRef() : base_type(0), _memoryPool(0) {} - FORCE_INLINE ArrayRef(MemoryPool* pool, ArrayData* data) - : base_type(data), _memoryPool(pool) {} + FORCE_INLINE ArrayRef() : base_type(0), _pool(0) {} + FORCE_INLINE ArrayRef(MemoryPool* pool, CollectionData* data) + : base_type(data), _pool(pool) {} operator VariantRef() { - return VariantRef(_memoryPool, getVariantData(_data)); + return VariantRef(_pool, reinterpret_cast(_data)); } operator ArrayConstRef() const { @@ -110,12 +108,12 @@ class ArrayRef : public ArrayRefBase, public Visitable { } VariantRef add() const { - return VariantRef(_memoryPool, arrayAdd(_data, _memoryPool)); + return VariantRef(_pool, arrayAdd(_data, _pool)); } FORCE_INLINE iterator begin() const { if (!_data) return iterator(); - return iterator(_memoryPool, _data->head); + return iterator(_pool, _data->head()); } FORCE_INLINE iterator end() const { @@ -153,7 +151,8 @@ class ArrayRef : public ArrayRefBase, public Visitable { // Copy a ArrayRef FORCE_INLINE bool copyFrom(ArrayRef src) const { - return arrayCopy(_data, src._data, _memoryPool); + if (!_data || !src._data) return false; + return _data->copyFrom(*src._data, _pool); } // Exports a 1D array @@ -191,30 +190,22 @@ class ArrayRef : public ArrayRefBase, public Visitable { // Gets the value at the specified index. FORCE_INLINE VariantRef get(size_t index) const { - return VariantRef(_memoryPool, arrayGet(_data, index)); + return VariantRef(_pool, _data ? _data->get(index) : 0); } // Removes element at specified position. FORCE_INLINE void remove(iterator it) const { - arrayRemove(_data, it.internal()); + if (!_data) return; + _data->remove(it.internal()); } // Removes element at specified index. FORCE_INLINE void remove(size_t index) const { - arrayRemove(_data, index); - } - - template - FORCE_INLINE void accept(Visitor& visitor) const { - ArrayConstRef(_data).accept(visitor); + if (!_data) return; + _data->remove(index); } private: - template - FORCE_INLINE bool add_impl(TValueRef value) const { - return add().set(value); - } - - MemoryPool* _memoryPool; + MemoryPool* _pool; }; } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Collection/CollectionData.hpp b/src/ArduinoJson/Collection/CollectionData.hpp new file mode 100644 index 00000000..54bd12b8 --- /dev/null +++ b/src/ArduinoJson/Collection/CollectionData.hpp @@ -0,0 +1,68 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2018 +// MIT License + +#pragma once + +namespace ARDUINOJSON_NAMESPACE { + +class MemoryPool; +class VariantData; +class VariantSlot; + +class CollectionData { + VariantSlot *_head; + VariantSlot *_tail; + + public: + // Must be a POD! + // - no constructor + // - no destructor + // - no virtual + // - no inheritance + VariantSlot *addSlot(MemoryPool *); + + VariantData *add(MemoryPool *pool); + + template + VariantData *add(TKey key, MemoryPool *pool); + + void clear(); + + template + bool containsKey(const TKey &key) const; + + bool copyFrom(const CollectionData &src, MemoryPool *pool); + + bool equalsArray(const CollectionData &other) const; + bool equalsObject(const CollectionData &other) const; + + VariantData *get(size_t index) const; + + template + VariantData *get(TKey key) const; + + VariantSlot *head() const { + return _head; + } + + void remove(size_t index); + + template + void remove(TKey key) { + remove(getSlot(key)); + } + + void remove(VariantSlot *slot); + + size_t size() const; + + private: + VariantSlot *getSlot(size_t index) const; + + template + VariantSlot *getSlot(TKey key) const; + + VariantSlot *getPreviousSlot(VariantSlot *) const; +}; +} // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Collection/CollectionImpl.hpp b/src/ArduinoJson/Collection/CollectionImpl.hpp new file mode 100644 index 00000000..45683a52 --- /dev/null +++ b/src/ArduinoJson/Collection/CollectionImpl.hpp @@ -0,0 +1,145 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2018 +// MIT License + +#pragma once + +#include "../Variant/VariantData.hpp" +#include "CollectionData.hpp" + +namespace ARDUINOJSON_NAMESPACE { + +inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) { + VariantSlot* slot = pool->allocVariant(); + if (!slot) return 0; + + if (_tail) { + _tail->setNextNotNull(slot); + _tail = slot; + } else { + _head = slot; + _tail = slot; + } + + slot->clear(); + return slot; +} + +inline VariantData* CollectionData::add(MemoryPool* pool) { + return addSlot(pool)->data(); +} + +template +inline VariantData* CollectionData::add(TKey key, MemoryPool* pool) { + VariantSlot* slot = addSlot(pool); + if (!slotSetKey(slot, key, pool)) return 0; + return slot->data(); +} + +inline void CollectionData::clear() { + _head = 0; + _tail = 0; +} + +template +inline bool CollectionData::containsKey(const TKey& key) const { + return getSlot(key) != 0; +} + +inline bool CollectionData::copyFrom(const CollectionData& src, + MemoryPool* pool) { + clear(); + for (VariantSlot* s = src._head; s; s = s->next()) { + VariantData* var; + if (s->key() != 0) { + if (s->ownsKey()) + var = add(ZeroTerminatedRamString(s->key()), pool); + else + var = add(ZeroTerminatedRamStringConst(s->key()), pool); + } else { + var = add(pool); + } + if (!var) return false; + if (!var->copyFrom(*s->data(), pool)) return false; + } + return true; +} + +inline bool CollectionData::equalsObject(const CollectionData& other) const { + size_t count = 0; + for (VariantSlot* slot = _head; slot; slot = slot->next()) { + VariantData* v1 = slot->data(); + VariantData* v2 = other.get(makeString(slot->key())); + if (!variantEquals(v1, v2)) return false; + count++; + } + return count == other.size(); +} + +inline bool CollectionData::equalsArray(const CollectionData& other) const { + VariantSlot* s1 = _head; + VariantSlot* s2 = other._head; + for (;;) { + if (s1 == s2) return true; + if (!s1 || !s2) return false; + if (!variantEquals(s1->data(), s2->data())) return false; + s1 = s1->next(); + s2 = s2->next(); + } +} + +template +inline VariantSlot* CollectionData::getSlot(TKey key) const { + VariantSlot* slot = _head; + while (slot) { + if (key.equals(slot->key())) break; + slot = slot->next(); + } + return slot; +} + +inline VariantSlot* CollectionData::getSlot(size_t index) const { + return _head->next(index); +} + +inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const { + VariantSlot* current = _head; + while (current) { + VariantSlot* next = current->next(); + if (next == target) return current; + current = next; + } + return 0; +} + +template +inline VariantData* CollectionData::get(TKey key) const { + VariantSlot* slot = getSlot(key); + return slot ? slot->data() : 0; +} + +inline VariantData* CollectionData::get(size_t index) const { + VariantSlot* slot = getSlot(index); + return slot ? slot->data() : 0; +} + +inline void CollectionData::remove(VariantSlot* slot) { + if (!slot) return; + VariantSlot* prev = getPreviousSlot(slot); + VariantSlot* next = slot->next(); + if (prev) + prev->setNext(next); + else + _head = next; + if (!next) _tail = prev; +} + +inline void CollectionData::remove(size_t index) { + remove(getSlot(index)); +} + +inline size_t CollectionData::size() const { + return slotSize(_head); +} + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Deserialization/deserialize.hpp b/src/ArduinoJson/Deserialization/deserialize.hpp index d2d16da5..bf686997 100644 --- a/src/ArduinoJson/Deserialization/deserialize.hpp +++ b/src/ArduinoJson/Deserialization/deserialize.hpp @@ -14,63 +14,58 @@ namespace ARDUINOJSON_NAMESPACE { -template