Plasma Engine  2.0
Loading...
Searching...
No Matches
SmallArray_inl.h
1
2template <typename T, plUInt16 Size>
4
5template <typename T, plUInt16 Size>
7{
8 CopyFrom((plArrayPtr<const T>)other, pAllocator);
9 m_uiUserData = other.m_uiUserData;
10}
11
12template <typename T, plUInt16 Size>
13PL_ALWAYS_INLINE plSmallArrayBase<T, Size>::plSmallArrayBase(const plArrayPtr<const T>& other, plAllocator* pAllocator)
14{
15 CopyFrom(other, pAllocator);
16}
17
18template <typename T, plUInt16 Size>
20{
21 MoveFrom(std::move(other), pAllocator);
22}
23
24template <typename T, plUInt16 Size>
26{
27 PL_ASSERT_DEBUG(m_uiCount == 0, "The derived class did not destruct all objects. Count is {0}.", m_uiCount);
28 PL_ASSERT_DEBUG(m_pElements == nullptr, "The derived class did not free its memory.");
29}
30
31template <typename T, plUInt16 Size>
33{
34 PL_ASSERT_DEV(other.GetCount() <= plSmallInvalidIndex, "Can't copy {} elements to small array. Maximum count is {}", other.GetCount(), plSmallInvalidIndex);
35
36 if (GetData() == other.GetPtr())
37 {
38 if (m_uiCount == other.GetCount())
39 return;
41 PL_ASSERT_DEV(m_uiCount > other.GetCount(), "Dangling array pointer. The given array pointer points to invalid memory.");
42 T* pElements = GetElementsPtr();
43 plMemoryUtils::Destruct(pElements + other.GetCount(), m_uiCount - other.GetCount());
44 m_uiCount = static_cast<plUInt16>(other.GetCount());
45 return;
46 }
47
48 const plUInt32 uiOldCount = m_uiCount;
49 const plUInt32 uiNewCount = other.GetCount();
50
51 if (uiNewCount > uiOldCount)
52 {
53 Reserve(static_cast<plUInt16>(uiNewCount), pAllocator);
54 T* pElements = GetElementsPtr();
55 plMemoryUtils::Copy(pElements, other.GetPtr(), uiOldCount);
56 plMemoryUtils::CopyConstructArray(pElements + uiOldCount, other.GetPtr() + uiOldCount, uiNewCount - uiOldCount);
57 }
58 else
59 {
60 T* pElements = GetElementsPtr();
61 plMemoryUtils::Copy(pElements, other.GetPtr(), uiNewCount);
62 plMemoryUtils::Destruct(pElements + uiNewCount, uiOldCount - uiNewCount);
63 }
64
65 m_uiCount = static_cast<plUInt16>(uiNewCount);
66}
68template <typename T, plUInt16 Size>
70{
71 Clear();
72
73 if (other.m_uiCapacity > Size)
74 {
75 if (m_uiCapacity > Size)
76 {
77 // only delete our own external storage
78 PL_DELETE_RAW_BUFFER(pAllocator, m_pElements);
79 }
81 m_uiCapacity = other.m_uiCapacity;
82 m_pElements = other.m_pElements;
83 }
84 else
85 {
86 plMemoryUtils::RelocateConstruct(GetElementsPtr(), other.GetElementsPtr(), other.m_uiCount);
87 }
88
89 m_uiCount = other.m_uiCount;
90 m_uiUserData = other.m_uiUserData;
91
92 // reset the other array to not reference the data anymore
93 other.m_pElements = nullptr;
94 other.m_uiCount = 0;
95 other.m_uiCapacity = 0;
96}
97
98template <typename T, plUInt16 Size>
100{
101 return plArrayPtr<const T>(GetElementsPtr(), m_uiCount);
102}
103
104template <typename T, plUInt16 Size>
106{
107 return plArrayPtr<T>(GetElementsPtr(), m_uiCount);
108}
109
110template <typename T, plUInt16 Size>
112{
113 return *this == rhs.GetArrayPtr();
114}
115
116#if PL_DISABLED(PL_USE_CPP20_OPERATORS)
117template <typename T, plUInt16 Size>
120 if (m_uiCount != rhs.GetCount())
121 return false;
123 return plMemoryUtils::IsEqual(GetElementsPtr(), rhs.GetPtr(), m_uiCount);
124}
125#endif
126
127template <typename T, plUInt16 Size>
128PL_ALWAYS_INLINE const T& plSmallArrayBase<T, Size>::operator[](const plUInt32 uiIndex) const
129{
130 PL_ASSERT_DEBUG(uiIndex < m_uiCount, "Out of bounds access. Array has {0} elements, trying to access element at index {1}.", m_uiCount, uiIndex);
131 return GetElementsPtr()[uiIndex];
132}
133
134template <typename T, plUInt16 Size>
135PL_ALWAYS_INLINE T& plSmallArrayBase<T, Size>::operator[](const plUInt32 uiIndex)
136{
137 PL_ASSERT_DEBUG(uiIndex < m_uiCount, "Out of bounds access. Array has {0} elements, trying to access element at index {1}.", m_uiCount, uiIndex);
138 return GetElementsPtr()[uiIndex];
139}
140
141template <typename T, plUInt16 Size>
142void plSmallArrayBase<T, Size>::SetCount(plUInt16 uiCount, plAllocator* pAllocator)
143{
144 const plUInt32 uiOldCount = m_uiCount;
145 const plUInt32 uiNewCount = uiCount;
146
147 if (uiNewCount > uiOldCount)
148 {
149 Reserve(static_cast<plUInt16>(uiNewCount), pAllocator);
150 plMemoryUtils::Construct<ConstructAll>(GetElementsPtr() + uiOldCount, uiNewCount - uiOldCount);
151 }
152 else if (uiNewCount < uiOldCount)
154 plMemoryUtils::Destruct(GetElementsPtr() + uiNewCount, uiOldCount - uiNewCount);
155 }
157 m_uiCount = uiCount;
158}
160template <typename T, plUInt16 Size>
161void plSmallArrayBase<T, Size>::SetCount(plUInt16 uiCount, const T& fillValue, plAllocator* pAllocator)
163 const plUInt32 uiOldCount = m_uiCount;
164 const plUInt32 uiNewCount = uiCount;
165
166 if (uiNewCount > uiOldCount)
167 {
168 Reserve(uiCount, pAllocator);
169 plMemoryUtils::CopyConstruct(GetElementsPtr() + uiOldCount, fillValue, uiNewCount - uiOldCount);
170 }
171 else if (uiNewCount < uiOldCount)
173 plMemoryUtils::Destruct(GetElementsPtr() + uiNewCount, uiOldCount - uiNewCount);
174 }
175
176 m_uiCount = uiCount;
177}
178
179template <typename T, plUInt16 Size>
180void plSmallArrayBase<T, Size>::EnsureCount(plUInt16 uiCount, plAllocator* pAllocator)
181{
182 if (uiCount > m_uiCount)
183 {
184 SetCount(uiCount, pAllocator);
185 }
186}
187
188template <typename T, plUInt16 Size>
189template <typename> // Second template needed so that the compiler does only instantiate it when called. Otherwise the static_assert would trigger early.
191{
192 static_assert(plIsPodType<T>::value == plTypeIsPod::value, "SetCountUninitialized is only supported for POD types.");
193 const plUInt16 uiOldCount = m_uiCount;
194 const plUInt16 uiNewCount = uiCount;
195
196 if (uiNewCount > uiOldCount)
197 {
198 Reserve(uiNewCount, pAllocator);
199 plMemoryUtils::Construct<SkipTrivialTypes>(GetElementsPtr() + uiOldCount, uiNewCount - uiOldCount);
200 }
201 else if (uiNewCount < uiOldCount)
202 {
203 plMemoryUtils::Destruct(GetElementsPtr() + uiNewCount, uiOldCount - uiNewCount);
204 }
205
206 m_uiCount = uiCount;
207}
208
209template <typename T, plUInt16 Size>
210PL_ALWAYS_INLINE plUInt32 plSmallArrayBase<T, Size>::GetCount() const
211{
212 return m_uiCount;
213}
214
215template <typename T, plUInt16 Size>
216PL_ALWAYS_INLINE bool plSmallArrayBase<T, Size>::IsEmpty() const
217{
218 return m_uiCount == 0;
219}
220
221template <typename T, plUInt16 Size>
223{
224 plMemoryUtils::Destruct(GetElementsPtr(), m_uiCount);
225 m_uiCount = 0;
226}
227
228template <typename T, plUInt16 Size>
229bool plSmallArrayBase<T, Size>::Contains(const T& value) const
230{
231 return IndexOf(value) != plInvalidIndex;
232}
233
234template <typename T, plUInt16 Size>
235void plSmallArrayBase<T, Size>::Insert(const T& value, plUInt32 uiIndex, plAllocator* pAllocator)
236{
237 PL_ASSERT_DEV(uiIndex <= m_uiCount, "Invalid index. Array has {0} elements, trying to insert element at index {1}.", m_uiCount, uiIndex);
238
239 Reserve(m_uiCount + 1, pAllocator);
240
241 plMemoryUtils::Prepend(GetElementsPtr() + uiIndex, value, m_uiCount - uiIndex);
242 m_uiCount++;
243}
244
245template <typename T, plUInt16 Size>
246void plSmallArrayBase<T, Size>::Insert(T&& value, plUInt32 uiIndex, plAllocator* pAllocator)
247{
248 PL_ASSERT_DEV(uiIndex <= m_uiCount, "Invalid index. Array has {0} elements, trying to insert element at index {1}.", m_uiCount, uiIndex);
249
250 Reserve(m_uiCount + 1, pAllocator);
251
252 plMemoryUtils::Prepend(GetElementsPtr() + uiIndex, std::move(value), m_uiCount - uiIndex);
253 m_uiCount++;
254}
255
256template <typename T, plUInt16 Size>
258{
259 plUInt32 uiIndex = IndexOf(value);
260
261 if (uiIndex == plInvalidIndex)
262 return false;
263
264 RemoveAtAndCopy(uiIndex);
265 return true;
266}
267
268template <typename T, plUInt16 Size>
270{
271 plUInt32 uiIndex = IndexOf(value);
272
273 if (uiIndex == plInvalidIndex)
274 return false;
275
276 RemoveAtAndSwap(uiIndex);
277 return true;
278}
279
280template <typename T, plUInt16 Size>
281void plSmallArrayBase<T, Size>::RemoveAtAndCopy(plUInt32 uiIndex, plUInt16 uiNumElements /*= 1*/)
282{
283 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);
284
285 T* pElements = GetElementsPtr();
286
287 m_uiCount -= uiNumElements;
288 plMemoryUtils::RelocateOverlapped(pElements + uiIndex, pElements + uiIndex + uiNumElements, m_uiCount - uiIndex);
289}
290
291template <typename T, plUInt16 Size>
292void plSmallArrayBase<T, Size>::RemoveAtAndSwap(plUInt32 uiIndex, plUInt16 uiNumElements /*= 1*/)
293{
294 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);
295
296 T* pElements = GetElementsPtr();
297
298 for (plUInt32 i = 0; i < uiNumElements; ++i)
299 {
300 m_uiCount--;
301
302 if (m_uiCount != uiIndex)
303 {
304 pElements[uiIndex] = std::move(pElements[m_uiCount]);
305 }
306 plMemoryUtils::Destruct(pElements + m_uiCount, 1);
307 ++uiIndex;
308 }
309}
310
311template <typename T, plUInt16 Size>
312plUInt32 plSmallArrayBase<T, Size>::IndexOf(const T& value, plUInt32 uiStartIndex) const
313{
314 const T* pElements = GetElementsPtr();
315
316 for (plUInt32 i = uiStartIndex; i < m_uiCount; i++)
317 {
318 if (plMemoryUtils::IsEqual(pElements + i, &value))
319 return i;
320 }
321 return plInvalidIndex;
322}
323
324template <typename T, plUInt16 Size>
325plUInt32 plSmallArrayBase<T, Size>::LastIndexOf(const T& value, plUInt32 uiStartIndex) const
326{
327 const T* pElements = GetElementsPtr();
328
329 for (plUInt32 i = plMath::Min<plUInt32>(uiStartIndex, m_uiCount); i-- > 0;)
330 {
331 if (plMemoryUtils::IsEqual(pElements + i, &value))
332 return i;
333 }
334 return plInvalidIndex;
335}
336
337template <typename T, plUInt16 Size>
339{
340 Reserve(m_uiCount + 1, pAllocator);
341
342 T* pElements = GetElementsPtr();
343
344 plMemoryUtils::Construct<SkipTrivialTypes>(pElements + m_uiCount, 1);
345
346 T& ReturnRef = *(pElements + m_uiCount);
347
348 m_uiCount++;
349
350 return ReturnRef;
351}
352
353template <typename T, plUInt16 Size>
354void plSmallArrayBase<T, Size>::PushBack(const T& value, plAllocator* pAllocator)
355{
356 Reserve(m_uiCount + 1, pAllocator);
357
358 plMemoryUtils::CopyConstruct(GetElementsPtr() + m_uiCount, value, 1);
359 m_uiCount++;
360}
361
362template <typename T, plUInt16 Size>
364{
365 Reserve(m_uiCount + 1, pAllocator);
366
367 plMemoryUtils::MoveConstruct<T>(GetElementsPtr() + m_uiCount, std::move(value));
368 m_uiCount++;
369}
370
371template <typename T, plUInt16 Size>
373{
374 PL_ASSERT_DEBUG(m_uiCount < m_uiCapacity, "Appending unchecked to array with insufficient capacity.");
375
376 plMemoryUtils::CopyConstruct(GetElementsPtr() + m_uiCount, value, 1);
377 m_uiCount++;
378}
379
380template <typename T, plUInt16 Size>
382{
383 PL_ASSERT_DEBUG(m_uiCount < m_uiCapacity, "Appending unchecked to array with insufficient capacity.");
384
385 plMemoryUtils::MoveConstruct<T>(GetElementsPtr() + m_uiCount, std::move(value));
386 m_uiCount++;
387}
388
389template <typename T, plUInt16 Size>
391{
392 const plUInt32 uiRangeCount = range.GetCount();
393 Reserve(m_uiCount + uiRangeCount, pAllocator);
394
395 plMemoryUtils::CopyConstructArray(GetElementsPtr() + m_uiCount, range.GetPtr(), uiRangeCount);
396 m_uiCount += uiRangeCount;
397}
398
399template <typename T, plUInt16 Size>
400void plSmallArrayBase<T, Size>::PopBack(plUInt32 uiCountToRemove /* = 1 */)
401{
402 PL_ASSERT_DEBUG(m_uiCount >= uiCountToRemove, "Out of bounds access. Array has {0} elements, trying to pop {1} elements.", m_uiCount, uiCountToRemove);
403
404 m_uiCount -= uiCountToRemove;
405 plMemoryUtils::Destruct(GetElementsPtr() + m_uiCount, uiCountToRemove);
406}
407
408template <typename T, plUInt16 Size>
410{
411 PL_ASSERT_DEBUG(m_uiCount > 0, "Out of bounds access. Trying to peek into an empty array.");
412 return GetElementsPtr()[m_uiCount - 1];
413}
414
415template <typename T, plUInt16 Size>
416PL_FORCE_INLINE const T& plSmallArrayBase<T, Size>::PeekBack() const
417{
418 PL_ASSERT_DEBUG(m_uiCount > 0, "Out of bounds access. Trying to peek into an empty array.");
419 return GetElementsPtr()[m_uiCount - 1];
420}
421
422template <typename T, plUInt16 Size>
423template <typename Comparer>
424void plSmallArrayBase<T, Size>::Sort(const Comparer& comparer)
425{
426 if (m_uiCount > 1)
427 {
428 plArrayPtr<T> ar = GetArrayPtr();
429 plSorting::QuickSort(ar, comparer);
430 }
431}
432
433template <typename T, plUInt16 Size>
435{
436 if (m_uiCount > 1)
437 {
438 plArrayPtr<T> ar = GetArrayPtr();
440 }
441}
442
443template <typename T, plUInt16 Size>
445{
446 if (IsEmpty())
447 return nullptr;
448
449 return GetElementsPtr();
450}
451
452template <typename T, plUInt16 Size>
453PL_ALWAYS_INLINE const T* plSmallArrayBase<T, Size>::GetData() const
454{
455 if (IsEmpty())
456 return nullptr;
457
458 return GetElementsPtr();
459}
460
461template <typename T, plUInt16 Size>
463{
464 return plArrayPtr<T>(GetData(), GetCount());
465}
466
467template <typename T, plUInt16 Size>
469{
470 return plArrayPtr<const T>(GetData(), GetCount());
471}
472
473template <typename T, plUInt16 Size>
478
479template <typename T, plUInt16 Size>
484
485template <typename T, plUInt16 Size>
486void plSmallArrayBase<T, Size>::Reserve(plUInt16 uiCapacity, plAllocator* pAllocator)
487{
488 if (m_uiCapacity >= uiCapacity)
489 return;
490
491 const plUInt32 uiCurCap = static_cast<plUInt32>(m_uiCapacity);
492 plUInt32 uiNewCapacity = uiCurCap + (uiCurCap / 2);
493
494 uiNewCapacity = plMath::Max<plUInt32>(uiNewCapacity, uiCapacity);
495 uiNewCapacity = plMemoryUtils::AlignSize<plUInt32>(uiNewCapacity, CAPACITY_ALIGNMENT);
496 uiNewCapacity = plMath::Min<plUInt32>(uiNewCapacity, 0xFFFFu);
497
498 SetCapacity(static_cast<plUInt16>(uiNewCapacity), pAllocator);
499}
500
501template <typename T, plUInt16 Size>
503{
504 if (IsEmpty())
505 {
506 if (m_uiCapacity > Size)
507 {
508 // completely deallocate all data, if the array is empty.
509 PL_DELETE_RAW_BUFFER(pAllocator, m_pElements);
510 }
511
512 m_uiCapacity = Size;
513 m_pElements = nullptr;
514 }
515 else if (m_uiCapacity > Size)
516 {
517 plUInt32 uiNewCapacity = plMemoryUtils::AlignSize<plUInt32>(m_uiCount, CAPACITY_ALIGNMENT);
518 uiNewCapacity = plMath::Min<plUInt32>(uiNewCapacity, 0xFFFFu);
519
520 if (m_uiCapacity != uiNewCapacity)
521 SetCapacity(static_cast<plUInt16>(uiNewCapacity), pAllocator);
522 }
523}
524
525template <typename T, plUInt16 Size>
526PL_ALWAYS_INLINE plUInt64 plSmallArrayBase<T, Size>::GetHeapMemoryUsage() const
527{
528 return m_uiCapacity <= Size ? 0 : m_uiCapacity * sizeof(T);
529}
530
531template <typename T, plUInt16 Size>
532template <typename U>
533PL_ALWAYS_INLINE const U& plSmallArrayBase<T, Size>::GetUserData() const
534{
535 static_assert(sizeof(U) <= sizeof(plUInt32));
536 return reinterpret_cast<const U&>(m_uiUserData);
537}
538
539template <typename T, plUInt16 Size>
540template <typename U>
541PL_ALWAYS_INLINE U& plSmallArrayBase<T, Size>::GetUserData()
542{
543 static_assert(sizeof(U) <= sizeof(plUInt32));
544 return reinterpret_cast<U&>(m_uiUserData);
545}
546
547template <typename T, plUInt16 Size>
548void plSmallArrayBase<T, Size>::SetCapacity(plUInt16 uiCapacity, plAllocator* pAllocator)
549{
550 if (m_uiCapacity > Size && uiCapacity > m_uiCapacity)
551 {
552 m_pElements = PL_EXTEND_RAW_BUFFER(pAllocator, m_pElements, m_uiCount, uiCapacity);
553 m_uiCapacity = uiCapacity;
554 }
555 else
556 {
557 // special case when migrating from in-place to external storage or shrinking
558 T* pOldElements = GetElementsPtr();
559
560 const plUInt32 uiOldCapacity = m_uiCapacity;
561 const plUInt32 uiNewCapacity = uiCapacity;
562 m_uiCapacity = plMath::Max(uiCapacity, Size);
563
564 if (uiNewCapacity > Size)
565 {
566 // new external storage
567 T* pNewElements = PL_NEW_RAW_BUFFER(pAllocator, T, uiCapacity);
568 plMemoryUtils::RelocateConstruct(pNewElements, pOldElements, m_uiCount);
569 m_pElements = pNewElements;
570 }
571 else
572 {
573 // Re-use inplace storage
574 plMemoryUtils::RelocateConstruct(GetElementsPtr(), pOldElements, m_uiCount);
575 }
576
577 if (uiOldCapacity > Size)
578 {
579 PL_DELETE_RAW_BUFFER(pAllocator, pOldElements);
580 }
581 }
582}
583
584template <typename T, plUInt16 Size>
586{
587 return m_uiCapacity <= Size ? reinterpret_cast<T*>(m_StaticData) : m_pElements;
588}
589
590template <typename T, plUInt16 Size>
591PL_ALWAYS_INLINE const T* plSmallArrayBase<T, Size>::GetElementsPtr() const
592{
593 return m_uiCapacity <= Size ? reinterpret_cast<const T*>(m_StaticData) : m_pElements;
594}
595
597
598template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
600
601template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
603 : SUPER(other, AllocatorWrapper::GetAllocator())
604{
605}
606
607template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
609 : SUPER(other, AllocatorWrapper::GetAllocator())
610{
611}
612
613template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
615 : SUPER(static_cast<SUPER&&>(other), AllocatorWrapper::GetAllocator())
616{
617}
618
619template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
621{
622 SUPER::Clear();
623 SUPER::Compact(AllocatorWrapper::GetAllocator());
624}
625
626template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
628{
629 *this = ((plArrayPtr<const T>)rhs); // redirect this to the plArrayPtr version
630 this->m_uiUserData = rhs.m_uiUserData;
631}
632
633template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
635{
636 SUPER::CopyFrom(rhs, AllocatorWrapper::GetAllocator());
637}
638
639template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
641{
642 SUPER::MoveFrom(std::move(rhs), AllocatorWrapper::GetAllocator());
643}
644
645template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
646PL_ALWAYS_INLINE void plSmallArray<T, Size, AllocatorWrapper>::SetCount(plUInt16 uiCount)
647{
648 SUPER::SetCount(uiCount, AllocatorWrapper::GetAllocator());
649}
650
651template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
652PL_ALWAYS_INLINE void plSmallArray<T, Size, AllocatorWrapper>::SetCount(plUInt16 uiCount, const T& fillValue)
653{
654 SUPER::SetCount(uiCount, fillValue, AllocatorWrapper::GetAllocator());
655}
656
657template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
658PL_ALWAYS_INLINE void plSmallArray<T, Size, AllocatorWrapper>::EnsureCount(plUInt16 uiCount)
659{
660 SUPER::EnsureCount(uiCount, AllocatorWrapper::GetAllocator());
661}
662
663template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
664template <typename> // Second template needed so that the compiler does only instantiate it when called. Otherwise the static_assert would trigger early.
665PL_ALWAYS_INLINE void plSmallArray<T, Size, AllocatorWrapper>::SetCountUninitialized(plUInt16 uiCount)
666{
667 SUPER::SetCountUninitialized(uiCount, AllocatorWrapper::GetAllocator());
668}
669
670template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
671PL_ALWAYS_INLINE void plSmallArray<T, Size, AllocatorWrapper>::InsertAt(plUInt32 uiIndex, const T& value)
672{
673 SUPER::Insert(value, uiIndex, AllocatorWrapper::GetAllocator());
674}
675
676template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
677PL_ALWAYS_INLINE void plSmallArray<T, Size, AllocatorWrapper>::InsertAt(plUInt32 uiIndex, T&& value)
678{
679 SUPER::Insert(value, uiIndex, AllocatorWrapper::GetAllocator());
680}
681
682template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
684{
685 return SUPER::ExpandAndGetRef(AllocatorWrapper::GetAllocator());
686}
687
688template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
689PL_ALWAYS_INLINE void plSmallArray<T, Size, AllocatorWrapper>::PushBack(const T& value)
690{
691 SUPER::PushBack(value, AllocatorWrapper::GetAllocator());
692}
693
694template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
695PL_ALWAYS_INLINE void plSmallArray<T, Size, AllocatorWrapper>::PushBack(T&& value)
696{
697 SUPER::PushBack(std::move(value), AllocatorWrapper::GetAllocator());
698}
699
700template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
702{
703 SUPER::PushBackRange(range, AllocatorWrapper::GetAllocator());
704}
705
706template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
707PL_ALWAYS_INLINE void plSmallArray<T, Size, AllocatorWrapper>::Reserve(plUInt16 uiCapacity)
708{
709 SUPER::Reserve(uiCapacity, AllocatorWrapper::GetAllocator());
710}
711
712template <typename T, plUInt16 Size, typename AllocatorWrapper /*= plDefaultAllocatorWrapper*/>
714{
715 SUPER::Compact(AllocatorWrapper::GetAllocator());
716}
717
719
720template <typename T, plUInt16 Size>
721typename plSmallArrayBase<T, Size>::iterator begin(plSmallArrayBase<T, Size>& ref_container)
722{
723 return ref_container.GetData();
724}
725
726template <typename T, plUInt16 Size>
727typename plSmallArrayBase<T, Size>::const_iterator begin(const plSmallArrayBase<T, Size>& container)
728{
729 return container.GetData();
730}
731
732template <typename T, plUInt16 Size>
733typename plSmallArrayBase<T, Size>::const_iterator cbegin(const plSmallArrayBase<T, Size>& container)
734{
735 return container.GetData();
736}
737
738template <typename T, plUInt16 Size>
740{
741 return typename plSmallArrayBase<T, Size>::reverse_iterator(ref_container.GetData() + ref_container.GetCount() - 1);
742}
743
744template <typename T, plUInt16 Size>
746{
747 return typename plSmallArrayBase<T, Size>::const_reverse_iterator(container.GetData() + container.GetCount() - 1);
748}
749
750template <typename T, plUInt16 Size>
752{
753 return typename plSmallArrayBase<T, Size>::const_reverse_iterator(container.GetData() + container.GetCount() - 1);
754}
755
756template <typename T, plUInt16 Size>
757typename plSmallArrayBase<T, Size>::iterator end(plSmallArrayBase<T, Size>& ref_container)
758{
759 return ref_container.GetData() + ref_container.GetCount();
760}
761
762template <typename T, plUInt16 Size>
763typename plSmallArrayBase<T, Size>::const_iterator end(const plSmallArrayBase<T, Size>& container)
764{
765 return container.GetData() + container.GetCount();
766}
767
768template <typename T, plUInt16 Size>
769typename plSmallArrayBase<T, Size>::const_iterator cend(const plSmallArrayBase<T, Size>& container)
770{
771 return container.GetData() + container.GetCount();
772}
773
774template <typename T, plUInt16 Size>
776{
777 return typename plSmallArrayBase<T, Size>::reverse_iterator(ref_container.GetData() - 1);
778}
779
780template <typename T, plUInt16 Size>
782{
783 return typename plSmallArrayBase<T, Size>::const_reverse_iterator(container.GetData() - 1);
784}
785
786template <typename T, plUInt16 Size>
788{
789 return typename plSmallArrayBase<T, Size>::const_reverse_iterator(container.GetData() - 1);
790}
Base class for all memory allocators.
Definition Allocator.h:23
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 RelocateConstruct(T *pDestination, T *pSource, size_t uiCount=1)
Constructs uiCount objects of type T in a raw buffer at pDestination from an existing array of object...
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 T AlignSize(T uiSize, T uiAlignment)
Aligns the given size uiSize by rounding up to the next multiple of the size.
static void Destruct(T *pDestination, size_t uiCount=1)
Destructs uiCount objects of type T at pDestination.
Implementation of a dynamically growing array with in-place storage and small memory overhead.
Definition SmallArray.h:17
void PopBack(plUInt32 uiCountToRemove=1)
Removes count elements from the end of the array.
Definition SmallArray_inl.h:400
void PushBackRange(const plArrayPtr< const T > &range, plAllocator *pAllocator)
Pushes all elements in range at the end of the array. Increases the capacity if necessary.
Definition SmallArray_inl.h:390
void Clear()
Clears the array.
Definition SmallArray_inl.h:222
void SetCount(plUInt16 uiCount, plAllocator *pAllocator)
Resizes the array to have exactly uiCount elements. Default constructs extra elements if the array is...
Definition SmallArray_inl.h:142
void RemoveAtAndSwap(plUInt32 uiIndex, plUInt16 uiNumElements=1)
Removes the element at index and fills the gap by swapping in the last element.
Definition SmallArray_inl.h:292
void MoveFrom(plSmallArrayBase< T, Size > &&other, plAllocator *pAllocator)
Moves the data from some other array into this one.
Definition SmallArray_inl.h:69
void SetCountUninitialized(plUInt16 uiCount, plAllocator *pAllocator)
Resizes the array to have exactly uiCount elements. Extra elements might be uninitialized.
Definition SmallArray_inl.h:190
void Sort()
Sort with default comparer.
Definition SmallArray_inl.h:434
void Compact(plAllocator *pAllocator)
Tries to compact the array to avoid wasting memory. The resulting capacity is at least 'GetCount' (no...
Definition SmallArray_inl.h:502
void Reserve(plUInt16 uiCapacity, plAllocator *pAllocator)
Expands the array so it can at least store the given capacity.
Definition SmallArray_inl.h:486
void Insert(const T &value, plUInt32 uiIndex, plAllocator *pAllocator)
Inserts value at index by shifting all following elements.
Definition SmallArray_inl.h:235
void CopyFrom(const plArrayPtr< const T > &other, plAllocator *pAllocator)
Copies the data from some other array into this one.
Definition SmallArray_inl.h:32
bool RemoveAndCopy(const T &value)
Removes the first occurrence of value and fills the gap by shifting all following elements.
Definition SmallArray_inl.h:257
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 SmallArray_inl.h:474
void EnsureCount(plUInt16 uiCount, plAllocator *pAllocator)
Ensures the container has at least uiCount elements. Ie. calls SetCount() if the container has fewer ...
Definition SmallArray_inl.h:180
T * GetData()
Returns a pointer to the array data, or nullptr if the array is empty.
Definition SmallArray_inl.h:444
plUInt64 GetHeapMemoryUsage() const
Returns the amount of bytes that are currently allocated on the heap.
Definition SmallArray_inl.h:526
T & PeekBack()
Returns the last element of the array.
Definition SmallArray_inl.h:409
T & ExpandAndGetRef(plAllocator *pAllocator)
Grows the array by one element and returns a reference to the newly created element.
Definition SmallArray_inl.h:338
plUInt32 LastIndexOf(const T &value, plUInt32 uiStartIndex=plSmallInvalidIndex) const
Searches for the last occurrence of the given value and returns its index or plInvalidIndex if not fo...
Definition SmallArray_inl.h:325
plArrayPtr< T > GetArrayPtr()
Returns an array pointer to the array data, or an empty array pointer if the array is empty.
Definition SmallArray_inl.h:462
plUInt32 GetCount() const
Returns the number of active elements in the array.
Definition SmallArray_inl.h:210
const T & operator[](plUInt32 uiIndex) const
Returns the element at the given index. Does bounds checks in debug builds.
Definition SmallArray_inl.h:128
void RemoveAtAndCopy(plUInt32 uiIndex, plUInt16 uiNumElements=1)
Removes the element at index and fills the gap by shifting all following elements.
Definition SmallArray_inl.h:281
void PushBackUnchecked(const T &value)
Pushes value at the end of the array. Does NOT ensure capacity.
Definition SmallArray_inl.h:372
bool IsEmpty() const
Returns true, if the array does not contain any elements.
Definition SmallArray_inl.h:216
void PushBack(const T &value, plAllocator *pAllocator)
Pushes value at the end of the array.
Definition SmallArray_inl.h:354
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 SmallArray_inl.h:312
bool operator==(const plSmallArrayBase< T, Size > &rhs) const
Compares this array to another contiguous array type.
Definition SmallArray_inl.h:111
bool RemoveAndSwap(const T &value)
Removes the first occurrence of value and fills the gap by swapping in the last element.
Definition SmallArray_inl.h:269
bool Contains(const T &value) const
Checks whether the given value can be found in the array. O(n) complexity.
Definition SmallArray_inl.h:229
Definition SmallArray.h:219
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
constexpr PL_ALWAYS_INLINE T Max(T f1, T f2)
Returns the greater value, f1 or f2.
Definition Math_inl.h:39
Base class for Pointer like reverse iterators.
Definition ArrayIterator.h:152
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
Non-Const class for Pointer like reverse iterators.
Definition ArrayIterator.h:216