InternedStrings know their slots

This commit is contained in:
Maxime Coste 2014-10-05 10:20:50 +01:00
parent d4a84125ef
commit 844c8f1ec4
3 changed files with 38 additions and 19 deletions

View File

@ -453,7 +453,7 @@ ByteCoord Buffer::char_next(ByteCoord coord) const
if (coord.column < m_lines[coord.line].length() - 1) if (coord.column < m_lines[coord.line].length() - 1)
{ {
auto line = m_lines[coord.line]; auto line = m_lines[coord.line];
coord.column += utf8::codepoint_size(line[(int)coord.column]); coord.column += utf8::codepoint_size(line[coord.column]);
// Handle invalid utf-8 // Handle invalid utf-8
if (coord.column >= line.length()) if (coord.column >= line.length())
{ {

View File

@ -24,26 +24,32 @@ InternedString StringRegistry::acquire(StringView str)
StringView storage_view{m_storage[slot].first.data(), (int)m_storage[slot].first.size()}; StringView storage_view{m_storage[slot].first.data(), (int)m_storage[slot].first.size()};
m_slot_map[storage_view] = slot; m_slot_map[storage_view] = slot;
return InternedString{storage_view, InternedString::AlreadyAcquired{}}; return InternedString{storage_view, slot};
} }
size_t slot = it->second; size_t slot = it->second;
m_storage[slot].second++; m_storage[slot].second++;
StringView storage_view{m_storage[slot].first.data(), (int)m_storage[slot].first.size()}; StringView storage_view{m_storage[slot].first.data(), (int)m_storage[slot].first.size()};
return InternedString{storage_view, InternedString::AlreadyAcquired{}}; return InternedString{storage_view, slot};
} }
void StringRegistry::release(StringView str) void StringRegistry::acquire(size_t slot)
{ {
auto it = m_slot_map.find(str); kak_assert(slot < m_storage.size());
kak_assert(it != m_slot_map.end()); kak_assert(m_storage[slot].second > 0);
++m_storage[slot].second;
}
size_t slot = it->second; void StringRegistry::release(size_t slot)
{
if (--m_storage[slot].second == 0) if (--m_storage[slot].second == 0)
{ {
m_free_slots.push_back(slot); m_free_slots.push_back(slot);
std::vector<char>& data = m_storage[slot].first;
auto it = m_slot_map.find(StringView{data.data(), (int)data.size()});
kak_assert(it != m_slot_map.end());
m_slot_map.erase(it); m_slot_map.erase(it);
m_storage[slot].first.clear(); data.clear();
} }
} }

View File

@ -17,7 +17,8 @@ private:
friend class InternedString; friend class InternedString;
InternedString acquire(StringView str); InternedString acquire(StringView str);
void release(StringView str); void acquire(size_t slot);
void release(size_t slot);
std::unordered_map<StringView, size_t> m_slot_map; std::unordered_map<StringView, size_t> m_slot_map;
std::vector<size_t> m_free_slots; std::vector<size_t> m_free_slots;
@ -34,26 +35,34 @@ public:
InternedString(InternedString&& str) : StringView(str) InternedString(InternedString&& str) : StringView(str)
{ {
static_cast<StringView&>(str) = StringView{}; m_slot = str.m_slot;
str.m_slot = -1;
} }
InternedString(const char* str) : StringView() { acquire_ifn(str); } InternedString(const char* str) : StringView() { acquire_ifn(str); }
InternedString(StringView str) : StringView() { acquire_ifn(str); } InternedString(StringView str) : StringView() { acquire_ifn(str); }
//InternedString(const String& str) : StringView() { acquire_ifn(str); }
InternedString& operator=(const InternedString& str) InternedString& operator=(const InternedString& str)
{ {
if (str.data() == data() && str.length() == length()) if (str.data() == data() && str.length() == length())
return *this; return *this;
release_ifn(); static_cast<StringView&>(*this) = str;
acquire_ifn(str); if (str.m_slot != m_slot)
{
release_ifn();
m_slot = str.m_slot;
if (str.m_slot != -1)
StringRegistry::instance().acquire(str.m_slot);
}
return *this; return *this;
} }
InternedString& operator=(InternedString&& str) InternedString& operator=(InternedString&& str)
{ {
static_cast<StringView&>(*this) = str; static_cast<StringView&>(*this) = str;
static_cast<StringView&>(str) = StringView{}; m_slot = str.m_slot;
str.m_slot = -1;
return *this; return *this;
} }
@ -73,23 +82,27 @@ public:
private: private:
friend class StringRegistry; friend class StringRegistry;
struct AlreadyAcquired{}; InternedString(StringView str, size_t slot)
InternedString(StringView str, AlreadyAcquired) : StringView(str), m_slot(slot) {}
: StringView(str) {}
void acquire_ifn(StringView str) void acquire_ifn(StringView str)
{ {
if (str.empty()) if (str.empty())
{
static_cast<StringView&>(*this) = StringView{}; static_cast<StringView&>(*this) = StringView{};
m_slot = -1;
}
else else
*this = StringRegistry::instance().acquire(str); *this = StringRegistry::instance().acquire(str);
} }
void release_ifn() void release_ifn()
{ {
if (!empty()) if (m_slot != -1)
StringRegistry::instance().release(*this); StringRegistry::instance().release(m_slot);
} }
size_t m_slot = -1;
}; };
} }