summaryrefslogtreecommitdiff
path: root/src/interned_string.cc
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2014-10-01 00:20:12 +0100
committerMaxime Coste <frrrwww@gmail.com>2014-10-01 00:20:12 +0100
commitd55d041c6aa9941cc74853e4b2bf6620773c84c1 (patch)
tree702ed4e245190845036d7523523fd0729ceeba81 /src/interned_string.cc
parentd9e462851c4b18b80b478956ed20fb0be8a1d640 (diff)
Add support for interned strings
Use interned strings for Modification contents and word database. Interned strings are guaranteed not to move in memory and are reference counted.
Diffstat (limited to 'src/interned_string.cc')
-rw-r--r--src/interned_string.cc50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/interned_string.cc b/src/interned_string.cc
new file mode 100644
index 00000000..b8825f66
--- /dev/null
+++ b/src/interned_string.cc
@@ -0,0 +1,50 @@
+#include "interned_string.hh"
+
+namespace Kakoune
+{
+
+InternedString StringRegistry::acquire(StringView str)
+{
+ auto it = m_slot_map.find(str);
+ if (it == m_slot_map.end())
+ {
+ size_t slot;
+ if (not m_free_slots.empty())
+ {
+ slot = m_free_slots.back();
+ m_free_slots.pop_back();
+ m_storage[slot] = DataAndRefCount({str.begin(), str.end()}, 1);
+ }
+ else
+ {
+ slot = m_storage.size();
+ m_storage.push_back(DataAndRefCount({str.begin(), str.end()}, 1));
+ }
+ // Create a new string view that point to the storage data
+ StringView storage_view{m_storage[slot].first.data(), (int)m_storage[slot].first.size()};
+ m_slot_map[storage_view] = slot;
+
+ return InternedString{storage_view, InternedString::AlreadyAcquired{}};
+ }
+
+ size_t slot = it->second;
+ m_storage[slot].second++;
+ StringView storage_view{m_storage[slot].first.data(), (int)m_storage[slot].first.size()};
+ return InternedString{storage_view, InternedString::AlreadyAcquired{}};
+}
+
+void StringRegistry::release(StringView str)
+{
+ auto it = m_slot_map.find(str);
+ kak_assert(it != m_slot_map.end());
+
+ size_t slot = it->second;
+ if (--m_storage[slot].second == 0)
+ {
+ m_free_slots.push_back(slot);
+ m_slot_map.erase(it);
+ m_storage[slot].first.clear();
+ }
+}
+
+}