Plasma Engine  2.0
Loading...
Searching...
No Matches
Map_inl.h
1#pragma once
2
3#include <Foundation/Math/Math.h>
4
5// ***** Const Iterator *****
6
7#define STACK_SIZE 64
8
9template <typename KeyType, typename ValueType, typename Comparer, bool REVERSE>
11{
12 if (m_pElement == nullptr)
13 {
14 PL_ASSERT_DEBUG(m_pElement != nullptr, "The Iterator is invalid (end).");
15 return;
16 }
17
18 // if this element has a right child, go there and then search for the left most child of that
19 if (m_pElement->m_pLink[dir1] != m_pElement->m_pLink[dir1]->m_pLink[dir1])
20 {
21 m_pElement = m_pElement->m_pLink[dir1];
22
23 while (m_pElement->m_pLink[dir0] != m_pElement->m_pLink[dir0]->m_pLink[dir0])
24 m_pElement = m_pElement->m_pLink[dir0];
25
26 return;
27 }
28
29 // if this element has a parent and this element is that parents left child, go directly to the parent
30 if ((m_pElement->m_pParent != m_pElement->m_pParent->m_pParent) && (m_pElement->m_pParent->m_pLink[dir0] == m_pElement))
31 {
32 m_pElement = m_pElement->m_pParent;
33 return;
34 }
35
36 // if this element has a parent and this element is that parents right child, search for the next parent, whose left child this is
37 if ((m_pElement->m_pParent != m_pElement->m_pParent->m_pParent) && (m_pElement->m_pParent->m_pLink[dir1] == m_pElement))
38 {
39 while (m_pElement->m_pParent->m_pLink[dir1] == m_pElement)
40 m_pElement = m_pElement->m_pParent;
41
42 // if we are at the root node..
43 if ((m_pElement->m_pParent == nullptr) || (m_pElement->m_pParent == m_pElement->m_pParent->m_pParent))
44 {
45 m_pElement = nullptr;
46 return;
47 }
48
49 m_pElement = m_pElement->m_pParent;
50 return;
51 }
52
53 m_pElement = nullptr;
54 return;
55}
56
57template <typename KeyType, typename ValueType, typename Comparer, bool REVERSE>
59{
60 if constexpr (REVERSE)
61 {
62 Advance(1, 0);
63 }
64 else
65 {
66 Advance(0, 1);
67 }
68}
69
70template <typename KeyType, typename ValueType, typename Comparer, bool REVERSE>
72{
73 if constexpr (REVERSE)
74 {
75 Advance(0, 1);
76 }
77 else
78 {
79 Advance(1, 0);
80 }
81}
82
83#if PL_ENABLED(PL_USE_CPP20_OPERATORS)
84
85// These functions are used for structured bindings.
86// They describe how many elements can be accessed in the binding and which type they are.
87namespace std
88{
89 template <typename KeyType, typename ValueType, typename Comparer, bool REVERSE>
90 struct tuple_size<plMapBaseConstIteratorBase<KeyType, ValueType, Comparer, REVERSE>> : integral_constant<size_t, 2>
91 {
92 };
93
94 template <typename KeyType, typename ValueType, typename Comparer, bool REVERSE>
95 struct tuple_element<0, plMapBaseConstIteratorBase<KeyType, ValueType, Comparer, REVERSE>>
96 {
97 using type = const KeyType&;
98 };
99
100 template <typename KeyType, typename ValueType, typename Comparer, bool REVERSE>
101 struct tuple_element<1, plMapBaseConstIteratorBase<KeyType, ValueType, Comparer, REVERSE>>
102 {
103 using type = const ValueType&;
104 };
105
106
107 template <typename KeyType, typename ValueType, typename Comparer, bool REVERSE>
108 struct tuple_size<plMapBaseIteratorBase<KeyType, ValueType, Comparer, REVERSE>> : integral_constant<size_t, 2>
109 {
110 };
111
112 template <typename KeyType, typename ValueType, typename Comparer, bool REVERSE>
113 struct tuple_element<0, plMapBaseIteratorBase<KeyType, ValueType, Comparer, REVERSE>>
114 {
115 using type = const KeyType&;
116 };
117
118 template <typename KeyType, typename ValueType, typename Comparer, bool REVERSE>
119 struct tuple_element<1, plMapBaseIteratorBase<KeyType, ValueType, Comparer, REVERSE>>
120 {
121 using type = ValueType&;
122 };
123} // namespace std
124#endif
125
126// ***** plMapBase *****
127
128template <typename KeyType, typename ValueType, typename Comparer>
130{
131 m_uiCount = 0;
132
133 m_NilNode.m_uiLevel = 0;
134 m_NilNode.m_pLink[0] = reinterpret_cast<Node*>(&m_NilNode);
135 m_NilNode.m_pLink[1] = reinterpret_cast<Node*>(&m_NilNode);
136 m_NilNode.m_pParent = reinterpret_cast<Node*>(&m_NilNode);
137
138 m_pFreeElementStack = nullptr;
139 m_pRoot = reinterpret_cast<Node*>(&m_NilNode);
140}
141
142template <typename KeyType, typename ValueType, typename Comparer>
144 : m_Elements(pAllocator)
145 , m_Comparer(comparer)
146{
147 Constructor();
148}
149
150template <typename KeyType, typename ValueType, typename Comparer>
152 : m_Elements(pAllocator)
153{
154 Constructor();
155
156 operator=(cc);
157}
158
159template <typename KeyType, typename ValueType, typename Comparer>
164
165template <typename KeyType, typename ValueType, typename Comparer>
167{
168 Clear();
169
170 for (ConstIterator it = rhs.GetIterator(); it.IsValid(); ++it)
171 Insert(it.Key(), it.Value());
172}
173
174template <typename KeyType, typename ValueType, typename Comparer>
176{
177 for (Iterator it = GetIterator(); it.IsValid(); ++it)
178 plMemoryUtils::Destruct<Node>(it.m_pElement, 1);
179
180 m_pFreeElementStack = nullptr;
181 m_Elements.Clear();
182
183 m_uiCount = 0;
184
185 m_NilNode.m_uiLevel = 0;
186 m_NilNode.m_pLink[0] = reinterpret_cast<Node*>(&m_NilNode);
187 m_NilNode.m_pLink[1] = reinterpret_cast<Node*>(&m_NilNode);
188 m_NilNode.m_pParent = reinterpret_cast<Node*>(&m_NilNode);
189
190 m_pRoot = reinterpret_cast<Node*>(&m_NilNode);
191}
192
193template <typename KeyType, typename ValueType, typename Comparer>
195{
196 return (m_uiCount == 0);
197}
198
199template <typename KeyType, typename ValueType, typename Comparer>
201{
202 return m_uiCount;
203}
204
205
206template <typename KeyType, typename ValueType, typename Comparer>
211
212template <typename KeyType, typename ValueType, typename Comparer>
217
218template <typename KeyType, typename ValueType, typename Comparer>
223
224template <typename KeyType, typename ValueType, typename Comparer>
227 return ConstReverseIterator(GetRightMost());
228}
230template <typename KeyType, typename ValueType, typename Comparer>
231typename plMapBase<KeyType, ValueType, Comparer>::Node* plMapBase<KeyType, ValueType, Comparer>::GetLeftMost() const
233 if (IsEmpty())
234 return nullptr;
236 Node* pNode = m_pRoot;
237
238 while ((const void*)pNode->m_pLink[0] != (const void*)&m_NilNode)
239 pNode = pNode->m_pLink[0];
240
241 return pNode;
243
244template <typename KeyType, typename ValueType, typename Comparer>
245typename plMapBase<KeyType, ValueType, Comparer>::Node* plMapBase<KeyType, ValueType, Comparer>::GetRightMost() const
246{
247 if (IsEmpty())
248 return nullptr;
249
250 Node* pNode = m_pRoot;
252 while ((const void*)pNode->m_pLink[1] != (const void*)&m_NilNode)
253 pNode = pNode->m_pLink[1];
255 return pNode;
256}
258template <typename KeyType, typename ValueType, typename Comparer>
259template <typename CompatibleKeyType>
260typename plMapBase<KeyType, ValueType, Comparer>::Node* plMapBase<KeyType, ValueType, Comparer>::Internal_Find(const CompatibleKeyType& key) const
262 Node* pNode = m_pRoot;
263
264 while ((const void*)pNode != (const void*)&m_NilNode)
266 const plInt32 dir = (plInt32)m_Comparer.Less(pNode->m_Key, key);
267 const plInt32 dir2 = (plInt32)m_Comparer.Less(key, pNode->m_Key);
268
269 if (dir == dir2)
270 break;
271
272 pNode = pNode->m_pLink[dir];
273 }
275 if ((const void*)pNode == (const void*)&m_NilNode)
276 return nullptr;
277
278 return pNode;
280
281template <typename KeyType, typename ValueType, typename Comparer>
282template <typename CompatibleKeyType>
283PL_ALWAYS_INLINE bool plMapBase<KeyType, ValueType, Comparer>::TryGetValue(const CompatibleKeyType& key, ValueType& out_value) const
284{
285 Node* pNode = Internal_Find<CompatibleKeyType>(key);
286 if (pNode != nullptr)
287 {
288 out_value = pNode->m_Value;
289 return true;
290 }
291
292 return false;
293}
294
295template <typename KeyType, typename ValueType, typename Comparer>
296template <typename CompatibleKeyType>
297PL_ALWAYS_INLINE bool plMapBase<KeyType, ValueType, Comparer>::TryGetValue(const CompatibleKeyType& key, const ValueType*& out_pValue) const
298{
299 Node* pNode = Internal_Find<CompatibleKeyType>(key);
300 if (pNode != nullptr)
301 {
302 out_pValue = &pNode->m_Value;
303 return true;
304 }
305
306 return false;
307}
308
309template <typename KeyType, typename ValueType, typename Comparer>
310template <typename CompatibleKeyType>
311PL_ALWAYS_INLINE bool plMapBase<KeyType, ValueType, Comparer>::TryGetValue(const CompatibleKeyType& key, ValueType*& out_pValue) const
312{
313 Node* pNode = Internal_Find<CompatibleKeyType>(key);
314 if (pNode != nullptr)
315 {
316 out_pValue = &pNode->m_Value;
317 return true;
318 }
319
320 return false;
321}
322
323template <typename KeyType, typename ValueType, typename Comparer>
324template <typename CompatibleKeyType>
325PL_ALWAYS_INLINE const ValueType* plMapBase<KeyType, ValueType, Comparer>::GetValue(const CompatibleKeyType& key) const
326{
327 Node* pNode = Internal_Find<CompatibleKeyType>(key);
328 return pNode ? &pNode->m_Value : nullptr;
329}
330
331template <typename KeyType, typename ValueType, typename Comparer>
332template <typename CompatibleKeyType>
333PL_ALWAYS_INLINE ValueType* plMapBase<KeyType, ValueType, Comparer>::GetValue(const CompatibleKeyType& key)
334{
335 Node* pNode = Internal_Find<CompatibleKeyType>(key);
336 return pNode ? &pNode->m_Value : nullptr;
337}
338
339template <typename KeyType, typename ValueType, typename Comparer>
340template <typename CompatibleKeyType>
341PL_ALWAYS_INLINE const ValueType& plMapBase<KeyType, ValueType, Comparer>::GetValueOrDefault(const CompatibleKeyType& key, const ValueType& defaultValue) const
342{
343 Node* pNode = Internal_Find<CompatibleKeyType>(key);
344 return pNode ? pNode->m_Value : defaultValue;
345}
346
347template <typename KeyType, typename ValueType, typename Comparer>
348template <typename CompatibleKeyType>
350{
351 return Iterator(Internal_Find<CompatibleKeyType>(key));
352}
353
354template <typename KeyType, typename ValueType, typename Comparer>
355template <typename CompatibleKeyType>
356PL_ALWAYS_INLINE typename plMapBase<KeyType, ValueType, Comparer>::ConstIterator plMapBase<KeyType, ValueType, Comparer>::Find(const CompatibleKeyType& key) const
357{
358 return ConstIterator(Internal_Find<CompatibleKeyType>(key));
359}
360
361template <typename KeyType, typename ValueType, typename Comparer>
362template <typename CompatibleKeyType>
363PL_ALWAYS_INLINE bool plMapBase<KeyType, ValueType, Comparer>::Contains(const CompatibleKeyType& key) const
364{
365 return Internal_Find(key) != nullptr;
366}
367
368template <typename KeyType, typename ValueType, typename Comparer>
369template <typename CompatibleKeyType>
370typename plMapBase<KeyType, ValueType, Comparer>::Node* plMapBase<KeyType, ValueType, Comparer>::Internal_LowerBound(const CompatibleKeyType& key) const
371{
372 Node* pNode = m_pRoot;
373 Node* pNodeSmaller = nullptr;
374
375 while ((const void*)pNode != (const void*)&m_NilNode)
376 {
377 const plInt32 dir = (plInt32)m_Comparer.Less(pNode->m_Key, key);
378 const plInt32 dir2 = (plInt32)m_Comparer.Less(key, pNode->m_Key);
379
380 if (dir == dir2)
381 return pNode;
382
383 if (dir == 0)
384 pNodeSmaller = pNode;
385
386 pNode = pNode->m_pLink[dir];
387 }
388
389 return pNodeSmaller;
390}
391
392template <typename KeyType, typename ValueType, typename Comparer>
393template <typename CompatibleKeyType>
395{
396 return Iterator(Internal_LowerBound(key));
397}
398
399template <typename KeyType, typename ValueType, typename Comparer>
400template <typename CompatibleKeyType>
402{
403 return ConstIterator(Internal_LowerBound(key));
404}
405
406template <typename KeyType, typename ValueType, typename Comparer>
407template <typename CompatibleKeyType>
408typename plMapBase<KeyType, ValueType, Comparer>::Node* plMapBase<KeyType, ValueType, Comparer>::Internal_UpperBound(const CompatibleKeyType& key) const
409{
410 Node* pNode = m_pRoot;
411 Node* pNodeSmaller = nullptr;
412
413 while ((const void*)pNode != (const void*)&m_NilNode)
414 {
415 const plInt32 dir = (plInt32)m_Comparer.Less(pNode->m_Key, key);
416 const plInt32 dir2 = (plInt32)m_Comparer.Less(key, pNode->m_Key);
417
418 if (dir == dir2)
419 {
420 ConstIterator it(pNode);
421 ++it;
422 return it.m_pElement;
423 }
424
425 if (dir == 0)
426 pNodeSmaller = pNode;
427
428 pNode = pNode->m_pLink[dir];
429 }
430
431 return pNodeSmaller;
432}
433
434template <typename KeyType, typename ValueType, typename Comparer>
435template <typename CompatibleKeyType>
437{
438 return Iterator(Internal_UpperBound(key));
439}
440
441template <typename KeyType, typename ValueType, typename Comparer>
442template <typename CompatibleKeyType>
444{
445 return ConstIterator(Internal_UpperBound(key));
446}
447
448template <typename KeyType, typename ValueType, typename Comparer>
449template <typename CompatibleKeyType>
450ValueType& plMapBase<KeyType, ValueType, Comparer>::operator[](const CompatibleKeyType& key)
451{
452 return FindOrAdd(key).Value();
453}
454
455template <typename KeyType, typename ValueType, typename Comparer>
456template <typename CompatibleKeyType>
458{
459 Node* pNilNode = reinterpret_cast<Node*>(&m_NilNode);
460 Node* pInsertedNode = nullptr;
461
462 {
463 Node* root = m_pRoot;
464
465 if (m_pRoot != pNilNode)
466 {
467 Node* it = m_pRoot;
468 Node* up[STACK_SIZE];
469
470 plInt32 top = 0;
471 plUInt32 dir = 0;
472
473 while (true)
474 {
475 if (m_Comparer.Equal(it->m_Key, key))
476 {
477 if (out_pExisted)
478 *out_pExisted = true;
479
480 return Iterator(it);
481 }
482
483 dir = m_Comparer.Less(it->m_Key, key) ? 1 : 0;
484
485 PL_ASSERT_DEBUG(top < STACK_SIZE, "plMapBase's internal stack is not large enough to be able to sort {0} elements.", GetCount());
486 up[top++] = it;
487
488 if (it->m_pLink[dir] == pNilNode)
489 break;
490
491 it = it->m_pLink[dir];
492 }
493
494 pInsertedNode = AcquireNode(std::forward<CompatibleKeyType>(key), ValueType(), 1, it);
495 it->m_pLink[dir] = pInsertedNode;
496
497 while (--top >= 0)
498 {
499 if (top != 0)
500 dir = (up[top - 1]->m_pLink[1] == up[top]) ? 1 : 0;
501
502 up[top] = SkewNode(up[top]);
503 up[top] = SplitNode(up[top]);
504
505 if (top != 0)
506 {
507 up[top - 1]->m_pLink[dir] = up[top];
508 up[top - 1]->m_pLink[dir]->m_pParent = up[top - 1];
509 }
510 else
511 root = up[top];
512 }
513 }
514 else
515 {
516 pInsertedNode = AcquireNode(std::forward<CompatibleKeyType>(key), ValueType(), 1, pNilNode);
517 root = pInsertedNode;
518 }
519
520 m_pRoot = root;
521 m_pRoot->m_pParent = pNilNode;
522 m_NilNode.m_pParent = pNilNode;
523 }
524
525 PL_ASSERT_DEBUG(pInsertedNode != nullptr, "Implementation Error.");
526
527 if (out_pExisted)
528 *out_pExisted = false;
529
530 return Iterator(pInsertedNode);
531}
532
533template <typename KeyType, typename ValueType, typename Comparer>
534template <typename CompatibleKeyType, typename CompatibleValueType>
536{
537 auto it = FindOrAdd(std::forward<CompatibleKeyType>(key));
538 it.Value() = std::forward<CompatibleValueType>(value);
539
540 return it;
541}
542
543template <typename KeyType, typename ValueType, typename Comparer>
544template <typename CompatibleKeyType>
545bool plMapBase<KeyType, ValueType, Comparer>::Remove(const CompatibleKeyType& key)
546{
547 bool bRemoved = true;
548 m_pRoot = Remove(m_pRoot, key, bRemoved);
549 m_pRoot->m_pParent = reinterpret_cast<Node*>(&m_NilNode);
550 m_NilNode.m_pParent = reinterpret_cast<Node*>(&m_NilNode);
551
552 return bRemoved;
553}
554
555template <typename KeyType, typename ValueType, typename Comparer>
556template <typename CompatibleKeyType>
557typename plMapBase<KeyType, ValueType, Comparer>::Node* plMapBase<KeyType, ValueType, Comparer>::AcquireNode(CompatibleKeyType&& key, ValueType&& value, plUInt8 uiLevel, Node* pParent)
558{
559 Node* pNode;
560
561 if (m_pFreeElementStack == nullptr)
562 {
563 m_Elements.PushBack();
564 pNode = &m_Elements.PeekBack();
565 }
566 else
567 {
568 pNode = m_pFreeElementStack;
569 m_pFreeElementStack = m_pFreeElementStack->m_pParent;
570 }
571
573
574 pNode->m_pParent = pParent;
575 pNode->m_Key = std::forward<CompatibleKeyType>(key);
576 pNode->m_Value = std::move(value);
577 pNode->m_uiLevel = uiLevel;
578 pNode->m_pLink[0] = reinterpret_cast<Node*>(&m_NilNode);
579 pNode->m_pLink[1] = reinterpret_cast<Node*>(&m_NilNode);
580
581 ++m_uiCount;
582
583 return pNode;
584}
585
586template <typename KeyType, typename ValueType, typename Comparer>
588{
589 PL_ASSERT_DEBUG(pNode != nullptr && pNode != &m_NilNode, "pNode is invalid.");
590
592
593 // try to reduce the element array, if possible
594 if (pNode == &m_Elements.PeekBack())
595 {
596 m_Elements.PopBack();
597 }
598 else if (pNode == &m_Elements.PeekFront())
599 {
600 m_Elements.PopFront();
601 }
602 else
603 {
604 pNode->m_pParent = m_pFreeElementStack;
605 m_pFreeElementStack = pNode;
606 }
607
608 --m_uiCount;
609}
610
611template <typename KeyType, typename ValueType, typename Comparer>
612PL_ALWAYS_INLINE typename plMapBase<KeyType, ValueType, Comparer>::Node* plMapBase<KeyType, ValueType, Comparer>::SkewNode(Node* root)
613{
614 if ((root->m_pLink[0]->m_uiLevel == root->m_uiLevel) && (root->m_uiLevel != 0))
615 {
616 Node* save = root->m_pLink[0];
617 root->m_pLink[0] = save->m_pLink[1];
618 root->m_pLink[0]->m_pParent = root;
619 save->m_pLink[1] = root;
620 save->m_pLink[1]->m_pParent = save;
621 root = save;
622 }
623
624 return root;
625}
626
627template <typename KeyType, typename ValueType, typename Comparer>
628PL_ALWAYS_INLINE typename plMapBase<KeyType, ValueType, Comparer>::Node* plMapBase<KeyType, ValueType, Comparer>::SplitNode(Node* root)
629{
630 if ((root->m_pLink[1]->m_pLink[1]->m_uiLevel == root->m_uiLevel) && (root->m_uiLevel != 0))
631 {
632 Node* save = root->m_pLink[1];
633 root->m_pLink[1] = save->m_pLink[0];
634 root->m_pLink[1]->m_pParent = root;
635 save->m_pLink[0] = root;
636 save->m_pLink[0]->m_pParent = save;
637 root = save;
638 ++root->m_uiLevel;
639 }
640
641 return root;
642}
643
644template <typename KeyType, typename ValueType, typename Comparer>
645template <typename CompatibleKeyType>
646typename plMapBase<KeyType, ValueType, Comparer>::Node* plMapBase<KeyType, ValueType, Comparer>::Remove(Node* root, const CompatibleKeyType& key, bool& bRemoved)
647{
648 bRemoved = false;
649
650 Node* ToErase = reinterpret_cast<Node*>(&m_NilNode);
651 Node* ToOverride = reinterpret_cast<Node*>(&m_NilNode);
652
653 if (root != &m_NilNode)
654 {
655 Node* it = root;
656 Node* up[STACK_SIZE];
657 plInt32 top = 0;
658 plInt32 dir = 0;
659
660 while (true)
661 {
662 PL_ASSERT_DEBUG(top >= 0 && top < STACK_SIZE, "Implementation error");
663 up[top++] = it;
664
665 if (it == &m_NilNode)
666 return root;
667
668 if (m_Comparer.Equal(it->m_Key, key))
669 break;
670
671 dir = m_Comparer.Less(it->m_Key, key) ? 1 : 0;
672
673 it = it->m_pLink[dir];
674 }
675
676 ToOverride = it;
677
678 if ((it->m_pLink[0] == &m_NilNode) || (it->m_pLink[1] == &m_NilNode))
679 {
680 plInt32 dir2 = it->m_pLink[0] == &m_NilNode;
681
682 if (--top != 0)
683 {
684 PL_ASSERT_DEBUG(top >= 1 && top < STACK_SIZE, "Implementation error");
685 up[top - 1]->m_pLink[dir] = it->m_pLink[dir2];
686 up[top - 1]->m_pLink[dir]->m_pParent = up[top - 1];
687 }
688 else
689 root = it->m_pLink[1];
690 }
691 else
692 {
693 Node* heir = it->m_pLink[1];
694 Node* prev = it;
695
696 while (heir->m_pLink[0] != &m_NilNode)
697 {
698 PL_ASSERT_DEBUG(top >= 0 && top < STACK_SIZE, "Implementation error");
699 up[top++] = prev = heir;
700
701 heir = heir->m_pLink[0];
702 }
703
704 ToErase = heir;
705 ToOverride = it;
706
707 prev->m_pLink[prev == it] = heir->m_pLink[1];
708 prev->m_pLink[prev == it]->m_pParent = prev;
709 }
710
711 while (--top >= 0)
712 {
713 if (top != 0)
714 {
715 PL_ASSERT_DEBUG(top >= 1 && top < STACK_SIZE, "Implementation error");
716 dir = up[top - 1]->m_pLink[1] == up[top];
717 }
718
719 PL_ASSERT_DEBUG(top >= 0 && top < STACK_SIZE, "Implementation error");
720
721 if ((up[top]->m_pLink[0]->m_uiLevel < up[top]->m_uiLevel - 1) || (up[top]->m_pLink[1]->m_uiLevel < up[top]->m_uiLevel - 1))
722 {
723 if (up[top]->m_pLink[1]->m_uiLevel > --up[top]->m_uiLevel)
724 up[top]->m_pLink[1]->m_uiLevel = up[top]->m_uiLevel;
725
726 up[top] = SkewNode(up[top]);
727 up[top]->m_pLink[1] = SkewNode(up[top]->m_pLink[1]);
728 up[top]->m_pLink[1]->m_pParent = up[top];
729
730 up[top]->m_pLink[1]->m_pLink[1] = SkewNode(up[top]->m_pLink[1]->m_pLink[1]);
731 up[top] = SplitNode(up[top]);
732 up[top]->m_pLink[1] = SplitNode(up[top]->m_pLink[1]);
733 up[top]->m_pLink[1]->m_pParent = up[top];
734 }
735
736 if (top != 0)
737 {
738 PL_ASSERT_DEBUG(top >= 1 && top < STACK_SIZE, "Implementation error");
739
740 up[top - 1]->m_pLink[dir] = up[top];
741 up[top - 1]->m_pLink[dir]->m_pParent = up[top - 1];
742 }
743 else
744 {
745 PL_ASSERT_DEBUG(top >= 0 && top < STACK_SIZE, "Implementation error");
746 root = up[top];
747 }
748 }
749 }
750
751 root->m_pParent = reinterpret_cast<Node*>(&m_NilNode);
752
753
754 // if necessary, swap nodes
755 if (ToErase != &m_NilNode)
756 {
757 Node* parent = ToOverride->m_pParent;
758
759 if (parent != &m_NilNode)
760 {
761 if (parent->m_pLink[0] == ToOverride)
762 {
763 parent->m_pLink[0] = ToErase;
764 parent->m_pLink[0]->m_pParent = parent;
765 }
766 if (parent->m_pLink[1] == ToOverride)
767 {
768 parent->m_pLink[1] = ToErase;
769 parent->m_pLink[1]->m_pParent = parent;
770 }
771 }
772 else
773 root = ToErase;
774
775 ToErase->m_uiLevel = ToOverride->m_uiLevel;
776 ToErase->m_pLink[0] = ToOverride->m_pLink[0];
777 ToErase->m_pLink[0]->m_pParent = ToErase;
778 ToErase->m_pLink[1] = ToOverride->m_pLink[1];
779 ToErase->m_pLink[1]->m_pParent = ToErase;
780 }
781
782 // remove the erased node
783 if (ToOverride != &m_NilNode)
784 {
785 bRemoved = true;
786 ReleaseNode(ToOverride);
787 }
788
789 return root;
790}
791
792template <typename KeyType, typename ValueType, typename Comparer>
794{
795 PL_ASSERT_DEBUG(pos.m_pElement != nullptr, "The Iterator(pos) is invalid.");
796
797 Iterator temp(pos);
798 ++temp;
799 Remove(pos.Key());
800 return temp;
801}
802
803template <typename KeyType, typename ValueType, typename Comparer>
805{
806 if (GetCount() != rhs.GetCount())
807 return false;
808
809 auto itLhs = GetIterator();
810 auto itRhs = rhs.GetIterator();
811
812 while (itLhs.IsValid())
813 {
814 if (!m_Comparer.Equal(itLhs.Key(), itRhs.Key()))
815 return false;
816
817 if (itLhs.Value() != itRhs.Value())
818 return false;
819
820 ++itLhs;
821 ++itRhs;
822 }
823
824 return true;
825}
826
827#undef STACK_SIZE
828
829
830template <typename KeyType, typename ValueType, typename Comparer, typename AllocatorWrapper>
832 : plMapBase<KeyType, ValueType, Comparer>(Comparer(), AllocatorWrapper::GetAllocator())
833{
834}
835
836template <typename KeyType, typename ValueType, typename Comparer, typename AllocatorWrapper>
838 : plMapBase<KeyType, ValueType, Comparer>(Comparer(), pAllocator)
839{
840}
841
842template <typename KeyType, typename ValueType, typename Comparer, typename AllocatorWrapper>
844 : plMapBase<KeyType, ValueType, Comparer>(comparer, pAllocator)
845{
846}
847
848template <typename KeyType, typename ValueType, typename Comparer, typename AllocatorWrapper>
850 : plMapBase<KeyType, ValueType, Comparer>(other, AllocatorWrapper::GetAllocator())
851{
852}
853
854template <typename KeyType, typename ValueType, typename Comparer, typename AllocatorWrapper>
856 : plMapBase<KeyType, ValueType, Comparer>(other, AllocatorWrapper::GetAllocator())
857{
858}
859
860template <typename KeyType, typename ValueType, typename Comparer, typename AllocatorWrapper>
862{
864}
865
866template <typename KeyType, typename ValueType, typename Comparer, typename AllocatorWrapper>
868{
870}
871
872template <typename KeyType, typename ValueType, typename Comparer>
874{
875 SwapNilNode(this->m_pRoot, &this->m_NilNode, &other.m_NilNode);
876 SwapNilNode(other.m_pRoot, &other.m_NilNode, &this->m_NilNode);
877
878 plMath::Swap(this->m_pRoot, other.m_pRoot);
879 plMath::Swap(this->m_uiCount, other.m_uiCount);
880 plMath::Swap(this->m_pFreeElementStack, other.m_pFreeElementStack);
881 plMath::Swap(this->m_Comparer, other.m_Comparer);
882
883 // after we swapped the root nodes, fix up their parent nodes
884 this->m_pRoot->m_pParent = reinterpret_cast<Node*>(&this->m_NilNode);
885 other.m_pRoot->m_pParent = reinterpret_cast<Node*>(&other.m_NilNode);
886
887 // the set allocator is stored in this array
888 m_Elements.Swap(other.m_Elements);
889}
890
891template <typename KeyType, typename ValueType, typename Comparer>
892void plMapBase<KeyType, ValueType, Comparer>::SwapNilNode(Node*& pCurNode, NilNode* pOld, NilNode* pNew)
893{
894 if (pCurNode == pOld)
895 {
896 pCurNode = reinterpret_cast<Node*>(pNew);
897 return;
898 }
899
900 SwapNilNode(pCurNode->m_pLink[0], pOld, pNew);
901 SwapNilNode(pCurNode->m_pLink[1], pOld, pNew);
902}
Base class for all memory allocators.
Definition Allocator.h:23
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.
Iterator Find(const CompatibleKeyType &key)
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
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.
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
plMapBase(const Comparer &comparer, plAllocator *pAllocator)
Initializes the map to be empty.
Definition Map_inl.h:143
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...
Definition Map.h:408
static void Construct(T *pDestination, size_t uiCount=1)
Constructs uiCount objects of type T in a raw buffer at pDestination.
static void Destruct(T *pDestination, size_t uiCount=1)
Destructs uiCount objects of type T at pDestination.
PL_ALWAYS_INLINE void Swap(T &ref_f1, T &ref_f2)
Swaps the values in the two variables f1 and f2.
Definition Math_inl.h:224
Base class for all iterators.
Definition Map.h:11
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
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