ezEngine  Milestone 9
ArrayBase_inl.h
1 
2 template <typename T, typename Derived>
4 {
5  m_pElements = nullptr;
6  m_uiCount = 0;
7  m_uiCapacity = 0;
8 }
9 
10 template <typename T, typename Derived>
12 {
13  EZ_ASSERT_DEBUG(m_uiCount == 0, "The derived class did not destruct all objects. Count is {0}.", m_uiCount);
14  EZ_ASSERT_DEBUG(m_pElements == nullptr, "The derived class did not free its memory.");
15 }
16 
17 template <typename T, typename Derived>
19 {
20  if (this->GetData() == rhs.GetPtr())
21  {
22  if (m_uiCount == rhs.GetCount())
23  return;
24 
25  EZ_ASSERT_DEV(m_uiCount > rhs.GetCount(), "Dangling array pointer. The given array pointer points to invalid memory.");
26  T* pElements = static_cast<Derived*>(this)->GetElementsPtr();
27  ezMemoryUtils::Destruct(pElements + rhs.GetCount(), m_uiCount - rhs.GetCount());
28  m_uiCount = rhs.GetCount();
29  return;
30  }
31 
32  const ezUInt32 uiOldCount = m_uiCount;
33  const ezUInt32 uiNewCount = rhs.GetCount();
34 
35  if (uiNewCount > uiOldCount)
36  {
37  static_cast<Derived*>(this)->Reserve(uiNewCount);
38  T* pElements = static_cast<Derived*>(this)->GetElementsPtr();
39  ezMemoryUtils::Copy(pElements, rhs.GetPtr(), uiOldCount);
40  ezMemoryUtils::CopyConstructArray(pElements + uiOldCount, rhs.GetPtr() + uiOldCount, uiNewCount - uiOldCount);
41  }
42  else
43  {
44  T* pElements = static_cast<Derived*>(this)->GetElementsPtr();
45  ezMemoryUtils::Copy(pElements, rhs.GetPtr(), uiNewCount);
46  ezMemoryUtils::Destruct(pElements + uiNewCount, uiOldCount - uiNewCount);
47  }
48 
49  m_uiCount = uiNewCount;
50 }
51 
52 template <typename T, typename Derived>
54 {
55  return ezArrayPtr<const T>(static_cast<const Derived*>(this)->GetElementsPtr(), m_uiCount);
56 }
57 
58 template <typename T, typename Derived>
60 {
61  return ezArrayPtr<T>(static_cast<Derived*>(this)->GetElementsPtr(), m_uiCount);
62 }
63 
64 template <typename T, typename Derived>
66 {
67  if (m_uiCount != rhs.GetCount())
68  return false;
69 
70  return ezMemoryUtils::IsEqual(static_cast<const Derived*>(this)->GetElementsPtr(), rhs.GetPtr(), m_uiCount);
71 }
72 
73 template <typename T, typename Derived>
74 EZ_ALWAYS_INLINE bool ezArrayBase<T, Derived>::operator!=(const ezArrayPtr<const T>& rhs) const
75 {
76  return !(*this == rhs);
77 }
78 
79 template <typename T, typename Derived>
80 EZ_ALWAYS_INLINE const T& ezArrayBase<T, Derived>::operator[](const ezUInt32 uiIndex) const
81 {
82  EZ_ASSERT_DEV(uiIndex < m_uiCount, "Out of bounds access. Array has {0} elements, trying to access element at index {1}.", m_uiCount,
83  uiIndex);
84  return static_cast<const Derived*>(this)->GetElementsPtr()[uiIndex];
85 }
86 
87 template <typename T, typename Derived>
88 EZ_ALWAYS_INLINE T& ezArrayBase<T, Derived>::operator[](const ezUInt32 uiIndex)
89 {
90  EZ_ASSERT_DEV(uiIndex < m_uiCount, "Out of bounds access. Array has {0} elements, trying to access element at index {1}.", m_uiCount,
91  uiIndex);
92  return static_cast<Derived*>(this)->GetElementsPtr()[uiIndex];
93 }
94 
95 template <typename T, typename Derived>
96 void ezArrayBase<T, Derived>::SetCount(ezUInt32 uiCount)
97 {
98  const ezUInt32 uiOldCount = m_uiCount;
99  const ezUInt32 uiNewCount = uiCount;
100 
101  if (uiNewCount > uiOldCount)
102  {
103  static_cast<Derived*>(this)->Reserve(uiNewCount);
104  ezMemoryUtils::DefaultConstruct(static_cast<Derived*>(this)->GetElementsPtr() + uiOldCount, uiNewCount - uiOldCount);
105  }
106  else if (uiNewCount < uiOldCount)
107  {
108  ezMemoryUtils::Destruct(static_cast<Derived*>(this)->GetElementsPtr() + uiNewCount, uiOldCount - uiNewCount);
109  }
110 
111  m_uiCount = uiCount;
112 }
113 
114 template <typename T, typename Derived>
115 void ezArrayBase<T, Derived>::SetCount(ezUInt32 uiCount, const T& FillValue)
116 {
117  const ezUInt32 uiOldCount = m_uiCount;
118  const ezUInt32 uiNewCount = uiCount;
119 
120  if (uiNewCount > uiOldCount)
121  {
122  static_cast<Derived*>(this)->Reserve(uiNewCount);
123  ezMemoryUtils::CopyConstruct(static_cast<Derived*>(this)->GetElementsPtr() + uiOldCount, FillValue, uiNewCount - uiOldCount);
124  }
125  else if (uiNewCount < uiOldCount)
126  {
127  ezMemoryUtils::Destruct(static_cast<Derived*>(this)->GetElementsPtr() + uiNewCount, uiOldCount - uiNewCount);
128  }
129 
130  m_uiCount = uiCount;
131 }
132 
133 template <typename T, typename Derived>
135 {
136  if (uiCount > m_uiCount)
137  {
138  SetCount(uiCount);
139  }
140 }
141 
142 template <typename T, typename Derived>
143 template <typename> // second template needed so that the compiler does only instantiate it when called. Otherwise the static_assert would
144  // trigger early.
146 {
147  static_assert(ezIsPodType<T>::value == ezTypeIsPod::value, "SetCountUninitialized is only supported for POD types.");
148  const ezUInt32 uiOldCount = m_uiCount;
149  const ezUInt32 uiNewCount = uiCount;
150 
151  if (uiNewCount > uiOldCount)
152  {
153  static_cast<Derived*>(this)->Reserve(uiNewCount);
154  ezMemoryUtils::Construct(static_cast<Derived*>(this)->GetElementsPtr() + uiOldCount, uiNewCount - uiOldCount);
155  }
156  else if (uiNewCount < uiOldCount)
157  {
158  ezMemoryUtils::Destruct(static_cast<Derived*>(this)->GetElementsPtr() + uiNewCount, uiOldCount - uiNewCount);
159  }
160 
161  m_uiCount = uiCount;
162 }
163 
164 template <typename T, typename Derived>
165 EZ_ALWAYS_INLINE ezUInt32 ezArrayBase<T, Derived>::GetCount() const
166 {
167  return m_uiCount;
168 }
169 
170 template <typename T, typename Derived>
171 EZ_ALWAYS_INLINE bool ezArrayBase<T, Derived>::IsEmpty() const
172 {
173  return m_uiCount == 0;
174 }
175 
176 template <typename T, typename Derived>
178 {
179  ezMemoryUtils::Destruct(static_cast<Derived*>(this)->GetElementsPtr(), m_uiCount);
180  m_uiCount = 0;
181 }
182 
183 template <typename T, typename Derived>
184 bool ezArrayBase<T, Derived>::Contains(const T& value) const
185 {
186  return IndexOf(value) != ezInvalidIndex;
187 }
188 
189 template <typename T, typename Derived>
190 void ezArrayBase<T, Derived>::Insert(const T& value, ezUInt32 uiIndex)
191 {
192  EZ_ASSERT_DEV(uiIndex <= m_uiCount, "Invalid index. Array has {0} elements, trying to insert element at index {1}.", m_uiCount, uiIndex);
193 
194  static_cast<Derived*>(this)->Reserve(m_uiCount + 1);
195 
196  ezMemoryUtils::Prepend(static_cast<Derived*>(this)->GetElementsPtr() + uiIndex, value, m_uiCount - uiIndex);
197  m_uiCount++;
198 }
199 
200 template <typename T, typename Derived>
201 void ezArrayBase<T, Derived>::Insert(T&& value, ezUInt32 uiIndex)
202 {
203  EZ_ASSERT_DEV(uiIndex <= m_uiCount, "Invalid index. Array has {0} elements, trying to insert element at index {1}.", m_uiCount, uiIndex);
204 
205  static_cast<Derived*>(this)->Reserve(m_uiCount + 1);
206 
207  ezMemoryUtils::Prepend(static_cast<Derived*>(this)->GetElementsPtr() + uiIndex, std::move(value), m_uiCount - uiIndex);
208  m_uiCount++;
209 }
210 
211 template <typename T, typename Derived>
213 {
214  ezUInt32 uiIndex = IndexOf(value);
215 
216  if (uiIndex == ezInvalidIndex)
217  return false;
218 
219  RemoveAtAndCopy(uiIndex);
220  return true;
221 }
222 
223 template <typename T, typename Derived>
225 {
226  ezUInt32 uiIndex = IndexOf(value);
227 
228  if (uiIndex == ezInvalidIndex)
229  return false;
230 
231  RemoveAtAndSwap(uiIndex);
232  return true;
233 }
234 
235 template <typename T, typename Derived>
237 {
238  EZ_ASSERT_DEV(uiIndex < m_uiCount, "Out of bounds access. Array has {0} elements, trying to remove element at index {1}.", m_uiCount,
239  uiIndex);
240 
241  T* pElements = static_cast<Derived*>(this)->GetElementsPtr();
242 
243  m_uiCount--;
244  ezMemoryUtils::RelocateOverlapped(pElements + uiIndex, pElements + uiIndex + 1, m_uiCount - uiIndex);
245 }
246 
247 template <typename T, typename Derived>
249 {
250  EZ_ASSERT_DEV(uiIndex < m_uiCount, "Out of bounds access. Array has {0} elements, trying to remove element at index {1}.", m_uiCount,
251  uiIndex);
252 
253  T* pElements = static_cast<Derived*>(this)->GetElementsPtr();
254 
255  m_uiCount--;
256  if (m_uiCount != uiIndex)
257  {
258  pElements[uiIndex] = std::move(pElements[m_uiCount]);
259  }
260  ezMemoryUtils::Destruct(pElements + m_uiCount, 1);
261 }
262 
263 template <typename T, typename Derived>
264 ezUInt32 ezArrayBase<T, Derived>::IndexOf(const T& value, ezUInt32 uiStartIndex) const
265 {
266  const T* pElements = static_cast<const Derived*>(this)->GetElementsPtr();
267 
268  for (ezUInt32 i = uiStartIndex; i < m_uiCount; i++)
269  {
270  if (ezMemoryUtils::IsEqual(pElements + i, &value))
271  return i;
272  }
273  return ezInvalidIndex;
274 }
275 
276 template <typename T, typename Derived>
277 ezUInt32 ezArrayBase<T, Derived>::LastIndexOf(const T& value, ezUInt32 uiStartIndex) const
278 {
279  const T* pElements = static_cast<const Derived*>(this)->GetElementsPtr();
280 
281  for (ezUInt32 i = ezMath::Min(uiStartIndex, m_uiCount); i-- > 0;)
282  {
283  if (ezMemoryUtils::IsEqual(pElements + i, &value))
284  return i;
285  }
286  return ezInvalidIndex;
287 }
288 
289 template <typename T, typename Derived>
291 {
292  static_cast<Derived*>(this)->Reserve(m_uiCount + 1);
293 
294  T* pElements = static_cast<Derived*>(this)->GetElementsPtr();
295 
296  ezMemoryUtils::Construct(pElements + m_uiCount, 1);
297 
298  T& ReturnRef = *(pElements + m_uiCount);
299 
300  m_uiCount++;
301 
302  return ReturnRef;
303 }
304 
305 template <typename T, typename Derived>
307 {
308  static_cast<Derived*>(this)->Reserve(m_uiCount + 1);
309 
310  ezMemoryUtils::CopyConstruct(static_cast<Derived*>(this)->GetElementsPtr() + m_uiCount, value, 1);
311  m_uiCount++;
312 }
313 
314 template <typename T, typename Derived>
316 {
317  static_cast<Derived*>(this)->Reserve(m_uiCount + 1);
318 
319  ezMemoryUtils::MoveConstruct<T>(static_cast<Derived*>(this)->GetElementsPtr() + m_uiCount, std::move(value));
320  m_uiCount++;
321 }
322 
323 template <typename T, typename Derived>
325 {
326  EZ_ASSERT_DEV(m_uiCount < m_uiCapacity, "Appending unchecked to array with insufficient capacity.");
327 
328  ezMemoryUtils::CopyConstruct(static_cast<Derived*>(this)->GetElementsPtr() + m_uiCount, value, 1);
329  m_uiCount++;
330 }
331 
332 template <typename T, typename Derived>
334 {
335  EZ_ASSERT_DEV(m_uiCount < m_uiCapacity, "Appending unchecked to array with insufficient capacity.");
336 
337  ezMemoryUtils::MoveConstruct<T>(static_cast<Derived*>(this)->GetElementsPtr() + m_uiCount, std::move(value));
338  m_uiCount++;
339 }
340 
341 template <typename T, typename Derived>
343 {
344  const ezUInt32 uiRangeCount = range.GetCount();
345  static_cast<Derived*>(this)->Reserve(m_uiCount + uiRangeCount);
346 
347  ezMemoryUtils::CopyConstructArray(static_cast<Derived*>(this)->GetElementsPtr() + m_uiCount, range.GetPtr(), uiRangeCount);
348  m_uiCount += uiRangeCount;
349 }
350 
351 template <typename T, typename Derived>
352 void ezArrayBase<T, Derived>::PopBack(ezUInt32 uiCountToRemove /* = 1 */)
353 {
354  EZ_ASSERT_DEV(m_uiCount >= uiCountToRemove, "Out of bounds access. Array has {0} elements, trying to pop {1} elements.", m_uiCount,
355  uiCountToRemove);
356 
357  m_uiCount -= uiCountToRemove;
358  ezMemoryUtils::Destruct(static_cast<Derived*>(this)->GetElementsPtr() + m_uiCount, uiCountToRemove);
359 }
360 
361 template <typename T, typename Derived>
363 {
364  EZ_ASSERT_DEV(m_uiCount > 0, "Out of bounds access. Trying to peek into an empty array.");
365  return static_cast<Derived*>(this)->GetElementsPtr()[m_uiCount - 1];
366 }
367 
368 template <typename T, typename Derived>
369 EZ_FORCE_INLINE const T& ezArrayBase<T, Derived>::PeekBack() const
370 {
371  EZ_ASSERT_DEV(m_uiCount > 0, "Out of bounds access. Trying to peek into an empty array.");
372  return static_cast<const Derived*>(this)->GetElementsPtr()[m_uiCount - 1];
373 }
374 
375 template <typename T, typename Derived>
376 template <typename Comparer>
377 void ezArrayBase<T, Derived>::Sort(const Comparer& comparer)
378 {
379  if (m_uiCount > 1)
380  {
381  ezArrayPtr<T> ar = *this;
382  ezSorting::QuickSort(ar, comparer);
383  }
384 }
385 
386 template <typename T, typename Derived>
388 {
389  if (m_uiCount > 1)
390  {
391  ezArrayPtr<T> ar = *this;
393  }
394 }
395 
396 template <typename T, typename Derived>
397 EZ_ALWAYS_INLINE T* ezArrayBase<T, Derived>::GetData()
398 {
399  if (IsEmpty())
400  return nullptr;
401 
402  return static_cast<Derived*>(this)->GetElementsPtr();
403 }
404 
405 template <typename T, typename Derived>
406 EZ_ALWAYS_INLINE const T* ezArrayBase<T, Derived>::GetData() const
407 {
408  if (IsEmpty())
409  return nullptr;
410 
411  return static_cast<const Derived*>(this)->GetElementsPtr();
412 }
413 
414 template <typename T, typename Derived>
416 {
417  return ezArrayPtr<T>(GetData(), GetCount());
418 }
419 
420 template <typename T, typename Derived>
422 {
423  return ezArrayPtr<const T>(GetData(), GetCount());
424 }
425 
426 template <typename T, typename Derived>
428 {
429  return GetArrayPtr().ToByteArray();
430 }
431 
432 template <typename T, typename Derived>
434 {
435  return GetArrayPtr().ToByteArray();
436 }
437 
438 template <typename T, typename Derived>
440 {
441  ezMath::Swap(this->m_pElements, other.m_pElements);
442  ezMath::Swap(this->m_uiCapacity, other.m_uiCapacity);
443  ezMath::Swap(this->m_uiCount, other.m_uiCount);
444 }
445 
ezUInt32 GetCount() const
Returns the number of active elements in the array.
Definition: ArrayBase_inl.h:165
EZ_ALWAYS_INLINE void Swap(T &f1, T &f2)
Swaps the values in the two variables f1 and f2.
Definition: Math_inl.h:112
void PushBackRange(const ezArrayPtr< const T > &range)
Pushes all elements in range at the end of the array. Increases the capacity if necessary.
Definition: ArrayBase_inl.h:342
bool IsEmpty() const
Returns true, if the array does not contain any elements.
Definition: ArrayBase_inl.h:171
void PopBack(ezUInt32 uiCountToRemove=1)
Removes count elements from the end of the array.
Definition: ArrayBase_inl.h:352
void EnsureCount(ezUInt32 uiCount)
Ensures the container has at least uiCount elements. Ie. calls SetCount() if the container has fewer ...
Definition: ArrayBase_inl.h:134
bool RemoveAndSwap(const T &value)
Removes the first occurrence of value and fills the gap by swapping in the last element.
Definition: ArrayBase_inl.h:224
#define EZ_ASSERT_DEBUG(bCondition, szErrorMsg,...)
Macro to raise an error, if a condition is not met.
Definition: Assert.h:88
bool operator==(const ezArrayPtr< const T > &rhs) const
Compares this array to another contiguous array type.
Definition: ArrayBase_inl.h:65
ezArrayBase()
Constructor.
Definition: ArrayBase_inl.h:3
static void Construct(T *pDestination, size_t uiCount)
Constructs uiCount objects of type T in a raw buffer at pDestination.
const T & operator[](ezUInt32 uiIndex) const
Returns the element at the given index. Does bounds checks in debug builds.
Definition: ArrayBase_inl.h:80
void PushBackUnchecked(const T &value)
Pushes value at the end of the array. Does NOT ensure capacity.
Definition: ArrayBase_inl.h:324
void SetCountUninitialized(ezUInt32 uiCount)
Resizes the array to have exactly uiCount elements. Extra elements might be uninitialized.
Definition: ArrayBase_inl.h:145
void Sort()
Sort with default comparer.
Definition: ArrayBase_inl.h:387
static void CopyConstruct(Destination *pDestination, const Source &copy, size_t uiCount)
Constructs uiCount objects of type T in a raw buffer at pDestination, by creating uiCount copies of c...
#define EZ_ASSERT_DEV(bCondition, szErrorMsg,...)
Macro to raise an error, if a condition is not met.
Definition: Assert.h:116
void RemoveAtAndSwap(ezUInt32 uiIndex)
Removes the element at index and fills the gap by swapping in the last element.
Definition: ArrayBase_inl.h:248
static void Destruct(T *pDestination, size_t uiCount)
Destructs uiCount objects of type T at pDestination.
T * GetData()
Returns a pointer to the array data, or nullptr if the array is empty.
Definition: ArrayBase_inl.h:397
bool RemoveAndCopy(const T &value)
Removes the first occurrence of value and fills the gap by shifting all following elements...
Definition: ArrayBase_inl.h:212
static void QuickSort(Container &container, const Comparer &comparer=Comparer())
Sorts the elements in container using a in-place quick sort implementation (not stable).
Definition: Sorting_inl.h:3
static void CopyConstructArray(T *pDestination, const T *pSource, size_t uiCount)
Constructs uiCount objects of type T in a raw buffer at pDestination from an existing array of object...
EZ_ALWAYS_INLINE ezUInt32 GetCount() const
Returns the number of elements in the array.
Definition: ArrayPtr.h:182
Base class for all array containers. Implements all the basic functionality that only requires a poin...
Definition: ArrayBase.h:12
static void DefaultConstruct(T *pDestination, size_t uiCount)
Default constructs uiCount objects of type T in a raw buffer at pDestination regardless of T being a ...
void SetCount(ezUInt32 uiCount)
Resizes the array to have exactly uiCount elements. Default constructs extra elements if the array is...
Definition: ArrayBase_inl.h:96
static void RelocateOverlapped(T *pDestination, T *pSource, size_t uiCount)
Moves objects of type T from pSource to pDestination.
constexpr EZ_ALWAYS_INLINE T Min(T f1, T f2)
Returns the smaller value, f1 or f2.
Definition: Math_inl.h:26
static void Prepend(T *pDestination, const T &source, size_t uiCount)
Moves uiCount objects in pDestination by one object and copies source to the free space...
static bool IsEqual(const T *a, const T *b, size_t uiCount=1)
Tests if objects of type T from pSource and pDestination are equal.
void Insert(const T &value, ezUInt32 uiIndex)
Inserts value at index by shifting all following elements.
Definition: ArrayBase_inl.h:190
ezArrayPtr< typename ezArrayPtr< T >::ByteType > GetByteArrayPtr()
Returns a byte array pointer to the array data, or an empty array pointer if the array is empty...
Definition: ArrayBase_inl.h:427
T & ExpandAndGetRef()
Grows the array by one element and returns a reference to the newly created element.
Definition: ArrayBase_inl.h:290
If there is an % operator which takes a TypeIsPod and returns a CompileTimeTrueType T is Pod...
Definition: TypeTraits.h:30
static void Copy(T *pDestination, const T *pSource, size_t uiCount)
Copies objects of type T from pSource to pDestination.
bool operator!=(const ezArrayPtr< const T > &rhs) const
Compares this array to another contiguous array type.
Definition: ArrayBase_inl.h:74
T * m_pElements
Element-type access to m_Data.
Definition: ArrayBase.h:155
~ezArrayBase()
Destructor.
Definition: ArrayBase_inl.h:11
void RemoveAtAndCopy(ezUInt32 uiIndex)
Removes the element at index and fills the gap by shifting all following elements.
Definition: ArrayBase_inl.h:236
EZ_ALWAYS_INLINE const PointerType GetPtr() const
Returns the pointer to the array.
Definition: ArrayPtr.h:158
ezUInt32 m_uiCount
The number of elements used from the array.
Definition: ArrayBase.h:158
ezUInt32 LastIndexOf(const T &value, ezUInt32 uiStartIndex=ezInvalidIndex) const
Searches for the last occurrence of the given value and returns its index or ezInvalidIndex if not fo...
Definition: ArrayBase_inl.h:277
void Clear()
Clears the array.
Definition: ArrayBase_inl.h:177
void PushBack(const T &value)
Pushes value at the end of the array.
Definition: ArrayBase_inl.h:306
ezUInt32 IndexOf(const T &value, ezUInt32 uiStartIndex=0) const
Searches for the first occurrence of the given value and returns its index or ezInvalidIndex if not f...
Definition: ArrayBase_inl.h:264
bool Contains(const T &value) const
Checks whether the given value can be found in the array. O(n) complexity.
Definition: ArrayBase_inl.h:184
void operator=(const ezArrayPtr< const T > &rhs)
Copies the data from some other contiguous array into this one.
Definition: ArrayBase_inl.h:18
ezArrayPtr< T > GetArrayPtr()
Returns an array pointer to the array data, or an empty array pointer if the array is empty...
Definition: ArrayBase_inl.h:415
ezUInt32 m_uiCapacity
The number of elements which can be stored in the array without re-allocating.
Definition: ArrayBase.h:161
T & PeekBack()
Returns the last element of the array.
Definition: ArrayBase_inl.h:362
This class encapsulates an array and it&#39;s size. It is recommended to use this class instead of plain ...
Definition: ArrayPtr.h:82
A comparer object is used in sorting algorithms to compare to objects of the same type...
Definition: Comparer.h:6