forked from bblanchon/ArduinoJson
Reference-count shared strings
This commit is contained in:
@@ -28,6 +28,7 @@ constexpr size_t sizeofObject(size_t n) {
|
||||
struct StringNode {
|
||||
struct StringNode* next;
|
||||
uint16_t length;
|
||||
uint16_t references;
|
||||
char data[1];
|
||||
};
|
||||
|
||||
@@ -112,6 +113,7 @@ class MemoryPool {
|
||||
|
||||
auto node = findString(str);
|
||||
if (node) {
|
||||
node->references++;
|
||||
return node->data;
|
||||
}
|
||||
|
||||
@@ -147,6 +149,7 @@ class MemoryPool {
|
||||
_allocator->allocate(sizeofString(length)));
|
||||
if (node) {
|
||||
node->length = uint16_t(length);
|
||||
node->references = 1;
|
||||
} else {
|
||||
_overflowed = true;
|
||||
}
|
||||
@@ -170,6 +173,23 @@ class MemoryPool {
|
||||
_allocator->deallocate(node);
|
||||
}
|
||||
|
||||
void dereferenceString(const char* s) {
|
||||
StringNode* prev = nullptr;
|
||||
for (auto node = _strings; node; node = node->next) {
|
||||
if (node->data == s) {
|
||||
if (--node->references == 0) {
|
||||
if (prev)
|
||||
prev->next = node->next;
|
||||
else
|
||||
_strings = node->next;
|
||||
_allocator->deallocate(node);
|
||||
}
|
||||
return;
|
||||
}
|
||||
prev = node;
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_right = _end;
|
||||
_overflowed = false;
|
||||
|
||||
@@ -33,6 +33,8 @@ class StringCopier {
|
||||
node = _pool->reallocString(_node, _size);
|
||||
_pool->addStringToList(node);
|
||||
_node = nullptr; // next time we need a new string
|
||||
} else {
|
||||
node->references++;
|
||||
}
|
||||
return JsonString(node->data, node->length, JsonString::Copied);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ inline VariantData* slotData(VariantSlot* slot) {
|
||||
|
||||
inline void slotRelease(const VariantSlot* slot, MemoryPool* pool) {
|
||||
ARDUINOJSON_ASSERT(slot != nullptr);
|
||||
if (slot->ownsKey())
|
||||
pool->dereferenceString(slot->key());
|
||||
variantRelease(slot->data(), pool);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ inline typename TVisitor::result_type variantAccept(const VariantData* var,
|
||||
|
||||
inline void variantRelease(const VariantData* var, MemoryPool* pool) {
|
||||
ARDUINOJSON_ASSERT(var != nullptr);
|
||||
auto s = var->getOwnedString();
|
||||
if (s)
|
||||
pool->dereferenceString(s);
|
||||
|
||||
auto c = var->asCollection();
|
||||
if (c) {
|
||||
for (auto slot = c->head(); slot; slot = slot->next())
|
||||
|
||||
Reference in New Issue
Block a user