forked from bblanchon/ArduinoJson
ResourceManager: extract the StringPool class
This commit is contained in:
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include <ArduinoJson/Memory/Alignment.hpp>
|
#include <ArduinoJson/Memory/Alignment.hpp>
|
||||||
#include <ArduinoJson/Memory/Allocator.hpp>
|
#include <ArduinoJson/Memory/Allocator.hpp>
|
||||||
#include <ArduinoJson/Memory/StringNode.hpp>
|
#include <ArduinoJson/Memory/StringPool.hpp>
|
||||||
#include <ArduinoJson/Memory/VariantPool.hpp>
|
#include <ArduinoJson/Memory/VariantPool.hpp>
|
||||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||||
#include <ArduinoJson/Polyfills/utility.hpp>
|
#include <ArduinoJson/Polyfills/utility.hpp>
|
||||||
@ -26,7 +26,7 @@ class ResourceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
~ResourceManager() {
|
~ResourceManager() {
|
||||||
deallocAllStrings();
|
stringPool_.clear(allocator_);
|
||||||
variantPool_.destroy(allocator_);
|
variantPool_.destroy(allocator_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,13 +34,12 @@ class ResourceManager {
|
|||||||
ResourceManager& operator=(const ResourceManager& src) = delete;
|
ResourceManager& operator=(const ResourceManager& src) = delete;
|
||||||
|
|
||||||
ResourceManager& operator=(ResourceManager&& src) {
|
ResourceManager& operator=(ResourceManager&& src) {
|
||||||
deallocAllStrings();
|
stringPool_.clear(allocator_);
|
||||||
variantPool_.destroy(allocator_);
|
variantPool_.destroy(allocator_);
|
||||||
allocator_ = src.allocator_;
|
allocator_ = src.allocator_;
|
||||||
variantPool_ = detail::move(src.variantPool_);
|
variantPool_ = detail::move(src.variantPool_);
|
||||||
overflowed_ = src.overflowed_;
|
overflowed_ = src.overflowed_;
|
||||||
strings_ = src.strings_;
|
stringPool_ = detail::move(src.stringPool_);
|
||||||
src.strings_ = nullptr;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,10 +61,7 @@ class ResourceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
size_t total = variantPool_.usage();
|
return variantPool_.usage() + stringPool_.size();
|
||||||
for (auto node = strings_; node; node = node->next)
|
|
||||||
total += sizeofString(node->length);
|
|
||||||
return total;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool overflowed() const {
|
bool overflowed() const {
|
||||||
@ -84,37 +80,20 @@ class ResourceManager {
|
|||||||
if (str.isNull())
|
if (str.isNull())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
auto node = findString(str);
|
auto node = stringPool_.add(str, allocator_);
|
||||||
if (node) {
|
|
||||||
node->references++;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t n = str.size();
|
|
||||||
|
|
||||||
node = allocString(n);
|
|
||||||
if (!node)
|
if (!node)
|
||||||
return nullptr;
|
overflowed_ = true;
|
||||||
|
|
||||||
stringGetChars(str, node->data, n);
|
|
||||||
node->data[n] = 0; // force NUL terminator
|
|
||||||
addStringToList(node);
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addStringToList(StringNode* node) {
|
void addStringToList(StringNode* node) {
|
||||||
ARDUINOJSON_ASSERT(node != nullptr);
|
stringPool_.add(node);
|
||||||
node->next = strings_;
|
|
||||||
strings_ = node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
StringNode* findString(const TAdaptedString& str) const {
|
StringNode* findString(const TAdaptedString& str) const {
|
||||||
for (auto node = strings_; node; node = node->next) {
|
return stringPool_.get(str);
|
||||||
if (stringEquals(str, adaptString(node->data, node->length)))
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StringNode* allocString(size_t length) {
|
StringNode* allocString(size_t length) {
|
||||||
@ -136,26 +115,13 @@ class ResourceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dereferenceString(const char* s) {
|
void dereferenceString(const char* s) {
|
||||||
StringNode* prev = nullptr;
|
stringPool_.dereference(s, allocator_);
|
||||||
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;
|
|
||||||
StringNode::destroy(node, allocator_);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
prev = node;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
variantPool_.clear();
|
variantPool_.clear();
|
||||||
overflowed_ = false;
|
overflowed_ = false;
|
||||||
deallocAllStrings();
|
stringPool_.clear(allocator_);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptrdiff_t shrinkToFit() {
|
ptrdiff_t shrinkToFit() {
|
||||||
@ -163,17 +129,9 @@ class ResourceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void deallocAllStrings() {
|
|
||||||
while (strings_) {
|
|
||||||
auto node = strings_;
|
|
||||||
strings_ = node->next;
|
|
||||||
deallocString(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Allocator* allocator_;
|
Allocator* allocator_;
|
||||||
bool overflowed_;
|
bool overflowed_;
|
||||||
StringNode* strings_ = nullptr;
|
StringPool stringPool_;
|
||||||
VariantPool variantPool_;
|
VariantPool variantPool_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
106
src/ArduinoJson/Memory/StringPool.hpp
Normal file
106
src/ArduinoJson/Memory/StringPool.hpp
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Memory/Allocator.hpp>
|
||||||
|
#include <ArduinoJson/Memory/StringNode.hpp>
|
||||||
|
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||||
|
#include <ArduinoJson/Polyfills/utility.hpp>
|
||||||
|
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||||
|
|
||||||
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
|
class VariantSlot;
|
||||||
|
class VariantPool;
|
||||||
|
|
||||||
|
class StringPool {
|
||||||
|
public:
|
||||||
|
StringPool() = default;
|
||||||
|
StringPool(const StringPool&) = delete;
|
||||||
|
|
||||||
|
~StringPool() {
|
||||||
|
ARDUINOJSON_ASSERT(strings_ == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator=(StringPool&& src) {
|
||||||
|
ARDUINOJSON_ASSERT(strings_ == nullptr);
|
||||||
|
strings_ = src.strings_;
|
||||||
|
src.strings_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear(Allocator* allocator) {
|
||||||
|
while (strings_) {
|
||||||
|
auto node = strings_;
|
||||||
|
strings_ = node->next;
|
||||||
|
StringNode::destroy(node, allocator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
size_t total = 0;
|
||||||
|
for (auto node = strings_; node; node = node->next)
|
||||||
|
total += sizeofString(node->length);
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
StringNode* add(TAdaptedString str, Allocator* allocator) {
|
||||||
|
ARDUINOJSON_ASSERT(str.isNull() == false);
|
||||||
|
|
||||||
|
auto node = get(str);
|
||||||
|
if (node) {
|
||||||
|
node->references++;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t n = str.size();
|
||||||
|
|
||||||
|
node = StringNode::create(n, allocator);
|
||||||
|
if (!node)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
stringGetChars(str, node->data, n);
|
||||||
|
node->data[n] = 0; // force NUL terminator
|
||||||
|
add(node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(StringNode* node) {
|
||||||
|
ARDUINOJSON_ASSERT(node != nullptr);
|
||||||
|
node->next = strings_;
|
||||||
|
strings_ = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
StringNode* get(const TAdaptedString& str) const {
|
||||||
|
for (auto node = strings_; node; node = node->next) {
|
||||||
|
if (stringEquals(str, adaptString(node->data, node->length)))
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dereference(const char* s, Allocator* allocator) {
|
||||||
|
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;
|
||||||
|
StringNode::destroy(node, allocator);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
prev = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
StringNode* strings_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
Reference in New Issue
Block a user