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