ResourceManager: extract the StringPool class

This commit is contained in:
Benoit Blanchon
2023-06-19 11:13:53 +02:00
parent 3e0ba2028c
commit 262747b419
2 changed files with 118 additions and 54 deletions

View File

@ -6,7 +6,7 @@
#include <ArduinoJson/Memory/Alignment.hpp>
#include <ArduinoJson/Memory/Allocator.hpp>
#include <ArduinoJson/Memory/StringNode.hpp>
#include <ArduinoJson/Memory/StringPool.hpp>
#include <ArduinoJson/Memory/VariantPool.hpp>
#include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Polyfills/utility.hpp>
@ -26,7 +26,7 @@ class ResourceManager {
}
~ResourceManager() {
deallocAllStrings();
stringPool_.clear(allocator_);
variantPool_.destroy(allocator_);
}
@ -34,13 +34,12 @@ class ResourceManager {
ResourceManager& operator=(const ResourceManager& src) = delete;
ResourceManager& operator=(ResourceManager&& src) {
deallocAllStrings();
stringPool_.clear(allocator_);
variantPool_.destroy(allocator_);
allocator_ = src.allocator_;
variantPool_ = detail::move(src.variantPool_);
overflowed_ = src.overflowed_;
strings_ = src.strings_;
src.strings_ = nullptr;
stringPool_ = detail::move(src.stringPool_);
return *this;
}
@ -62,10 +61,7 @@ class ResourceManager {
}
size_t size() const {
size_t total = variantPool_.usage();
for (auto node = strings_; node; node = node->next)
total += sizeofString(node->length);
return total;
return variantPool_.usage() + stringPool_.size();
}
bool overflowed() const {
@ -84,37 +80,20 @@ class ResourceManager {
if (str.isNull())
return 0;
auto node = findString(str);
if (node) {
node->references++;
return node;
}
size_t n = str.size();
node = allocString(n);
auto node = stringPool_.add(str, allocator_);
if (!node)
return nullptr;
overflowed_ = true;
stringGetChars(str, node->data, n);
node->data[n] = 0; // force NUL terminator
addStringToList(node);
return node;
}
void addStringToList(StringNode* node) {
ARDUINOJSON_ASSERT(node != nullptr);
node->next = strings_;
strings_ = node;
stringPool_.add(node);
}
template <typename TAdaptedString>
StringNode* findString(const TAdaptedString& str) const {
for (auto node = strings_; node; node = node->next) {
if (stringEquals(str, adaptString(node->data, node->length)))
return node;
}
return nullptr;
return stringPool_.get(str);
}
StringNode* allocString(size_t length) {
@ -136,26 +115,13 @@ class ResourceManager {
}
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;
StringNode::destroy(node, allocator_);
}
return;
}
prev = node;
}
stringPool_.dereference(s, allocator_);
}
void clear() {
variantPool_.clear();
overflowed_ = false;
deallocAllStrings();
stringPool_.clear(allocator_);
}
ptrdiff_t shrinkToFit() {
@ -163,17 +129,9 @@ class ResourceManager {
}
private:
void deallocAllStrings() {
while (strings_) {
auto node = strings_;
strings_ = node->next;
deallocString(node);
}
}
Allocator* allocator_;
bool overflowed_;
StringNode* strings_ = nullptr;
StringPool stringPool_;
VariantPool variantPool_;
};

View 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