ezEngine  Milestone 7
List_inl.h
1 #pragma once
2 
3 #include <Foundation/Math/Math.h>
4 
5 // **** ListElement ****
6 
7 template <typename T>
8 ezListBase<T>::ListElementBase::ListElementBase() : m_pPrev(nullptr), m_pNext(nullptr)
9 {
10 }
11 
12 template <typename T>
13 ezListBase<T>::ListElement::ListElement(const T& data) : m_Data(data)
14 {
15 }
16 
17 // **** ezListBase ****
18 
19 template <typename T>
21  m_End(reinterpret_cast<ListElement*>(&m_Last)),
22  m_uiCount(0),
23  m_Elements(pAllocator),
24  m_pFreeElementStack(nullptr)
25 {
26  m_First.m_pNext = reinterpret_cast<ListElement*>(&m_Last);
27  m_Last.m_pPrev = reinterpret_cast<ListElement*>(&m_First);
28 }
29 
30 template <typename T>
32  m_End(reinterpret_cast<ListElement*>(&m_Last)),
33  m_uiCount(0),
34  m_Elements(pAllocator),
35  m_pFreeElementStack(nullptr)
36 {
37  m_First.m_pNext = reinterpret_cast<ListElement*>(&m_Last);
38  m_Last.m_pPrev = reinterpret_cast<ListElement*>(&m_First);
39 
40  operator=(cc);
41 }
42 
43 template <typename T>
45 {
46  Clear();
47 }
48 
49 template <typename T>
51 {
52  Clear();
53  Insert(GetIterator(), cc.GetIterator(), cc.GetEndIterator());
54 }
55 
56 template <typename T>
58 {
59  ListElement* pNode;
60 
61  if (m_pFreeElementStack == nullptr)
62  {
63  m_Elements.PushBack();
64  pNode = &m_Elements.PeekBack();
65  }
66  else
67  {
68  pNode = m_pFreeElementStack;
69  m_pFreeElementStack = m_pFreeElementStack->m_pNext;
70  }
71 
72  ezMemoryUtils::Construct<ListElement>(pNode, 1);
73  pNode->m_Data = data;
74  return pNode;
75 }
76 
77 template <typename T>
79 {
80  ezMemoryUtils::Destruct<ListElement>(pNode, 1);
81 
82  if (pNode == &m_Elements.PeekBack())
83  {
84  m_Elements.PopBack();
85  }
86  else
87  if (pNode == &m_Elements.PeekFront())
88  {
89  m_Elements.PopFront();
90  }
91  else
92  {
93  pNode->m_pNext = m_pFreeElementStack;
94  m_pFreeElementStack = pNode;
95  }
96 
97  --m_uiCount;
98 }
99 
100 
101 template <typename T>
103 {
104  return Iterator(m_First.m_pNext);
105 }
106 
107 template <typename T>
109 {
110  return Iterator(m_Last.m_pPrev);
111 }
112 
113 template <typename T>
115 {
116  return m_End;
117 }
118 
119 template <typename T>
121 {
122  return ConstIterator(m_First.m_pNext);
123 }
124 
125 template <typename T>
127 {
128  return ConstIterator(m_Last.m_pPrev);
129 }
130 
131 template <typename T>
133 {
134  return m_End;
135 }
136 
137 template <typename T>
138 EZ_FORCE_INLINE ezUInt32 ezListBase<T>::GetCount() const
139 {
140  return m_uiCount;
141 }
142 
143 template <typename T>
144 EZ_FORCE_INLINE bool ezListBase<T>::IsEmpty() const
145 {
146  return (m_uiCount == 0);
147 }
148 
149 template <typename T>
151 {
152  if (!IsEmpty())
153  Remove(GetIterator(), GetEndIterator());
154 
155  m_pFreeElementStack = nullptr;
156  m_Elements.Clear();
157 }
158 
159 template <typename T>
160 EZ_FORCE_INLINE T& ezListBase<T>::PeekFront()
161 {
162  EZ_ASSERT_DEV(!IsEmpty(), "The container is empty.");
163 
164  return m_First.m_pNext->m_Data;
165 }
166 
167 template <typename T>
168 EZ_FORCE_INLINE T& ezListBase<T>::PeekBack()
169 {
170  EZ_ASSERT_DEV(!IsEmpty(), "The container is empty.");
171 
172  return m_Last.m_pPrev->m_Data;
173 }
174 
175 template <typename T>
176 EZ_FORCE_INLINE const T& ezListBase<T>::PeekFront() const
177 {
178  EZ_ASSERT_DEV(!IsEmpty(), "The container is empty.");
179 
180  return m_First.m_pNext->m_Data;
181 }
182 
183 template <typename T>
184 EZ_FORCE_INLINE const T& ezListBase<T>::PeekBack() const
185 {
186  EZ_ASSERT_DEV(!IsEmpty(), "The container is empty.");
187 
188  return m_Last.m_pPrev->m_Data;
189 }
190 
191 
192 template <typename T>
193 EZ_FORCE_INLINE void ezListBase<T>::PushBack()
194 {
195  PushBack(T());
196 }
197 
198 template <typename T>
199 EZ_FORCE_INLINE void ezListBase<T>::PushBack(const T& element)
200 {
201  Insert(GetEndIterator(), element);
202 }
203 
204 template <typename T>
205 EZ_FORCE_INLINE void ezListBase<T>::PushFront()
206 {
207  PushFront(T());
208 }
209 
210 template <typename T>
211 EZ_FORCE_INLINE void ezListBase<T>::PushFront(const T& element)
212 {
213  Insert(GetIterator(), element);
214 }
215 
216 template <typename T>
217 EZ_FORCE_INLINE void ezListBase<T>::PopBack()
218 {
219  EZ_ASSERT_DEV(!IsEmpty(), "The container is empty.");
220 
221  Remove(Iterator(m_Last.m_pPrev));
222 }
223 
224 template <typename T>
226 {
227  EZ_ASSERT_DEV(!IsEmpty(), "The container is empty.");
228 
229  Remove(Iterator(m_First.m_pNext));
230 }
231 
232 template <typename T>
233 typename ezListBase<T>::Iterator ezListBase<T>::Insert(const Iterator& pos, const T& data)
234 {
235  EZ_ASSERT_DEV(pos.m_pElement != nullptr, "The iterator (pos) is invalid.");
236 
237  ++m_uiCount;
238  ListElement* elem = AcquireNode(data);
239 
240  elem->m_pNext = pos.m_pElement;
241  elem->m_pPrev = pos.m_pElement->m_pPrev;
242 
243  pos.m_pElement->m_pPrev->m_pNext = elem;
244  pos.m_pElement->m_pPrev = elem;
245 
246  return Iterator(elem);
247 }
248 
249 template <typename T>
250 void ezListBase<T>::Insert(const Iterator& pos, ConstIterator first, const ConstIterator& last)
251 {
252  EZ_ASSERT_DEV(pos.m_pElement != nullptr, "The iterator (pos) is invalid.");
253  EZ_ASSERT_DEV(first.m_pElement != nullptr, "The iterator (first) is invalid.");
254  EZ_ASSERT_DEV(last.m_pElement != nullptr, "The iterator (last) is invalid.");
255 
256  while (first != last)
257  {
258  Insert(pos, *first);
259  ++first;
260  }
261 }
262 
263 template <typename T>
265 {
266  EZ_ASSERT_DEV(!IsEmpty(), "The container is empty.");
267  EZ_ASSERT_DEV(pos.m_pElement != nullptr, "The iterator (pos) is invalid.");
268 
269  ListElement* pPrev = pos.m_pElement->m_pPrev;
270  ListElement* pNext = pos.m_pElement->m_pNext;
271 
272  pPrev->m_pNext = pNext;
273  pNext->m_pPrev = pPrev;
274 
275  ReleaseNode(pos.m_pElement);
276 
277  return Iterator(pNext);
278 }
279 
280 template <typename T>
282 {
283  EZ_ASSERT_DEV(!IsEmpty(), "The container is empty.");
284  EZ_ASSERT_DEV(first.m_pElement != nullptr, "The iterator (first) is invalid.");
285  EZ_ASSERT_DEV(last.m_pElement != nullptr, "The iterator (last) is invalid.");
286 
287  while (first != last)
288  first = Remove(first);
289 
290  return last;
291 }
292 
296 template <typename T>
297 void ezListBase<T>::SetCount(ezUInt32 uiNewSize)
298 {
299  while (m_uiCount > uiNewSize)
300  PopBack();
301 
302  while (m_uiCount < uiNewSize)
303  PushBack();
304 }
305 
306 template <typename T>
308 {
309  if (GetCount() != rhs.GetCount())
310  return false;
311 
312  auto itLhs = GetIterator();
313  auto itRhs = rhs.GetIterator();
314 
315  while (itLhs.IsValid())
316  {
317  if (*itLhs != *itRhs)
318  return false;
319 
320  ++itLhs;
321  ++itRhs;
322  }
323 
324  return true;
325 }
326 
327 template <typename T>
329 {
330  return !operator==(rhs);
331 }
332 
333 template <typename T, typename A>
334 ezList<T, A>::ezList() : ezListBase<T>(A::GetAllocator())
335 {
336 }
337 
338 template <typename T, typename A>
339 ezList<T, A>::ezList(ezAllocatorBase* pAllocator) : ezListBase<T>(pAllocator)
340 {
341 }
342 
343 template <typename T, typename A>
344 ezList<T, A>::ezList(const ezList<T, A>& other) : ezListBase<T>(other, A::GetAllocator())
345 {
346 }
347 
348 template <typename T, typename A>
349 ezList<T, A>::ezList(const ezListBase<T>& other) : ezListBase<T>(other, A::GetAllocator())
350 {
351 }
352 
353 template <typename T, typename A>
354 void ezList<T, A>::operator=(const ezList<T, A>& rhs)
355 {
357 }
358 
359 template <typename T, typename A>
360 void ezList<T, A>::operator=(const ezListBase<T>& rhs)
361 {
363 }
364