Plasma Engine  2.0
Loading...
Searching...
No Matches
HashTable.h
1#pragma once
2
3#include <Foundation/Algorithm/HashingUtils.h>
4#include <Foundation/Math/Math.h>
5#include <Foundation/Memory/AllocatorWrapper.h>
6
7template <typename KeyType, typename ValueType, typename Hasher>
9
11template <typename KeyType, typename ValueType, typename Hasher>
13{
14 using iterator_category = std::forward_iterator_tag;
16 using difference_type = std::ptrdiff_t;
19
20 PL_DECLARE_POD_TYPE();
21
23 bool IsValid() const; // [tested]
24
26 bool operator==(const plHashTableBaseConstIterator& rhs) const;
27 PL_ADD_DEFAULT_OPERATOR_NOTEQUAL(const plHashTableBaseConstIterator&);
28
30 const KeyType& Key() const; // [tested]
31
33 const ValueType& Value() const; // [tested]
34
36 void Next(); // [tested]
37
39 void operator++(); // [tested]
40
42 PL_ALWAYS_INLINE plHashTableBaseConstIterator& operator*() { return *this; } // [tested]
43
44protected:
45 friend class plHashTableBase<KeyType, ValueType, Hasher>;
46
48 void SetToBegin();
49 void SetToEnd();
50
51 const plHashTableBase<KeyType, ValueType, Hasher>* m_pHashTable = nullptr;
52 plUInt32 m_uiCurrentIndex = 0; // current element index that this iterator points to.
53 plUInt32 m_uiCurrentCount = 0; // current number of valid elements that this iterator has found so far.
54
55#if PL_ENABLED(PL_USE_CPP20_OPERATORS)
56public:
57 struct Pointer
58 {
59 std::pair<const KeyType&, const ValueType&> value;
60 const std::pair<const KeyType&, const ValueType&>* operator->() const { return &value; }
61 };
62
63 PL_ALWAYS_INLINE Pointer operator->() const
64 {
65 return Pointer{.value = {Key(), Value()}};
66 }
67
68 // These function is used to return the values for structured bindings.
69 // The number and type of type of each slot are defined in the inl file.
70 template <std::size_t Index>
71 std::tuple_element_t<Index, plHashTableBaseConstIterator>& get() const
72 {
73 if constexpr (Index == 0)
74 return Key();
75 if constexpr (Index == 1)
76 return Value();
77 }
78#endif
79};
80
82template <typename KeyType, typename ValueType, typename Hasher>
83struct plHashTableBaseIterator : public plHashTableBaseConstIterator<KeyType, ValueType, Hasher>
84{
85 PL_DECLARE_POD_TYPE();
86
88 PL_ALWAYS_INLINE plHashTableBaseIterator(const plHashTableBaseIterator& rhs); // [tested]
89
91 PL_ALWAYS_INLINE void operator=(const plHashTableBaseIterator& rhs); // [tested]
92
93 // this is required to pull in the const version of this function
94 using plHashTableBaseConstIterator<KeyType, ValueType, Hasher>::Value;
95
97 PL_FORCE_INLINE ValueType& Value(); // [tested]
98
100 PL_FORCE_INLINE ValueType& Value() const;
101
103 PL_ALWAYS_INLINE plHashTableBaseIterator& operator*() { return *this; } // [tested]
104
105private:
106 friend class plHashTableBase<KeyType, ValueType, Hasher>;
107
109
110#if PL_ENABLED(PL_USE_CPP20_OPERATORS)
111public:
112 struct Pointer
113 {
114 std::pair<const KeyType&, ValueType&> value;
115 const std::pair<const KeyType&, ValueType&>* operator->() const { return &value; }
116 };
117
118 PL_ALWAYS_INLINE Pointer operator->() const
119 {
121 }
122
123 // These functions are used to return the values for structured bindings.
124 // The number and type of type of each slot are defined in the inl file.
125 template <std::size_t Index>
126 std::tuple_element_t<Index, plHashTableBaseIterator>& get()
127 {
128 if constexpr (Index == 0)
130 if constexpr (Index == 1)
131 return Value();
132 }
133
134 template <std::size_t Index>
135 std::tuple_element_t<Index, plHashTableBaseIterator>& get() const
136 {
137 if constexpr (Index == 0)
139 if constexpr (Index == 1)
140 return Value();
141 }
142#endif
143};
144
153
155template <typename KeyType, typename ValueType, typename Hasher>
157{
158public:
161
162protected:
164 explicit plHashTableBase(plAllocator* pAllocator); // [tested]
165
168
171
173 ~plHashTableBase(); // [tested]
174
177
180
181public:
183 bool operator==(const plHashTableBase<KeyType, ValueType, Hasher>& rhs) const; // [tested]
184 PL_ADD_DEFAULT_OPERATOR_NOTEQUAL(const plHashTableBase<KeyType, ValueType, Hasher>&);
185
188 void Reserve(plUInt32 uiCapacity); // [tested]
189
194 void Compact(); // [tested]
195
197 plUInt32 GetCount() const; // [tested]
198
200 bool IsEmpty() const; // [tested]
201
203 void Clear(); // [tested]
204
208 template <typename CompatibleKeyType, typename CompatibleValueType>
209 bool Insert(CompatibleKeyType&& key, CompatibleValueType&& value, ValueType* out_pOldValue = nullptr); // [tested]
210
212 template <typename CompatibleKeyType>
213 bool Remove(const CompatibleKeyType& key, ValueType* out_pOldValue = nullptr); // [tested]
214
216 Iterator Remove(const Iterator& pos); // [tested]
217
219 void Remove(const ConstIterator& pos) = delete;
220
222 template <typename CompatibleKeyType>
223 bool TryGetValue(const CompatibleKeyType& key, ValueType& out_value) const; // [tested]
224
226 template <typename CompatibleKeyType>
227 bool TryGetValue(const CompatibleKeyType& key, const ValueType*& out_pValue) const; // [tested]
228
230 template <typename CompatibleKeyType>
231 bool TryGetValue(const CompatibleKeyType& key, ValueType*& out_pValue) const; // [tested]
232
234 template <typename CompatibleKeyType>
235 ConstIterator Find(const CompatibleKeyType& key) const;
236
238 template <typename CompatibleKeyType>
239 Iterator Find(const CompatibleKeyType& key);
240
242 template <typename CompatibleKeyType>
243 const ValueType* GetValue(const CompatibleKeyType& key) const; // [tested]
244
246 template <typename CompatibleKeyType>
247 ValueType* GetValue(const CompatibleKeyType& key); // [tested]
248
250 ValueType& operator[](const KeyType& key); // [tested]
251
253 ValueType& FindOrAdd(const KeyType& key, bool* out_pExisted = nullptr); // [tested]
254
256 template <typename CompatibleKeyType>
257 bool Contains(const CompatibleKeyType& key) const; // [tested]
258
260 Iterator GetIterator(); // [tested]
261
263 Iterator GetEndIterator(); // [tested]
264
266 ConstIterator GetIterator() const; // [tested]
267
269 ConstIterator GetEndIterator() const; // [tested]
270
272 plAllocator* GetAllocator() const;
273
275 plUInt64 GetHeapMemoryUsage() const; // [tested]
276
278 void Swap(plHashTableBase<KeyType, ValueType, Hasher>& other); // [tested]
279
280private:
281 friend struct plHashTableBaseConstIterator<KeyType, ValueType, Hasher>;
282 friend struct plHashTableBaseIterator<KeyType, ValueType, Hasher>;
283
284 struct Entry
285 {
286 KeyType key;
287 ValueType value;
288 };
289
290 Entry* m_pEntries = nullptr;
291 plUInt32* m_pEntryFlags = nullptr;
292
293 plUInt32 m_uiCount = 0;
294 plUInt32 m_uiCapacity = 0;
295
296 plAllocator* m_pAllocator = nullptr;
297
298 enum
299 {
300 FREE_ENTRY = 0,
301 VALID_ENTRY = 1,
302 DELETED_ENTRY = 2,
303 FLAGS_MASK = 3,
304 CAPACITY_ALIGNMENT = 32
305 };
306
307 void SetCapacity(plUInt32 uiCapacity);
308
309 void RemoveInternal(plUInt32 uiIndex);
310
311 template <typename CompatibleKeyType>
312 plUInt32 FindEntry(const CompatibleKeyType& key) const;
313
314 template <typename CompatibleKeyType>
315 plUInt32 FindEntry(plUInt32 uiHash, const CompatibleKeyType& key) const;
316
317 plUInt32 GetFlagsCapacity() const;
318 plUInt32 GetFlags(plUInt32* pFlags, plUInt32 uiEntryIndex) const;
319 void SetFlags(plUInt32 uiEntryIndex, plUInt32 uiFlags);
320
321 bool IsFreeEntry(plUInt32 uiEntryIndex) const;
322 bool IsValidEntry(plUInt32 uiEntryIndex) const;
323 bool IsDeletedEntry(plUInt32 uiEntryIndex) const;
324
325 void MarkEntryAsFree(plUInt32 uiEntryIndex);
326 void MarkEntryAsValid(plUInt32 uiEntryIndex);
327 void MarkEntryAsDeleted(plUInt32 uiEntryIndex);
328};
329
331template <typename KeyType, typename ValueType, typename Hasher = plHashHelper<KeyType>, typename AllocatorWrapper = plDefaultAllocatorWrapper>
351
353// begin() /end() for range-based for-loop support
354
355template <typename KeyType, typename ValueType, typename Hasher>
357{
358 return ref_container.GetIterator();
359}
360
361template <typename KeyType, typename ValueType, typename Hasher>
363{
364 return container.GetIterator();
365}
366
367template <typename KeyType, typename ValueType, typename Hasher>
369{
370 return container.GetIterator();
371}
372
373template <typename KeyType, typename ValueType, typename Hasher>
375{
376 return ref_container.GetEndIterator();
377}
378
379template <typename KeyType, typename ValueType, typename Hasher>
381{
382 return container.GetEndIterator();
383}
384
385template <typename KeyType, typename ValueType, typename Hasher>
387{
388 return container.GetEndIterator();
389}
390
391#include <Foundation/Containers/Implementation/HashTable_inl.h>
Base class for all memory allocators.
Definition Allocator.h:23
Implementation of a hashtable which stores key/value pairs.
Definition HashTable.h:157
bool TryGetValue(const CompatibleKeyType &key, const ValueType *&out_pValue) const
Returns whether an entry with the given key was found and if found writes out the pointer to the corr...
bool operator==(const plHashTableBase< KeyType, ValueType, Hasher > &rhs) const
Compares this table to another table.
Definition HashTable_inl.h:282
ValueType & FindOrAdd(const KeyType &key, bool *out_pExisted=nullptr)
Returns the value stored at the given key. If none exists, one is created. bExisted indicates whether...
Definition HashTable_inl.h:583
Iterator GetIterator()
Returns an Iterator to the very first element.
Definition HashTable_inl.h:625
plAllocator * GetAllocator() const
Returns the allocator that is used by this instance.
Definition HashTable_inl.h:657
bool Contains(const CompatibleKeyType &key) const
Returns if an entry with given key exists in the table.
void Remove(const ConstIterator &pos)=delete
Cannot remove an element with just a plHashTableBaseConstIterator.
plUInt64 GetHeapMemoryUsage() const
Returns the amount of bytes that are currently allocated on the heap.
Definition HashTable_inl.h:663
void operator=(const plHashTableBase< KeyType, ValueType, Hasher > &rhs)
Copies the data from another hashtable into this one.
plUInt32 GetCount() const
Returns the number of active entries in the table.
Definition HashTable_inl.h:343
bool TryGetValue(const CompatibleKeyType &key, ValueType &out_value) const
Returns whether an entry with the given key was found and if found writes out the corresponding value...
ValueType & operator[](const KeyType &key)
Returns the value to the given key if found or creates a new entry with the given key and a default c...
Definition HashTable_inl.h:577
const ValueType * GetValue(const CompatibleKeyType &key) const
Returns a pointer to the value of the entry with the given key if found, otherwise returns nullptr.
ConstIterator Find(const CompatibleKeyType &key) const
Searches for key, returns a plHashTableBaseConstIterator to it or an invalid iterator,...
Definition HashTable_inl.h:528
Iterator Remove(const Iterator &pos)
Erases the key/value pair at the given Iterator. Returns an iterator to the element after the given i...
~plHashTableBase()
Destructor.
Definition HashTable_inl.h:215
Iterator GetEndIterator()
Returns an Iterator to the first element that is not part of the hash-table. Needed to support range ...
Definition HashTable_inl.h:633
void Compact()
Tries to compact the hashtable to avoid wasting memory.
Definition HashTable_inl.h:325
plHashTableBase(plHashTableBase< KeyType, ValueType, Hasher > &&rhs, plAllocator *pAllocator)
Moves data from an existing hashtable into this one.
bool IsEmpty() const
Returns true, if the hashtable does not contain any elements.
Definition HashTable_inl.h:349
bool Insert(CompatibleKeyType &&key, CompatibleValueType &&value, ValueType *out_pOldValue=nullptr)
Inserts the key value pair or replaces value if an entry with the given key already exists.
plHashTableBase(const plHashTableBase< KeyType, ValueType, Hasher > &rhs, plAllocator *pAllocator)
Creates a copy of the given hashtable.
void Clear()
Clears the table.
Definition HashTable_inl.h:355
void Reserve(plUInt32 uiCapacity)
Expands the hashtable by over-allocating the internal storage so that the load factor is lower or equ...
Definition HashTable_inl.h:307
void operator=(plHashTableBase< KeyType, ValueType, Hasher > &&rhs)
Moves data from an existing hashtable into this one.
bool Remove(const CompatibleKeyType &key, ValueType *out_pOldValue=nullptr)
Removes the entry with the given key. Returns whether an entry was removed and optionally writes out ...
bool TryGetValue(const CompatibleKeyType &key, ValueType *&out_pValue) const
Returns whether an entry with the given key was found and if found writes out the pointer to the corr...
void Swap(plHashTableBase< KeyType, ValueType, Hasher > &other)
Swaps this map with the other one.
Definition HashTable_inl.h:867
plHashTableBase(plAllocator *pAllocator)
Creates an empty hashtable. Does not allocate any data yet.
Definition HashTable_inl.h:181
ValueType * GetValue(const CompatibleKeyType &key)
Returns a pointer to the value of the entry with the given key if found, otherwise returns nullptr.
Definition HashTable.h:333
Const iterator.
Definition HashTable.h:13
void operator++()
Shorthand for 'Next'.
Definition HashTable_inl.h:88
void Next()
Advances the iterator to the next element in the map. The iterator will not be valid anymore,...
Definition HashTable_inl.h:62
PL_ALWAYS_INLINE plHashTableBaseConstIterator & operator*()
Returns '*this' to enable foreach.
Definition HashTable.h:42
const ValueType & Value() const
Returns the 'value' of the element that this iterator points to.
Definition HashTable_inl.h:56
const KeyType & Key() const
Returns the 'key' of the element that this iterator points to.
Definition HashTable_inl.h:50
bool IsValid() const
Checks whether this iterator points to a valid element.
Definition HashTable_inl.h:38
bool operator==(const plHashTableBaseConstIterator &rhs) const
Checks whether the two iterators point to the same element.
Definition HashTable_inl.h:44
Iterator with write access.
Definition HashTable.h:84
PL_ALWAYS_INLINE plHashTableBaseIterator & operator*()
Returns '*this' to enable foreach.
Definition HashTable.h:103
PL_ALWAYS_INLINE plHashTableBaseIterator(const plHashTableBaseIterator &rhs)
Creates a new iterator from another.
PL_ALWAYS_INLINE void operator=(const plHashTableBaseIterator &rhs)
Assigns one iterator no another.
Definition HashTable_inl.h:134
PL_FORCE_INLINE ValueType & Value()
Returns the 'value' of the element that this iterator points to.
Definition HashTable_inl.h:142