74 Entry() : hashCode(-1), next(-1) {}
75 Entry(
int h,
int n,
const TKey& k,
const TValue& v) : hashCode(h), next(n), key(k), value(v) {}
76 Entry(
const Entry& other) : hashCode(other.hashCode), next(other.next), key(other.key), value(other.value) {}
77 Entry(Entry&& other) noexcept : hashCode(other.hashCode), next(other.next), key(std::move(other.key)), value(std::move(other.value)) {}
87 void Initialize(
int capacity) {
90 for (
int i = 0; i < m_iCapacity; i++) m_pBuckets[i] = -1;
100 for (
int i = 0; i < m_iCount; ++i) {
101 if (m_pEntries[i].hashCode >= 0) m_pEntries[i].~Entry();
105 m_pBuckets =
nullptr;
106 m_pEntries =
nullptr;
110 Resize(m_iCount > 0 ? m_iCount * 2 : 4);
113 void Resize(
int newSize) {
116 for (
int i = 0; i < newCapacity; i++) pNewBuckets[i] = -1;
118 for (
int i = 0; i < m_iCount; i++) {
119 if (m_pEntries[i].hashCode >= 0) {
120 ::new ((
void*)&pNewEntries[i]) Entry(std::move(m_pEntries[i]));
121 m_pEntries[i].~Entry();
123 ::new ((
void*)&pNewEntries[i]) Entry();
126 for (
int i = 0; i < m_iCount; i++) {
127 if (pNewEntries[i].hashCode >= 0) {
128 int bucket = pNewEntries[i].hashCode % newCapacity;
129 pNewEntries[i].next = pNewBuckets[bucket];
130 pNewBuckets[bucket] = i;
135 m_pBuckets = pNewBuckets;
136 m_pEntries = pNewEntries;
137 m_iCapacity = newCapacity;
140 int FindEntry(
const TKey& key)
const {
141 if (m_pBuckets !=
nullptr) {
143 for (
int i = m_pBuckets[hashCode % m_iCapacity]; i >= 0; i = m_pEntries[i].next) {
144 if (m_pEntries[i].hashCode == hashCode && m_pEntries[i].key == key)
return i;
150 bool Insert(
const TKey& key,
const TValue& value,
bool add) {
151 if (m_pBuckets ==
nullptr) Initialize(0);
153 int targetBucket = hashCode % m_iCapacity;
155 for (
int i = m_pBuckets[targetBucket]; i >= 0; i = m_pEntries[i].next) {
156 if (m_pEntries[i].hashCode == hashCode && m_pEntries[i].key == key) {
158 m_pEntries[i].value = value;
164 if (m_iFreeCount > 0) {
166 m_iFreeList = m_pEntries[index].next;
169 if (m_iCount == m_iCapacity) {
171 targetBucket = hashCode % m_iCapacity;
176 ::new ((
void*)&m_pEntries[index]) Entry(hashCode, m_pBuckets[targetBucket], key, value);
177 m_pBuckets[targetBucket] = index;
182 Dictionary() : m_pBuckets(nullptr), m_pEntries(nullptr), m_iCount(0), m_iFreeList(-1), m_iFreeCount(0), m_iCapacity(0) {}
189 if (other.m_iCount > 0) {
190 Initialize(other.m_iCount);
191 for (int i = 0; i < other.m_iCount; i++) {
192 if (other.m_pEntries[i].hashCode >= 0) {
193 Add(other.m_pEntries[i].key, other.m_pEntries[i].value);
200 if (
this != &other) {
202 if (other.m_iCount > 0) {
203 Initialize(other.m_iCount);
204 for (
int i = 0; i < other.m_iCount; i++) {
205 if (other.m_pEntries[i].hashCode >= 0) {
206 Add(other.m_pEntries[i].key, other.m_pEntries[i].value);
214 Dictionary(
Dictionary&& other) noexcept : m_pBuckets(other.m_pBuckets), m_pEntries(other.m_pEntries), m_iCount(other.m_iCount), m_iFreeList(other.m_iFreeList), m_iFreeCount(other.m_iFreeCount), m_iCapacity(other.m_iCapacity) {
215 other.m_pBuckets =
nullptr;
216 other.m_pEntries =
nullptr;
218 other.m_iFreeList = -1;
219 other.m_iFreeCount = 0;
220 other.m_iCapacity = 0;
224 if (
this != &other) {
226 m_pBuckets = other.m_pBuckets;
227 m_pEntries = other.m_pEntries;
228 m_iCount = other.m_iCount;
229 m_iFreeList = other.m_iFreeList;
230 m_iFreeCount = other.m_iFreeCount;
231 m_iCapacity = other.m_iCapacity;
232 other.m_pBuckets =
nullptr;
233 other.m_pEntries =
nullptr;
235 other.m_iFreeList = -1;
236 other.m_iFreeCount = 0;
237 other.m_iCapacity = 0;
242 int GetCount()
const {
return m_iCount - m_iFreeCount; }
244 void Add(
const TKey& key,
const TValue& value) {
245 Insert(key, value,
true);
249 if (m_pBuckets !=
nullptr) {
251 int bucket = hashCode % m_iCapacity;
253 for (
int i = m_pBuckets[bucket]; i >= 0; last = i, i = m_pEntries[i].next) {
254 if (m_pEntries[i].hashCode == hashCode && m_pEntries[i].key == key) {
255 if (last < 0) m_pBuckets[bucket] = m_pEntries[i].next;
256 else m_pEntries[last].next = m_pEntries[i].next;
257 m_pEntries[i].~Entry();
258 m_pEntries[i].hashCode = -1;
259 m_pEntries[i].next = m_iFreeList;
271 for (
int i = 0; i < m_iCapacity; i++) m_pBuckets[i] = -1;
272 for (
int i = 0; i < m_iCount; i++) {
273 if (m_pEntries[i].hashCode >= 0) m_pEntries[i].~Entry();
282 return FindEntry(key) >= 0;
286 int i = FindEntry(key);
288 value = m_pEntries[i].value;
295 int i = FindEntry(key);
296 if (i >= 0)
return m_pEntries[i].value;
297 Insert(key, TValue(),
false);
298 return m_pEntries[FindEntry(key)].value;
302 int i = FindEntry(key);
303 if (i >= 0)
return m_pEntries[i].value;
310 for (
int i = 0; i < m_iCount; ++i) {
311 if (m_pEntries[i].hashCode >= 0) arrKeys[index++] = m_pEntries[i].key;
319 for (
int i = 0; i < m_iCount; ++i) {
320 if (m_pEntries[i].hashCode >= 0) arrValues[index++] = m_pEntries[i].value;
329 void AdvanceToValid() {
330 while (m_pDict && m_iIndex < m_pDict->m_iCount && m_pDict->m_pEntries[m_iIndex].hashCode < 0) {