Plasma Engine  2.0
Loading...
Searching...
No Matches
List_inl.h
1#pragma once
2
3#include <Foundation/Math/Math.h>
4
5// **** ListElement ****
6
7template <typename T>
9 : m_pPrev(nullptr)
10 , m_pNext(nullptr)
11{
12}
13
14template <typename T>
16 : m_Data(data)
17{
18}
19
20// **** plListBase ****
21
22template <typename T>
24 : m_End(reinterpret_cast<ListElement*>(&m_Last))
25 , m_uiCount(0)
26 , m_Elements(pAllocator)
27 , m_pFreeElementStack(nullptr)
28{
29 m_First.m_pNext = reinterpret_cast<ListElement*>(&m_Last);
30 m_Last.m_pPrev = reinterpret_cast<ListElement*>(&m_First);
31}
32
33template <typename T>
35 : m_End(reinterpret_cast<ListElement*>(&m_Last))
36 , m_uiCount(0)
37 , m_Elements(pAllocator)
38 , m_pFreeElementStack(nullptr)
39{
40 m_First.m_pNext = reinterpret_cast<ListElement*>(&m_Last);
41 m_Last.m_pPrev = reinterpret_cast<ListElement*>(&m_First);
42
43 operator=(cc);
44}
45
46template <typename T>
48{
49 Clear();
50}
51
52template <typename T>
54{
55 Clear();
56 Insert(GetIterator(), cc.GetIterator(), cc.GetEndIterator());
57}
58
59template <typename T>
60typename plListBase<T>::ListElement* plListBase<T>::AcquireNode()
61{
62 ListElement* pNode;
63
64 if (m_pFreeElementStack == nullptr)
65 {
66 m_Elements.PushBack();
67 pNode = &m_Elements.PeekBack();
68 }
69 else
70 {
71 pNode = m_pFreeElementStack;
72 m_pFreeElementStack = m_pFreeElementStack->m_pNext;
73 }
74
76 return pNode;
77}
78
79template <typename T>
80void plListBase<T>::ReleaseNode(ListElement* pNode)
81{
83
84 if (pNode == &m_Elements.PeekBack())
85 {
86 m_Elements.PopBack();
87 }
88 else if (pNode == &m_Elements.PeekFront())
89 {
90 m_Elements.PopFront();
91 }
92 else
93 {
94 pNode->m_pNext = m_pFreeElementStack;
95 m_pFreeElementStack = pNode;
96 }
97
98 --m_uiCount;
99}
100
101
102template <typename T>
104{
105 return Iterator(m_First.m_pNext);
106}
107
108template <typename T>
110{
111 return m_End;
112}
113
114template <typename T>
115PL_ALWAYS_INLINE typename plListBase<T>::ConstIterator plListBase<T>::GetIterator() const
117 return ConstIterator(m_First.m_pNext);
118}
120template <typename T>
121PL_ALWAYS_INLINE typename plListBase<T>::ConstIterator plListBase<T>::GetEndIterator() const
123 return m_End;
124}
126template <typename T>
127PL_ALWAYS_INLINE plUInt32 plListBase<T>::GetCount() const
128{
129 return m_uiCount;
130}
131
132template <typename T>
133PL_ALWAYS_INLINE bool plListBase<T>::IsEmpty() const
134{
135 return (m_uiCount == 0);
136}
137
138template <typename T>
140{
141 if (!IsEmpty())
142 Remove(GetIterator(), GetEndIterator());
143
144 m_pFreeElementStack = nullptr;
145 m_Elements.Clear();
146}
148template <typename T>
149PL_FORCE_INLINE void plListBase<T>::Compact()
151 m_Elements.Compact();
152}
154template <typename T>
155PL_FORCE_INLINE T& plListBase<T>::PeekFront()
157 PL_ASSERT_DEBUG(!IsEmpty(), "The container is empty.");
158
159 return m_First.m_pNext->m_Data;
160}
161
162template <typename T>
163PL_FORCE_INLINE T& plListBase<T>::PeekBack()
164{
165 PL_ASSERT_DEBUG(!IsEmpty(), "The container is empty.");
166
167 return m_Last.m_pPrev->m_Data;
169
170template <typename T>
171PL_FORCE_INLINE const T& plListBase<T>::PeekFront() const
172{
173 PL_ASSERT_DEBUG(!IsEmpty(), "The container is empty.");
175 return m_First.m_pNext->m_Data;
176}
178template <typename T>
179PL_FORCE_INLINE const T& plListBase<T>::PeekBack() const
181 PL_ASSERT_DEBUG(!IsEmpty(), "The container is empty.");
182
183 return m_Last.m_pPrev->m_Data;
184}
185
187template <typename T>
188PL_ALWAYS_INLINE T& plListBase<T>::PushBack()
190 return *Insert(GetEndIterator());
191}
193template <typename T>
194PL_ALWAYS_INLINE void plListBase<T>::PushBack(const T& element)
196 Insert(GetEndIterator(), element);
197}
199template <typename T>
200PL_ALWAYS_INLINE T& plListBase<T>::PushFront()
201{
202 return *Insert(GetIterator());
203}
205template <typename T>
206PL_ALWAYS_INLINE void plListBase<T>::PushFront(const T& element)
207{
208 Insert(GetIterator(), element);
209}
210
211template <typename T>
212PL_FORCE_INLINE void plListBase<T>::PopBack()
213{
214 PL_ASSERT_DEBUG(!IsEmpty(), "The container is empty.");
215
216 Remove(Iterator(m_Last.m_pPrev));
217}
218
219template <typename T>
221{
222 PL_ASSERT_DEBUG(!IsEmpty(), "The container is empty.");
223
224 Remove(Iterator(m_First.m_pNext));
225}
226
227template <typename T>
229{
230 PL_ASSERT_DEV(pos.m_pElement != nullptr, "The iterator (pos) is invalid.");
231
232 ++m_uiCount;
233 ListElement* elem = AcquireNode();
234
235 elem->m_pNext = pos.m_pElement;
236 elem->m_pPrev = pos.m_pElement->m_pPrev;
237
238 pos.m_pElement->m_pPrev->m_pNext = elem;
239 pos.m_pElement->m_pPrev = elem;
240
241 return Iterator(elem);
242}
243
244template <typename T>
245typename plListBase<T>::Iterator plListBase<T>::Insert(const Iterator& pos, const T& data)
246{
247 PL_ASSERT_DEV(pos.m_pElement != nullptr, "The iterator (pos) is invalid.");
248
249 ++m_uiCount;
250 ListElement* elem = AcquireNode();
251 elem->m_Data = data;
252
253 elem->m_pNext = pos.m_pElement;
254 elem->m_pPrev = pos.m_pElement->m_pPrev;
255
256 pos.m_pElement->m_pPrev->m_pNext = elem;
257 pos.m_pElement->m_pPrev = elem;
258
259 return Iterator(elem);
260}
261
262template <typename T>
263void plListBase<T>::Insert(const Iterator& pos, ConstIterator first, const ConstIterator& last)
264{
265 PL_ASSERT_DEV(pos.m_pElement != nullptr && first.m_pElement != nullptr && last.m_pElement != nullptr, "One of the iterators is invalid.");
266
267 while (first != last)
268 {
269 Insert(pos, *first);
270 ++first;
271 }
272}
273
274template <typename T>
276{
277 PL_ASSERT_DEV(!IsEmpty(), "The container is empty.");
278 PL_ASSERT_DEV(pos.m_pElement != nullptr, "The iterator (pos) is invalid.");
279
280 ListElement* pPrev = pos.m_pElement->m_pPrev;
281 ListElement* pNext = pos.m_pElement->m_pNext;
282
283 pPrev->m_pNext = pNext;
284 pNext->m_pPrev = pPrev;
285
286 ReleaseNode(pos.m_pElement);
287
288 return Iterator(pNext);
289}
290
291template <typename T>
293{
294 PL_ASSERT_DEV(!IsEmpty(), "The container is empty.");
295 PL_ASSERT_DEV(first.m_pElement != nullptr && last.m_pElement != nullptr, "An iterator is invalid.");
296
297 while (first != last)
298 first = Remove(first);
299
300 return last;
301}
302
306template <typename T>
307void plListBase<T>::SetCount(plUInt32 uiNewSize)
308{
309 while (m_uiCount > uiNewSize)
310 PopBack();
311
312 while (m_uiCount < uiNewSize)
313 PushBack();
314}
315
316template <typename T>
318{
319 if (GetCount() != rhs.GetCount())
320 return false;
321
322 auto itLhs = GetIterator();
323 auto itRhs = rhs.GetIterator();
324
325 while (itLhs.IsValid())
326 {
327 if (*itLhs != *itRhs)
328 return false;
329
330 ++itLhs;
331 ++itRhs;
332 }
333
334 return true;
335}
336
337template <typename T, typename A>
339 : plListBase<T>(A::GetAllocator())
340{
341}
342
343template <typename T, typename A>
345 : plListBase<T>(pAllocator)
346{
347}
348
349template <typename T, typename A>
351 : plListBase<T>(other, A::GetAllocator())
352{
353}
354
355template <typename T, typename A>
357 : plListBase<T>(other, A::GetAllocator())
358{
359}
360
361template <typename T, typename A>
363{
365}
366
367template <typename T, typename A>
369{
371}
Base class for all memory allocators.
Definition Allocator.h:23
A List-class, similar to STL::list.
Definition List.h:12
plUInt32 GetCount() const
Returns the number of elements in the list. O(1) operation.
Definition List_inl.h:127
~plListBase()
Destroys the list and all its content.
Definition List_inl.h:47
void SetCount(plUInt32 uiNewSize)
Sets the number of elements that are in the list.
Definition List_inl.h:307
Iterator Remove(const Iterator &pos)
Erases the element pointed to by the iterator.
Definition List_inl.h:275
plListBase(plAllocator *pAllocator)
Initializes the list to be empty.
Definition List_inl.h:23
void PopFront()
Removes the very first element from the list.
Definition List_inl.h:220
T & PushFront()
Appends a default-constructed element to the front of the list and returns a reference to it.
Definition List_inl.h:200
void PopBack()
Removes the very last element from the list.
Definition List_inl.h:212
const T & PeekBack() const
Returns the very last element in the list.
Definition List_inl.h:179
void Compact()
See plDeque::Compact()
Definition List_inl.h:149
T & PushBack()
Appends a default-constructed element to the list and returns a reference to it.
Definition List_inl.h:188
void operator=(const plListBase< T > &cc)
Copies the list cc into this list.
Definition List_inl.h:53
const T & PeekFront() const
Returns the very first element in the list.
Definition List_inl.h:171
void Clear()
Clears the list, afterwards it is empty.
Definition List_inl.h:139
Iterator Insert(const Iterator &pos, const T &data)
Inserts one element before the position defined by the iterator.
Definition List_inl.h:245
bool IsEmpty() const
Returns whether size == 0. O(1) operation.
Definition List_inl.h:133
Iterator GetEndIterator()
Returns an iterator pointing behind the last element. Necessary if one wants to insert elements at th...
Definition List_inl.h:109
Iterator GetIterator()
Returns an iterator to the first list-element.
Definition List_inl.h:103
bool operator==(const plListBase< T > &rhs) const
Comparison operator.
Definition List_inl.h:317
Definition List.h:239
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.
A forward-iterator. Allows sequential access from front-to-back.
Definition List.h:86