Skip to content

Commit ee144b8

Browse files
committed
Deduplicate static strings
1 parent 08b2400 commit ee144b8

File tree

5 files changed

+61
-3
lines changed

5 files changed

+61
-3
lines changed

extras/tests/JsonDocument/MemberProxy.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,24 @@ TEST_CASE("Deduplicate keys") {
382382
Allocate(sizeofString("example")),
383383
});
384384
}
385+
386+
SECTION("string literals") {
387+
doc[0]["example"] = 1;
388+
doc[1]["example"] = 2;
389+
doc.shrinkToFit();
390+
391+
const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
392+
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
393+
CHECK(key1 == key2);
394+
395+
REQUIRE(spy.log() ==
396+
AllocatorLog{
397+
Allocate(sizeofPool()),
398+
Allocate(sizeofStaticStringPool()),
399+
Reallocate(sizeofPool(), sizeofPool(6)),
400+
Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(1)),
401+
});
402+
}
385403
}
386404

387405
TEST_CASE("MemberProxy under memory constraints") {

extras/tests/ResourceManager/saveString.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,25 @@ static StringNode* saveString(ResourceManager& resources, const char* s,
1919
return resources.saveString(adaptString(s, n));
2020
}
2121

22+
TEST_CASE("ResourceManager::saveStaticString()") {
23+
SpyingAllocator spy;
24+
ResourceManager resources(&spy);
25+
26+
auto a = resources.saveStaticString("hello");
27+
auto b = resources.saveStaticString("world");
28+
REQUIRE(a != b);
29+
30+
auto c = resources.saveStaticString("hello");
31+
REQUIRE(a == c);
32+
33+
resources.shrinkToFit();
34+
REQUIRE(spy.log() ==
35+
AllocatorLog{
36+
Allocate(sizeofStaticStringPool()),
37+
Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(2)),
38+
});
39+
}
40+
2241
TEST_CASE("ResourceManager::saveString()") {
2342
ResourceManager resources;
2443

src/ArduinoJson/Memory/MemoryPool.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ class MemoryPool {
8181
return slots_ + id;
8282
}
8383

84+
SlotId find(const T& value) const {
85+
for (SlotId i = 0; i < usage_; i++) {
86+
if (slots_[i] == value)
87+
return i;
88+
}
89+
return NULL_SLOT;
90+
}
91+
8492
void clear() {
8593
usage_ = 0;
8694
}

src/ArduinoJson/Memory/MemoryPoolList.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,15 @@ class MemoryPoolList {
114114
return pools_[poolIndex].getSlot(indexInPool);
115115
}
116116

117+
SlotId find(const T& value) const {
118+
for (PoolCount i = 0; i < count_; i++) {
119+
SlotId id = pools_[i].find(value);
120+
if (id != NULL_SLOT)
121+
return SlotId(i * ARDUINOJSON_POOL_CAPACITY + id);
122+
}
123+
return NULL_SLOT;
124+
}
125+
117126
void clear(Allocator* allocator) {
118127
for (PoolCount i = 0; i < count_; i++)
119128
pools_[i].destroy(allocator);

src/ArduinoJson/Memory/ResourceManager.hpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,14 @@ class ResourceManager {
114114
}
115115

116116
SlotId saveStaticString(const char* s) {
117+
auto existingSlotId = staticStringsPools_.find(s);
118+
if (existingSlotId != NULL_SLOT)
119+
return existingSlotId;
120+
117121
auto slot = staticStringsPools_.allocSlot(allocator_);
118-
if (!slot)
119-
return NULL_SLOT;
120-
*slot = s;
122+
if (slot)
123+
*slot = s;
124+
121125
return slot.id();
122126
}
123127

0 commit comments

Comments
 (0)