Plasma Engine  2.0
Loading...
Searching...
No Matches
Map.h
1#pragma once
2
3#include <Foundation/Containers/Deque.h>
4
5template <typename KeyType, typename ValueType, typename Comparer>
6class plMapBase;
7
9template <typename KeyType, typename ValueType, typename Comparer, bool REVERSE>
11{
12 using iterator_category = std::forward_iterator_tag;
14 using difference_type = std::ptrdiff_t;
17
18 PL_DECLARE_POD_TYPE();
19
21 PL_ALWAYS_INLINE plMapBaseConstIteratorBase()
22 : m_pElement(nullptr)
23 {
24 } // [tested]
25
27 PL_ALWAYS_INLINE bool IsValid() const { return (m_pElement != nullptr); } // [tested]
28
30 PL_ALWAYS_INLINE bool operator==(const plMapBaseConstIteratorBase& it2) const { return (m_pElement == it2.m_pElement); }
31 PL_ADD_DEFAULT_OPERATOR_NOTEQUAL(const plMapBaseConstIteratorBase&);
32
34 PL_FORCE_INLINE const KeyType& Key() const
35 {
36 PL_ASSERT_DEBUG(IsValid(), "Cannot access the 'key' of an invalid iterator.");
37 return m_pElement->m_Key;
38 } // [tested]
39
41 PL_FORCE_INLINE const ValueType& Value() const
42 {
43 PL_ASSERT_DEBUG(IsValid(), "Cannot access the 'value' of an invalid iterator.");
44 return m_pElement->m_Value;
45 } // [tested]
46
48 PL_ALWAYS_INLINE plMapBaseConstIteratorBase& operator*() { return *this; } // [tested]
49
51 void Next(); // [tested]
52
54 void Prev(); // [tested]
55
57 PL_ALWAYS_INLINE void operator++() { Next(); } // [tested]
58
60 PL_ALWAYS_INLINE void operator--() { Prev(); } // [tested]
61
62protected:
63 void Advance(const plInt32 dir0, const plInt32 dir1);
64
65 friend class plMapBase<KeyType, ValueType, Comparer>;
66
67 PL_ALWAYS_INLINE explicit plMapBaseConstIteratorBase(typename plMapBase<KeyType, ValueType, Comparer>::Node* pInit)
68 : m_pElement(pInit)
69 {
70 }
71
72 typename plMapBase<KeyType, ValueType, Comparer>::Node* m_pElement;
73
74#if PL_ENABLED(PL_USE_CPP20_OPERATORS)
75public:
76 struct Pointer
77 {
78 std::pair<const KeyType&, const ValueType&> value;
79 const std::pair<const KeyType&, const ValueType&>* operator->() const { return &value; }
80 };
81
82 PL_ALWAYS_INLINE Pointer operator->() const
83 {
84 return Pointer{.value = {Key(), Value()}};
85 }
86
87 // This function is used to return the values for structured bindings.
88 // The number and type of each slot are defined in the inl file.
89 template <std::size_t Index>
90 std::tuple_element_t<Index, plMapBaseConstIteratorBase>& get() const
91 {
92 if constexpr (Index == 0)
93 return Key();
94 if constexpr (Index == 1)
95 return Value();
96 }
97#endif
98};
99
101template <typename KeyType, typename ValueType, typename Comparer, bool REVERSE>
102struct plMapBaseIteratorBase : public plMapBaseConstIteratorBase<KeyType, ValueType, Comparer, REVERSE>
103{
104 using iterator_category = std::forward_iterator_tag;
106 using difference_type = std::ptrdiff_t;
109
110 PL_DECLARE_POD_TYPE();
111
113 PL_ALWAYS_INLINE plMapBaseIteratorBase()
114 : plMapBaseConstIteratorBase<KeyType, ValueType, Comparer, REVERSE>()
115 {
116 }
117
119 PL_FORCE_INLINE ValueType& Value()
120 {
121 PL_ASSERT_DEBUG(this->IsValid(), "Cannot access the 'value' of an invalid iterator.");
122 return this->m_pElement->m_Value;
123 }
124
126 PL_FORCE_INLINE ValueType& Value() const
127 {
128 PL_ASSERT_DEBUG(this->IsValid(), "Cannot access the 'value' of an invalid iterator.");
129 return this->m_pElement->m_Value;
130 }
131
133 PL_ALWAYS_INLINE plMapBaseIteratorBase& operator*() { return *this; } // [tested]
134
135private:
136 friend class plMapBase<KeyType, ValueType, Comparer>;
137
138 PL_ALWAYS_INLINE explicit plMapBaseIteratorBase(typename plMapBase<KeyType, ValueType, Comparer>::Node* pInit)
139 : plMapBaseConstIteratorBase<KeyType, ValueType, Comparer, REVERSE>(pInit)
140 {
141 }
142
143#if PL_ENABLED(PL_USE_CPP20_OPERATORS)
144public:
145 struct Pointer
146 {
147 std::pair<const KeyType&, ValueType&> value;
148 const std::pair<const KeyType&, ValueType&>* operator->() const { return &value; }
149 };
150
151 PL_ALWAYS_INLINE Pointer operator->() const
152 {
154 }
155
156
157 // These functions are used to return the values for structured bindings.
158 // The number and type of type of each slot are defined in the inl file.
159
160 template <std::size_t Index>
161 std::tuple_element_t<Index, plMapBaseIteratorBase>& get()
162 {
163 if constexpr (Index == 0)
165 if constexpr (Index == 1)
166 return Value();
167 }
168
169 template <std::size_t Index>
170 std::tuple_element_t<Index, plMapBaseIteratorBase>& get() const
171 {
172 if constexpr (Index == 0)
174 if constexpr (Index == 1)
175 return Value();
176 }
177#endif
178};
179
191template <typename KeyType, typename ValueType, typename Comparer>
193{
194
195public:
198
201
202private:
203 friend ConstIterator;
205 friend Iterator;
206 friend ReverseIterator;
207 struct Node;
208
210 struct NilNode
211 {
212 Node* m_pParent = nullptr;
213 Node* m_pLink[2] = {nullptr, nullptr};
214 plUInt8 m_uiLevel = 0;
215 };
216
218 struct Node : public NilNode
219 {
220 KeyType m_Key;
221 ValueType m_Value;
222 };
223
224protected:
226 plMapBase(const Comparer& comparer, plAllocator* pAllocator); // [tested]
227
229 plMapBase(const plMapBase<KeyType, ValueType, Comparer>& cc, plAllocator* pAllocator); // [tested]
230
232 ~plMapBase(); // [tested]
233
236
237public:
239 bool IsEmpty() const; // [tested]
240
242 plUInt32 GetCount() const; // [tested]
243
245 void Clear(); // [tested]
246
248 Iterator GetIterator(); // [tested]
249
252
254 ConstIterator GetIterator() const; // [tested]
255
257 ConstReverseIterator GetReverseIterator() const; // [tested]
258
260 template <typename CompatibleKeyType, typename CompatibleValueType>
261 Iterator Insert(CompatibleKeyType&& key, CompatibleValueType&& value); // [tested]
262
264 template <typename CompatibleKeyType>
265 bool Remove(const CompatibleKeyType& key); // [tested]
266
269 Iterator Remove(const Iterator& pos); // [tested]
270
273 template <typename CompatibleKeyType>
274 Iterator FindOrAdd(CompatibleKeyType&& key, bool* out_pExisted = nullptr); // [tested]
275
278 template <typename CompatibleKeyType>
279 ValueType& operator[](const CompatibleKeyType& key); // [tested]
280
282 template <typename CompatibleKeyType>
283 bool TryGetValue(const CompatibleKeyType& key, ValueType& out_value) const; // [tested]
284
286 template <typename CompatibleKeyType>
287 bool TryGetValue(const CompatibleKeyType& key, const ValueType*& out_pValue) const; // [tested]
288
290 template <typename CompatibleKeyType>
291 bool TryGetValue(const CompatibleKeyType& key, ValueType*& out_pValue) const; // [tested]
292
294 template <typename CompatibleKeyType>
295 const ValueType* GetValue(const CompatibleKeyType& key) const; // [tested]
296
298 template <typename CompatibleKeyType>
299 ValueType* GetValue(const CompatibleKeyType& key); // [tested]
300
302 template <typename CompatibleKeyType>
303 const ValueType& GetValueOrDefault(const CompatibleKeyType& key, const ValueType& defaultValue) const; // [tested]
304
306 template <typename CompatibleKeyType>
307 Iterator Find(const CompatibleKeyType& key); // [tested]
308
311 template <typename CompatibleKeyType>
312 Iterator LowerBound(const CompatibleKeyType& key); // [tested]
313
316 template <typename CompatibleKeyType>
317 Iterator UpperBound(const CompatibleKeyType& key); // [tested]
318
320 template <typename CompatibleKeyType>
321 ConstIterator Find(const CompatibleKeyType& key) const; // [tested]
322
324 template <typename CompatibleKeyType>
325 bool Contains(const CompatibleKeyType& key) const; // [tested]
326
329 template <typename CompatibleKeyType>
330 ConstIterator LowerBound(const CompatibleKeyType& key) const; // [tested]
331
334 template <typename CompatibleKeyType>
335 ConstIterator UpperBound(const CompatibleKeyType& key) const; // [tested]
336
338 plAllocator* GetAllocator() const { return m_Elements.GetAllocator(); }
339
341 bool operator==(const plMapBase<KeyType, ValueType, Comparer>& rhs) const; // [tested]
342 PL_ADD_DEFAULT_OPERATOR_NOTEQUAL(const plMapBase<KeyType, ValueType, Comparer>&);
343
345 plUInt64 GetHeapMemoryUsage() const { return m_Elements.GetHeapMemoryUsage(); } // [tested]
346
348 void Swap(plMapBase<KeyType, ValueType, Comparer>& other); // [tested]
349
350private:
351 template <typename CompatibleKeyType>
352 Node* Internal_Find(const CompatibleKeyType& key) const;
353 template <typename CompatibleKeyType>
354 Node* Internal_LowerBound(const CompatibleKeyType& key) const;
355 template <typename CompatibleKeyType>
356 Node* Internal_UpperBound(const CompatibleKeyType& key) const;
357
358private:
359 void Constructor();
360
362 template <typename CompatibleKeyType>
363 Node* AcquireNode(CompatibleKeyType&& key, ValueType&& value, plUInt8 uiLevel, Node* pParent);
364
366 void ReleaseNode(Node* pNode);
367
368 // \brief Red-Black Tree stuff(Anderson Tree to be exact).
369 // Code taken from here: http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_andersson.aspx
370 Node* SkewNode(Node* root);
371 Node* SplitNode(Node* root);
372 void Insert(const KeyType& key, const ValueType& value, Node*& pInsertedNode);
373 template <typename CompatibleKeyType>
374 Node* Remove(Node* root, const CompatibleKeyType& key, bool& bRemoved);
375
377 Node* GetLeftMost() const;
378
380 Node* GetRightMost() const;
381
383 void SwapNilNode(Node*& pCurNode, NilNode* pOld, NilNode* pNew);
384
386 Node* m_pRoot;
387
389 Node* m_pFreeElementStack;
390
392 NilNode m_NilNode;
393
396
398 plUInt32 m_uiCount;
399
401 Comparer m_Comparer;
402};
403
404
406template <typename KeyType, typename ValueType, typename Comparer = plCompareHelper<KeyType>, typename AllocatorWrapper = plDefaultAllocatorWrapper>
407class plMap : public plMapBase<KeyType, ValueType, Comparer>
408{
409public:
410 plMap();
411 explicit plMap(plAllocator* pAllocator);
412 plMap(const Comparer& comparer, plAllocator* pAllocator);
413
416
418 void operator=(const plMapBase<KeyType, ValueType, Comparer>& rhs);
419};
420
421template <typename KeyType, typename ValueType, typename Comparer>
423{
424 return ref_container.GetIterator();
425}
426
427template <typename KeyType, typename ValueType, typename Comparer>
429{
430 return container.GetIterator();
431}
432
433template <typename KeyType, typename ValueType, typename Comparer>
435{
436 return container.GetIterator();
437}
438
439template <typename KeyType, typename ValueType, typename Comparer>
441{
443}
444
445template <typename KeyType, typename ValueType, typename Comparer>
447{
449}
450
451template <typename KeyType, typename ValueType, typename Comparer>
453{
455}
456
457#include <Foundation/Containers/Implementation/Map_inl.h>
Base class for all memory allocators.
Definition Allocator.h:23
plUInt64 GetHeapMemoryUsage() const
Returns the amount of bytes that are currently allocated on the heap.
Definition Deque_inl.h:970
plAllocator * GetAllocator() const
Returns the allocator that is used by this instance.
Definition Deque.h:168
Definition Deque.h:270
An associative container. Similar to STL::map.
Definition Map.h:193
bool Contains(const CompatibleKeyType &key) const
Checks whether the given key is in the container.
plAllocator * GetAllocator() const
Returns the allocator that is used by this instance.
Definition Map.h:338
ConstIterator UpperBound(const CompatibleKeyType &key) const
Returns an Iterator to the element with a key that is LARGER than the given key. Returns an invalid i...
Iterator Find(const CompatibleKeyType &key)
Searches for key, returns an Iterator to it or an invalid iterator, if no such key is found....
ConstIterator Find(const CompatibleKeyType &key) const
Searches for key, returns an Iterator to it or an invalid iterator, if no such key is found....
void Clear()
Destroys all elements in the map and resets its size to zero.
Definition Map_inl.h:175
~plMapBase()
Destroys all elements from the map.
Definition Map_inl.h:160
bool operator==(const plMapBase< KeyType, ValueType, Comparer > &rhs) const
Comparison operator.
Definition Map_inl.h:804
plUInt64 GetHeapMemoryUsage() const
Returns the amount of bytes that are currently allocated on the heap.
Definition Map.h:345
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...
bool IsEmpty() const
Returns whether there are no elements in the map. O(1) operation.
Definition Map_inl.h:194
Iterator LowerBound(const CompatibleKeyType &key)
Returns an Iterator to the element with a key equal or larger than the given key. Returns an invalid ...
ValueType & operator[](const CompatibleKeyType &key)
Allows read/write access to the value stored under the given key. If there is no such key,...
Definition Map_inl.h:450
ReverseIterator GetReverseIterator()
Returns a ReverseIterator to the very last element.
Definition Map_inl.h:219
Iterator Insert(CompatibleKeyType &&key, CompatibleValueType &&value)
Inserts the key/value pair into the tree and returns an Iterator to it. O(log n) operation.
Definition Map_inl.h:535
bool Remove(const CompatibleKeyType &key)
Erases the key/value pair with the given key, if it exists. O(log n) operation.
Definition Map_inl.h:545
plUInt32 GetCount() const
Returns the number of elements currently stored in the map. O(1) operation.
Definition Map_inl.h:200
Iterator FindOrAdd(CompatibleKeyType &&key, bool *out_pExisted=nullptr)
Searches for the given key and returns an iterator to it. If it did not exist yet,...
Definition Map_inl.h:457
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.
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...
Iterator GetIterator()
Returns an Iterator to the very first element.
Definition Map_inl.h:207
void operator=(const plMapBase< KeyType, ValueType, Comparer > &rhs)
Copies all key/value pairs from the given map into this one.
Definition Map_inl.h:166
void Swap(plMapBase< KeyType, ValueType, Comparer > &other)
Swaps this map with the other one.
Definition Map_inl.h:873
ValueType * GetValue(const CompatibleKeyType &key)
Returns a pointer to the value of the entry with the given key if found, otherwise returns nullptr.
plMapBase(const Comparer &comparer, plAllocator *pAllocator)
Initializes the map to be empty.
Definition Map_inl.h:143
ConstIterator LowerBound(const CompatibleKeyType &key) const
Returns an Iterator to the element with a key equal or larger than the given key. Returns an invalid ...
const ValueType & GetValueOrDefault(const CompatibleKeyType &key, const ValueType &defaultValue) const
Either returns the value of the entry with the given key, if found, or the provided default value.
Iterator UpperBound(const CompatibleKeyType &key)
Returns an Iterator to the element with a key that is LARGER than the given key. Returns an invalid i...
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...
Definition Map.h:408
Base class for all iterators.
Definition Map.h:11
PL_ALWAYS_INLINE bool operator==(const plMapBaseConstIteratorBase &it2) const
Checks whether the two iterators point to the same element.
Definition Map.h:30
PL_ALWAYS_INLINE bool IsValid() const
Checks whether this iterator points to a valid element.
Definition Map.h:27
PL_FORCE_INLINE const KeyType & Key() const
Returns the 'key' of the element that this iterator points to.
Definition Map.h:34
void Prev()
Advances the iterator to the previous element in the map. The iterator will not be valid anymore,...
Definition Map_inl.h:71
PL_FORCE_INLINE const ValueType & Value() const
Returns the 'value' of the element that this iterator points to.
Definition Map.h:41
PL_ALWAYS_INLINE void operator--()
Shorthand for 'Prev'.
Definition Map.h:60
PL_ALWAYS_INLINE plMapBaseConstIteratorBase & operator*()
Returns '*this' to enable foreach.
Definition Map.h:48
PL_ALWAYS_INLINE void operator++()
Shorthand for 'Next'.
Definition Map.h:57
PL_ALWAYS_INLINE plMapBaseConstIteratorBase()
Constructs an invalid iterator.
Definition Map.h:21
void Next()
Advances the iterator to the next element in the map. The iterator will not be valid anymore,...
Definition Map_inl.h:58
Forward Iterator to iterate over all elements in sorted order.
Definition Map.h:103
PL_ALWAYS_INLINE plMapBaseIteratorBase()
Constructs an invalid iterator.
Definition Map.h:113
PL_ALWAYS_INLINE plMapBaseIteratorBase & operator*()
Returns '*this' to enable foreach.
Definition Map.h:133
PL_FORCE_INLINE ValueType & Value() const
Returns the 'value' of the element that this iterator points to.
Definition Map.h:126
PL_FORCE_INLINE ValueType & Value()
Returns the 'value' of the element that this iterator points to.
Definition Map.h:119