Use singly-linked list to reduce memory usage

This commit is contained in:
Benoit Blanchon
2018-12-01 12:05:51 +01:00
parent aaf0d5c3c5
commit 1d942cdf41
8 changed files with 97 additions and 71 deletions

View File

@@ -15,26 +15,23 @@ template <typename TKey>
inline bool slotSetKey(VariantSlot* var, TKey key, MemoryPool* pool) {
char* dup = key.save(pool);
if (!dup) return false;
var->key = dup;
var->value.keyIsOwned = true;
var->setKey(dup, true);
return true;
}
inline bool slotSetKey(VariantSlot* var, ZeroTerminatedRamStringConst key,
MemoryPool*) {
var->key = key.c_str();
var->value.keyIsOwned = false;
var->setKey(key.c_str(), false);
return true;
}
inline bool slotSetKey(VariantSlot* var, StringInMemoryPool key, MemoryPool*) {
var->key = key.c_str();
var->value.keyIsOwned = true;
var->setKey(key.c_str(), true);
return true;
}
inline const char* slotGetKey(const VariantSlot* var) {
return var->key;
return var->key();
}
inline size_t slotSize(const VariantSlot* var) {

View File

@@ -11,6 +11,8 @@
namespace ARDUINOJSON_NAMESPACE {
class VariantSlot;
enum VariantType {
JSON_NULL,
JSON_LINKED_RAW,
@@ -26,13 +28,13 @@ enum VariantType {
};
struct ObjectData {
struct VariantSlot *head;
struct VariantSlot *tail;
VariantSlot *head;
VariantSlot *tail;
};
struct ArrayData {
struct VariantSlot *head;
struct VariantSlot *tail;
VariantSlot *head;
VariantSlot *tail;
};
struct RawData {
@@ -56,9 +58,9 @@ union VariantContent {
// this struct must be a POD type to prevent error calling offsetof on clang
struct VariantData {
VariantContent content;
bool keyIsOwned : 1;
VariantType type : 7;
VariantContent content;
};
inline VariantData *getVariantData(ArrayData *arr) {

View File

@@ -11,16 +11,33 @@ namespace ARDUINOJSON_NAMESPACE {
typedef conditional<sizeof(void*) <= 2, int8_t, int16_t>::type VariantSlotDiff;
struct VariantSlot {
VariantData value;
VariantSlotDiff next;
VariantSlotDiff prev;
const char* key;
class VariantSlot {
// CAUTION: same layout as VariantData
// we cannot use composition because it adds padding
// (+20% on ESP8266 for example)
VariantContent _content;
bool _keyIsOwned : 1;
VariantType _type : 7;
VariantSlotDiff _next;
const char* _key;
// Must be a POD! so no constructor, nor destructor, nor virtual
public:
// Must be a POD!
// - no constructor
// - no destructor
// - no virtual
// - no inheritance
VariantData* getData() {
return reinterpret_cast<VariantData*>(&_content);
}
const VariantData* getData() const {
return reinterpret_cast<const VariantData*>(&_content);
}
VariantSlot* getNext() {
return next ? this + next : 0;
return _next ? this + _next : 0;
}
const VariantSlot* getNext() const {
@@ -30,32 +47,50 @@ struct VariantSlot {
VariantSlot* getNext(size_t distance) {
VariantSlot* slot = this;
while (distance--) {
if (!slot->next) return 0;
slot += slot->next;
if (!slot->_next) return 0;
slot += slot->_next;
}
return slot;
}
VariantSlot* getPrev(VariantSlot* head) {
while (head) {
VariantSlot* nxt = head->getNext();
if (nxt == this) return head;
head = nxt;
}
return head;
}
const VariantSlot* getNext(size_t distance) const {
return const_cast<VariantSlot*>(this)->getNext(distance);
}
VariantSlot* getPrev() {
return prev ? this + prev : 0;
}
void setNext(VariantSlot* slot) {
this->next = VariantSlotDiff(slot ? slot - this : 0);
}
void setPrev(VariantSlot* slot) {
this->prev = VariantSlotDiff(slot ? slot - this : 0);
_next = VariantSlotDiff(slot ? slot - this : 0);
}
void attachTo(VariantSlot* tail) {
VariantSlotDiff offset = VariantSlotDiff(tail - this);
this->prev = offset;
tail->next = VariantSlotDiff(-offset);
tail->_next = VariantSlotDiff(this - tail);
}
void setKey(const char* k, bool owned) {
_keyIsOwned = owned;
_key = k;
}
const char* key() const {
return _key;
}
bool ownsKey() const {
return _keyIsOwned;
}
void init() {
_next = 0;
_type = JSON_NULL;
_keyIsOwned = false;
}
};