summaryrefslogtreecommitdiff
path: root/src/interned_string.cc
blob: 2f2f56f8566165efa1d7357e5543544d63d953f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#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();
            kak_assert(m_storage[slot].second == 0);
            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, slot};
    }

    size_t slot = it->second;
    auto& data = m_storage[slot];
    ++data.second;
    return {{data.first.data(), (int)data.first.size()}, slot};
}

void StringRegistry::acquire(size_t slot)
{
    kak_assert(slot < m_storage.size());
    kak_assert(m_storage[slot].second > 0);
    ++m_storage[slot].second;
}

void StringRegistry::release(size_t slot) noexcept
{
    kak_assert(m_storage[slot].second > 0);
    if (--m_storage[slot].second == 0)
    {
        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);
        data = std::vector<char>{};
    }
}

}