16template <
typename T_Key,
typename T_Entry>
17struct GrowingHashmap {
18 using key_type = T_Key;
19 using value_type = T_Entry;
20 using size_type =
unsigned int;
23 static constexpr size_type min_size = 8;
26 value_type value = value_type();
35 GrowingHashmap() : used(0), fill(0), mask(-1), m_map(nullptr)
42 GrowingHashmap(
const GrowingHashmap& other) : used(other.used), fill(other.fill), mask(other.mask)
45 m_map =
new MapElem[size];
46 std::copy(other.m_map, other.m_map + size, m_map);
49 GrowingHashmap(GrowingHashmap&& other) noexcept : GrowingHashmap()
54 GrowingHashmap& operator=(GrowingHashmap other)
60 friend void swap(GrowingHashmap& first, GrowingHashmap& second)
noexcept
62 std::swap(first.used, second.used);
63 std::swap(first.fill, second.fill);
64 std::swap(first.mask, second.mask);
65 std::swap(first.m_map, second.m_map);
68 size_type size()
const
72 size_type capacity()
const
81 value_type get(key_type key)
const noexcept
83 if (m_map ==
nullptr)
return value_type();
85 return m_map[lookup(key)].value;
88 value_type& operator[](key_type key)
noexcept
90 if (m_map ==
nullptr) allocate();
92 size_t i = lookup(key);
94 if (m_map[i].value == value_type()) {
96 if (++fill * 3 >= (mask + 1) * 2) {
105 return m_map[i].value;
112 m_map =
new MapElem[min_size];
119 size_t lookup(key_type key)
const
121 size_t hash =
static_cast<size_t>(key);
122 size_t i = hash &
static_cast<size_t>(mask);
124 if (m_map[i].value == value_type() || m_map[i].key == key)
return i;
126 size_t perturb = hash;
128 i = (i * 5 + perturb + 1) &
static_cast<size_t>(mask);
129 if (m_map[i].value == value_type() || m_map[i].key == key)
return i;
135 void grow(
int minUsed)
137 int newSize = mask + 1;
138 while (newSize <= minUsed)
141 MapElem* oldMap = m_map;
142 m_map =
new MapElem[
static_cast<size_t>(newSize)];
147 for (
int i = 0; used > 0; i++)
148 if (oldMap[i].value != value_type()) {
149 size_t j = lookup(oldMap[i].key);
151 m_map[j].key = oldMap[i].key;
152 m_map[j].value = oldMap[i].value;
161template <
typename T_Key,
typename T_Entry>
162struct HybridGrowingHashmap {
163 using key_type = T_Key;
164 using value_type = T_Entry;
166 HybridGrowingHashmap()
168 m_extendedAscii.fill(value_type());
171 value_type get(
char key)
const noexcept
174 return m_extendedAscii[
static_cast<uint8_t
>(key)];
177 template <
typename CharT>
178 value_type get(CharT key)
const noexcept
180 if (key >= 0 && key <= 255)
181 return m_extendedAscii[
static_cast<uint8_t
>(key)];
183 return m_map.get(
static_cast<key_type
>(key));
186 value_type& operator[](
char key)
noexcept
189 return m_extendedAscii[
static_cast<uint8_t
>(key)];
192 template <
typename CharT>
193 value_type& operator[](CharT key)
195 if (key >= 0 && key <= 255)
196 return m_extendedAscii[
static_cast<uint8_t
>(key)];
198 return m_map[
static_cast<key_type
>(key)];
202 GrowingHashmap<key_type, value_type> m_map;
203 std::array<value_type, 256> m_extendedAscii;