mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-11-03 08:01:41 +01:00
Store static strings in a dedicated pool
Because a slot id is smaller than a pointer, this change will ultimately allow reducing the slot size.
This commit is contained in:
@@ -34,6 +34,11 @@ class Slot {
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
T& operator*() const {
|
||||
ARDUINOJSON_ASSERT(ptr_ != nullptr);
|
||||
return *ptr_;
|
||||
}
|
||||
|
||||
T* operator->() const {
|
||||
ARDUINOJSON_ASSERT(ptr_ != nullptr);
|
||||
return ptr_;
|
||||
@@ -76,6 +81,14 @@ class MemoryPool {
|
||||
return slots_ + id;
|
||||
}
|
||||
|
||||
SlotId find(const T& value) const {
|
||||
for (SlotId i = 0; i < usage_; i++) {
|
||||
if (slots_[i] == value)
|
||||
return i;
|
||||
}
|
||||
return NULL_SLOT;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
usage_ = 0;
|
||||
}
|
||||
|
||||
@@ -114,6 +114,15 @@ class MemoryPoolList {
|
||||
return pools_[poolIndex].getSlot(indexInPool);
|
||||
}
|
||||
|
||||
SlotId find(const T& value) const {
|
||||
for (PoolCount i = 0; i < count_; i++) {
|
||||
SlotId id = pools_[i].find(value);
|
||||
if (id != NULL_SLOT)
|
||||
return SlotId(i * ARDUINOJSON_POOL_CAPACITY + id);
|
||||
}
|
||||
return NULL_SLOT;
|
||||
}
|
||||
|
||||
void clear(Allocator* allocator) {
|
||||
for (PoolCount i = 0; i < count_; i++)
|
||||
pools_[i].destroy(allocator);
|
||||
|
||||
@@ -34,6 +34,7 @@ class ResourceManager {
|
||||
~ResourceManager() {
|
||||
stringPool_.clear(allocator_);
|
||||
variantPools_.clear(allocator_);
|
||||
staticStringsPools_.clear(allocator_);
|
||||
}
|
||||
|
||||
ResourceManager(const ResourceManager&) = delete;
|
||||
@@ -42,6 +43,7 @@ class ResourceManager {
|
||||
friend void swap(ResourceManager& a, ResourceManager& b) {
|
||||
swap(a.stringPool_, b.stringPool_);
|
||||
swap(a.variantPools_, b.variantPools_);
|
||||
swap(a.staticStringsPools_, b.staticStringsPools_);
|
||||
swap_(a.allocator_, b.allocator_);
|
||||
swap_(a.overflowed_, b.overflowed_);
|
||||
}
|
||||
@@ -111,14 +113,34 @@ class ResourceManager {
|
||||
stringPool_.dereference(s, allocator_);
|
||||
}
|
||||
|
||||
SlotId saveStaticString(const char* s) {
|
||||
auto existingSlotId = staticStringsPools_.find(s);
|
||||
if (existingSlotId != NULL_SLOT)
|
||||
return existingSlotId;
|
||||
|
||||
auto slot = staticStringsPools_.allocSlot(allocator_);
|
||||
if (slot)
|
||||
*slot = s;
|
||||
else
|
||||
overflowed_ = true;
|
||||
|
||||
return slot.id();
|
||||
}
|
||||
|
||||
const char* getStaticString(SlotId id) const {
|
||||
return *staticStringsPools_.getSlot(id);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
variantPools_.clear(allocator_);
|
||||
overflowed_ = false;
|
||||
variantPools_.clear(allocator_);
|
||||
stringPool_.clear(allocator_);
|
||||
staticStringsPools_.clear(allocator_);
|
||||
}
|
||||
|
||||
void shrinkToFit() {
|
||||
variantPools_.shrinkToFit(allocator_);
|
||||
staticStringsPools_.shrinkToFit(allocator_);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -126,6 +148,7 @@ class ResourceManager {
|
||||
bool overflowed_;
|
||||
StringPool stringPool_;
|
||||
MemoryPoolList<SlotData> variantPools_;
|
||||
MemoryPoolList<const char*> staticStringsPools_;
|
||||
};
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
|
||||
@@ -18,7 +18,7 @@ class JsonPair {
|
||||
JsonPair(detail::ObjectData::iterator iterator,
|
||||
detail::ResourceManager* resources) {
|
||||
if (!iterator.done()) {
|
||||
key_ = iterator->asString();
|
||||
key_ = iterator->asString(resources);
|
||||
iterator.next(resources);
|
||||
value_ = JsonVariant(iterator.data(), resources);
|
||||
}
|
||||
@@ -46,7 +46,7 @@ class JsonPairConst {
|
||||
JsonPairConst(detail::ObjectData::iterator iterator,
|
||||
const detail::ResourceManager* resources) {
|
||||
if (!iterator.done()) {
|
||||
key_ = iterator->asString();
|
||||
key_ = iterator->asString(resources);
|
||||
iterator.next(resources);
|
||||
value_ = JsonVariantConst(iterator.data(), resources);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ inline ObjectData::iterator ObjectData::findKey(
|
||||
return iterator();
|
||||
bool isKey = true;
|
||||
for (auto it = createIterator(resources); !it.done(); it.next(resources)) {
|
||||
if (isKey && stringEquals(key, adaptString(it->asString())))
|
||||
if (isKey && stringEquals(key, adaptString(it->asString(resources))))
|
||||
return it;
|
||||
isKey = !isKey;
|
||||
}
|
||||
|
||||
@@ -90,8 +90,9 @@ template <size_t N>
|
||||
struct StringAdapter<const char (&)[N]> {
|
||||
using AdaptedString = RamString;
|
||||
|
||||
static AdaptedString adapt(const char (&p)[N]) {
|
||||
return RamString(p, N - 1, true);
|
||||
static AdaptedString adapt(const char* p) {
|
||||
ARDUINOJSON_ASSERT(p);
|
||||
return RamString(p, ::strlen(p), true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -28,8 +28,7 @@ class JsonString {
|
||||
detail::enable_if_t<detail::is_integral<TSize>::value &&
|
||||
!detail::is_same<TSize, bool>::value,
|
||||
int> = 0>
|
||||
JsonString(const char* data, TSize sz, bool isStatic = false)
|
||||
: str_(data, size_t(sz), isStatic) {}
|
||||
JsonString(const char* data, TSize sz) : str_(data, size_t(sz), false) {}
|
||||
|
||||
// Returns a pointer to the characters.
|
||||
const char* c_str() const {
|
||||
|
||||
@@ -160,7 +160,7 @@ struct Converter<const char*> : private detail::VariantAttorney {
|
||||
|
||||
static const char* fromJson(JsonVariantConst src) {
|
||||
auto data = getData(src);
|
||||
return data ? data->asString().c_str() : 0;
|
||||
return data ? data->asString(getResourceManager(src)).c_str() : 0;
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
@@ -178,7 +178,7 @@ struct Converter<JsonString> : private detail::VariantAttorney {
|
||||
|
||||
static JsonString fromJson(JsonVariantConst src) {
|
||||
auto data = getData(src);
|
||||
return data ? data->asString() : JsonString();
|
||||
return data ? data->asString(getResourceManager(src)) : JsonString();
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
|
||||
@@ -56,13 +56,10 @@ union VariantContent {
|
||||
bool asBoolean;
|
||||
uint32_t asUint32;
|
||||
int32_t asInt32;
|
||||
#if ARDUINOJSON_USE_EXTENSIONS
|
||||
SlotId asSlotId;
|
||||
#endif
|
||||
ArrayData asArray;
|
||||
ObjectData asObject;
|
||||
CollectionData asCollection;
|
||||
const char* asLinkedString;
|
||||
struct StringNode* asOwnedString;
|
||||
char asTinyString[tinyStringMaxLength + 1];
|
||||
};
|
||||
|
||||
@@ -77,7 +77,7 @@ class VariantData {
|
||||
return visit.visit(JsonString(content_.asTinyString));
|
||||
|
||||
case VariantType::LinkedString:
|
||||
return visit.visit(JsonString(content_.asLinkedString, true));
|
||||
return visit.visit(JsonString(asLinkedString(resources), true));
|
||||
|
||||
case VariantType::OwnedString:
|
||||
return visit.visit(JsonString(content_.asOwnedString->data,
|
||||
@@ -216,7 +216,7 @@ class VariantData {
|
||||
str = content_.asTinyString;
|
||||
break;
|
||||
case VariantType::LinkedString:
|
||||
str = content_.asLinkedString;
|
||||
str = asLinkedString(resources);
|
||||
break;
|
||||
case VariantType::OwnedString:
|
||||
str = content_.asOwnedString->data;
|
||||
@@ -261,7 +261,7 @@ class VariantData {
|
||||
str = content_.asTinyString;
|
||||
break;
|
||||
case VariantType::LinkedString:
|
||||
str = content_.asLinkedString;
|
||||
str = asLinkedString(resources);
|
||||
break;
|
||||
case VariantType::OwnedString:
|
||||
str = content_.asOwnedString->data;
|
||||
@@ -298,12 +298,14 @@ class VariantData {
|
||||
}
|
||||
}
|
||||
|
||||
JsonString asString() const {
|
||||
const char* asLinkedString(const ResourceManager* resources) const;
|
||||
|
||||
JsonString asString(const ResourceManager* resources) const {
|
||||
switch (type_) {
|
||||
case VariantType::TinyString:
|
||||
return JsonString(content_.asTinyString);
|
||||
case VariantType::LinkedString:
|
||||
return JsonString(content_.asLinkedString, true);
|
||||
return JsonString(asLinkedString(resources), true);
|
||||
case VariantType::OwnedString:
|
||||
return JsonString(content_.asOwnedString->data,
|
||||
content_.asOwnedString->length);
|
||||
@@ -519,12 +521,7 @@ class VariantData {
|
||||
var->setString(value, resources);
|
||||
}
|
||||
|
||||
void setLinkedString(const char* s) {
|
||||
ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
|
||||
ARDUINOJSON_ASSERT(s);
|
||||
type_ = VariantType::LinkedString;
|
||||
content_.asLinkedString = s;
|
||||
}
|
||||
bool setLinkedString(const char* s, ResourceManager* resources);
|
||||
|
||||
template <typename TAdaptedString>
|
||||
void setTinyString(const TAdaptedString& s) {
|
||||
|
||||
@@ -18,6 +18,20 @@ inline void VariantData::setRawString(SerializedValue<T> value,
|
||||
setRawString(dup);
|
||||
}
|
||||
|
||||
inline bool VariantData::setLinkedString(const char* s,
|
||||
ResourceManager* resources) {
|
||||
ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
|
||||
ARDUINOJSON_ASSERT(s);
|
||||
|
||||
auto slotId = resources->saveStaticString(s);
|
||||
if (slotId == NULL_SLOT)
|
||||
return false;
|
||||
|
||||
type_ = VariantType::LinkedString;
|
||||
content_.asSlotId = slotId;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
inline bool VariantData::setString(TAdaptedString value,
|
||||
ResourceManager* resources) {
|
||||
@@ -26,10 +40,8 @@ inline bool VariantData::setString(TAdaptedString value,
|
||||
if (value.isNull())
|
||||
return false;
|
||||
|
||||
if (value.isStatic()) {
|
||||
setLinkedString(value.data());
|
||||
return true;
|
||||
}
|
||||
if (value.isStatic())
|
||||
return setLinkedString(value.data(), resources);
|
||||
|
||||
if (isTinyString(value, value.size())) {
|
||||
setTinyString(value);
|
||||
@@ -70,6 +82,12 @@ inline const VariantExtension* VariantData::getExtension(
|
||||
}
|
||||
#endif
|
||||
|
||||
inline const char* VariantData::asLinkedString(
|
||||
const ResourceManager* resources) const {
|
||||
ARDUINOJSON_ASSERT(type_ == VariantType::LinkedString);
|
||||
return resources->getStaticString(content_.asSlotId);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
enable_if_t<sizeof(T) == 8, bool> VariantData::setFloat(
|
||||
T value, ResourceManager* resources) {
|
||||
|
||||
Reference in New Issue
Block a user