Nebula
Loading...
Searching...
No Matches
array.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
34#include "core/types.h"
35#include "system/systeminfo.h"
36#include "math/scalar.h"
37#include <type_traits>
38#include <new>
39
40
41
42//------------------------------------------------------------------------------
43namespace Util
44{
45
46template<class TYPE, int STACK_SIZE>
48{
49 TYPE* data() { return stackElements; }
50private:
51 TYPE stackElements[STACK_SIZE];
52};
53
54template<class TYPE>
55struct _smallvector<TYPE, 0>
56{
57 TYPE* data() { return nullptr; }
58};
59
60template<class TYPE, int SMALL_VECTOR_SIZE = 0> class Array
61{
62public:
64 typedef TYPE* Iterator;
65 typedef const TYPE* ConstIterator;
66
68
72 Array(SizeT initialCapacity, SizeT initialGrow);
74 Array(SizeT initialSize, SizeT initialGrow, const TYPE& initialValue);
76 Array(const ArrayT& rhs);
78 Array(ArrayT&& rhs) noexcept;
80 Array(std::initializer_list<TYPE> list);
82 Array(std::nullptr_t);
84 Array(const TYPE* const buf, SizeT num);
87
93 TYPE& operator[](IndexT index) const;
95 TYPE& operator[](IndexT index);
101 template<typename T> T As() const;
102
104 TYPE& Get(IndexT index) const;
105
107 template <typename ...ELEM_TYPE>
108 void Append(const TYPE& first, const ELEM_TYPE&... elements);
110 void Append(const TYPE& elm);
112 void Append(TYPE&& elm);
116 void AppendArray(const TYPE* arr, const SizeT count);
118 TYPE& Emplace();
122 void Reserve(SizeT num);
123
125 const SizeT Size() const;
127 const SizeT ByteSize() const;
129 const SizeT Capacity() const;
131 TYPE& Front() const;
133 TYPE& Back() const;
135 bool IsEmpty() const;
137 bool IsValidIndex(IndexT index) const;
139 void EraseIndex(IndexT index);
149 void EraseBack();
153 TYPE PopFront();
155 TYPE PopBack();
157 void Insert(IndexT index, const TYPE& elm);
159 void Insert(IndexT index, TYPE&& elm);
161 IndexT InsertSorted(const TYPE& elm);
163 IndexT InsertSorted(TYPE&& elm);
165 IndexT InsertAtEndOfIdenticalRange(IndexT startIndex, const TYPE& elm);
169 bool IsSorted() const;
171 void Clear();
173 void Reset();
175 void Free();
181 Iterator End() const;
185 Iterator Find(const TYPE& elm, const IndexT start = 0) const;
187 IndexT FindIndex(const TYPE& elm, const IndexT start = 0) const;
189 template <typename KEYTYPE> IndexT FindIndex(typename std::enable_if<true, const KEYTYPE&>::type elm, const IndexT start = 0) const;
191 void Fill(IndexT first, SizeT num, const TYPE& elm);
197 void Sort();
199 void QuickSort();
201 void SortWithFunc(bool (*func)(const TYPE& lhs, const TYPE& rhs));
203 void QuickSortWithFunc(int (*func)(const void* lhs, const void* rhs));
205 IndexT BinarySearchIndex(const TYPE& elm) const;
207 template <typename KEYTYPE> IndexT BinarySearchIndex(typename std::enable_if<true, const KEYTYPE&>::type elm) const;
208
210 void Resize(SizeT num);
212 template <typename ...ARGS> void Resize(SizeT num, ARGS... args);
214 void Extend(SizeT num);
216 void Fit();
217
219 constexpr SizeT TypeSize() const;
220
223 Iterator end() const;
224 size_t size() const;
225 void resize(size_t size);
226 void clear() noexcept;
227 void push_back(const TYPE& item);
228
230 void Grow();
231protected:
232 template<typename ELEM>
233 void InsertInternal(IndexT index, ELEM&& elm);
234 template<typename ELEM>
236 template<typename ELEM>
238
239 template<class T, bool S>
240 friend class FixedArray;
241
243 void Destroy(TYPE* elm);
245 void Reset(TYPE* elm);
247 void Copy(const Array<TYPE, SMALL_VECTOR_SIZE>& src);
249 void Delete();
251 void GrowTo(SizeT newCapacity);
253 void Move(IndexT fromIndex, IndexT toIndex);
255 void DestroyRange(IndexT fromIndex, IndexT toIndex);
257 void CopyRange(TYPE* to, TYPE* from, SizeT num);
259 void MoveRange(TYPE* to, TYPE* from, SizeT num);
260
261 static const SizeT MinGrowSize = 16;
262 static const SizeT MaxGrowSize = 65536; // FIXME: big grow size needed for mesh tools
263 SizeT grow; // grow by this number of elements if array exhausted
264 SizeT capacity; // number of elements allocated
265 SizeT count; // number of elements in array
266 TYPE* elements; // pointer to element array
267
268 _smallvector<TYPE, SMALL_VECTOR_SIZE> stackElements;
269};
270
271//------------------------------------------------------------------------------
274template<class TYPE, int SMALL_VECTOR_SIZE>
275Array<TYPE, SMALL_VECTOR_SIZE>::Array() :
276 grow(16),
277 capacity(SMALL_VECTOR_SIZE),
278 count(0),
279 elements(this->stackElements.data())
280{
281}
282
283//------------------------------------------------------------------------------
286template<class TYPE, int SMALL_VECTOR_SIZE>
288 grow(_grow),
289 capacity(SMALL_VECTOR_SIZE),
290 count(0),
291 elements(this->stackElements.data())
292{
293 if (0 == this->grow)
294 {
295 this->grow = 16;
296 }
297 this->GrowTo(_capacity);
298}
299
300//------------------------------------------------------------------------------
303template<class TYPE, int SMALL_VECTOR_SIZE>
304Array<TYPE, SMALL_VECTOR_SIZE>::Array(SizeT initialSize, SizeT _grow, const TYPE& initialValue) :
305 grow(_grow),
306 capacity(SMALL_VECTOR_SIZE),
307 count(0),
308 elements(stackElements.data())
309{
310 if (0 == this->grow)
311 {
312 this->grow = 16;
313 }
314
315 this->GrowTo(initialSize);
316 this->count = initialSize;
317 IndexT i;
318 for (i = 0; i < initialSize; i++)
319 {
320 this->elements[i] = initialValue;
321 }
322}
323
324//------------------------------------------------------------------------------
327template<class TYPE, int SMALL_VECTOR_SIZE>
328Array<TYPE, SMALL_VECTOR_SIZE>::Array(const TYPE* const buf, SizeT num) :
329 grow(16),
330 capacity(SMALL_VECTOR_SIZE),
331 count(0),
332 elements(stackElements.data())
333{
334 static_assert(std::is_trivially_copyable<TYPE>::value, "TYPE is not trivially copyable; Util::Array cannot be constructed from pointer of TYPE.");
335 this->GrowTo(num);
336 this->count = num;
337 const SizeT bytes = num * sizeof(TYPE);
338 Memory::Copy(buf, this->elements, bytes);
339}
340
341//------------------------------------------------------------------------------
344template<class TYPE, int SMALL_VECTOR_SIZE>
345Array<TYPE, SMALL_VECTOR_SIZE>::Array(std::initializer_list<TYPE> list) :
346 grow(16),
347 capacity(SMALL_VECTOR_SIZE),
348 count(0),
349 elements(stackElements.data())
350{
351 this->GrowTo((SizeT)list.size());
352 this->count = (SizeT)list.size();
353 IndexT i;
354 for (i = 0; i < this->count; i++)
355 {
356 this->elements[i] = list.begin()[i];
357 }
358}
359
360//------------------------------------------------------------------------------
363template<class TYPE, int SMALL_VECTOR_SIZE>
365 grow(16),
366 capacity(SMALL_VECTOR_SIZE),
367 count(0),
368 elements(stackElements.data())
369{
370}
371
372//------------------------------------------------------------------------------
375template<class TYPE, int SMALL_VECTOR_SIZE>
377 grow(16),
378 capacity(SMALL_VECTOR_SIZE),
379 count(0),
380 elements(this->stackElements.data())
381{
382 this->Copy(rhs);
383}
384
385//------------------------------------------------------------------------------
388template<class TYPE, int SMALL_VECTOR_SIZE>
390 grow(rhs.grow),
391 capacity(rhs.capacity),
392 count(rhs.count),
393 elements(this->stackElements.data())
394{
395 // If data is on the stack, copy data over
396 if (rhs.capacity <= SMALL_VECTOR_SIZE)
397 {
398 for (IndexT i = 0; i < rhs.count; i++)
399 {
400 this->elements[i] = std::move(rhs.elements[i]);
401 }
402 }
403 else
404 {
405 // Otherwise, exchange pointers and invalidate
406 this->elements = rhs.elements;
407 rhs.elements = rhs.stackElements.data();
408 }
409 rhs.count = 0;
410 rhs.capacity = SMALL_VECTOR_SIZE;
411}
412
413//------------------------------------------------------------------------------
416template<class TYPE, int SMALL_VECTOR_SIZE>
417void
419{
420 #if NEBULA_BOUNDSCHECKS
421 // Make sure array is either empty, or stack array before copy
422 n_assert(this->stackElements.data() == this->elements);
423 #endif
424
425 this->GrowTo(src.capacity);
426 this->grow = src.grow;
427 this->count = src.count;
428 IndexT i;
429 for (i = 0; i < this->count; i++)
430 {
431 this->elements[i] = src.elements[i];
432 }
433}
434
435//------------------------------------------------------------------------------
438template<class TYPE, int SMALL_VECTOR_SIZE>
439void
441{
442 this->grow = 16;
443
444 if (this->capacity > 0)
445 {
446 if (this->elements != this->stackElements.data())
447 {
448 ArrayFree(this->capacity, this->elements);
449 }
450 else
451 {
452 // If in small vector, run destructor
453 this->DestroyRange(0, this->count);
454 }
455 }
456 this->elements = this->stackElements.data();
457 this->count = 0;
458 this->capacity = SMALL_VECTOR_SIZE;
459}
460
461//------------------------------------------------------------------------------
464template<class TYPE, int SMALL_VECTOR_SIZE> void
466{
467 elm->~TYPE();
468}
469
470//------------------------------------------------------------------------------
473template<class TYPE, int SMALL_VECTOR_SIZE> void
475{
476 if constexpr (!std::is_trivially_destructible<TYPE>::value)
477 {
478 this->Destroy(elm);
479 ::new ((void*)elm) TYPE();
480 }
481}
482
483//------------------------------------------------------------------------------
486template<class TYPE, int SMALL_VECTOR_SIZE>
491
492//------------------------------------------------------------------------------
495template<class TYPE, int SMALL_VECTOR_SIZE> void
497{
498 this->Delete();
499 this->grow = _grow;
500 this->capacity = _capacity;
501 this->count = _capacity;
502 if (this->capacity > 0)
503 {
504 this->GrowTo(this->capacity);
505 }
506 else
507 {
508 this->elements = 0;
509 }
510}
511
512//------------------------------------------------------------------------------
515template<class TYPE, int SMALL_VECTOR_SIZE> void
517{
518 if (this != &rhs)
519 {
520 if ((this->capacity > 0) && (rhs.count <= this->capacity))
521 {
522 // source array fits into our capacity, copy in place
523 n_assert(0 != this->elements);
524
525 this->CopyRange(this->elements, rhs.elements, rhs.count);
526 if (rhs.count < this->count)
527 {
528 this->DestroyRange(rhs.count, this->count);
529 }
530 this->grow = rhs.grow;
531 this->count = rhs.count;
532 }
533 else
534 {
535 // source array doesn't fit into our capacity, need to reallocate
536 this->Delete();
537 this->Copy(rhs);
538 }
539 }
540}
541
542//------------------------------------------------------------------------------
545template<class TYPE, int SMALL_VECTOR_SIZE> void
547{
548 if (this != &rhs)
549 {
550 this->Delete();
551
552 // If rhs is not using stack, simply reassign pointers
553 if (rhs.elements != rhs.stackElements.data())
554 {
555 this->elements = rhs.elements;
556 rhs.elements = nullptr;
557 }
558 else
559 {
560 // Otherwise, move every element over to the stack of this array
561 this->MoveRange(this->elements, rhs.elements, rhs.count);
562 }
563
564 this->grow = rhs.grow;
565 this->count = rhs.count;
566 this->capacity = rhs.capacity;
567 rhs.elements = rhs.stackElements.data();
568 rhs.count = 0;
569 rhs.capacity = SMALL_VECTOR_SIZE;
570 }
571}
572
573//------------------------------------------------------------------------------
576template<class TYPE, int SMALL_VECTOR_SIZE> void
578{
579 if (newCapacity > SMALL_VECTOR_SIZE)
580 {
581 TYPE* newArray = ArrayAlloc<TYPE>(newCapacity);
582 if (this->elements)
583 {
584 this->MoveRange(newArray, this->elements, this->count);
585
586 // discard old array if not the stack array
587 if (this->elements != this->stackElements.data())
588 ArrayFree(this->capacity, this->elements);
589 }
590 this->elements = newArray;
591 this->capacity = newCapacity;
592 }
593}
594
595//------------------------------------------------------------------------------
598template<class TYPE, int SMALL_VECTOR_SIZE>
599void
601{
602 #if NEBULA_BOUNDSCHECKS
603 n_assert(this->grow > 0);
604 #endif
605
606 SizeT growToSize;
607 if (0 == this->capacity)
608 {
609 growToSize = this->grow;
610 }
611 else
612 {
613 // grow by half of the current capacity, but never more then MaxGrowSize
614 SizeT growBy = this->capacity >> 1;
615 if (growBy == 0)
616 {
617 growBy = MinGrowSize;
618 }
619 else if (growBy > MaxGrowSize)
620 {
621 growBy = MaxGrowSize;
622 }
623 growToSize = this->capacity + growBy;
624 }
625 this->GrowTo(growToSize);
626}
627
628//------------------------------------------------------------------------------
633template<class TYPE, int SMALL_VECTOR_SIZE>
634void
636{
637 #if NEBULA_BOUNDSCHECKS
638 n_assert(this->elements);
639 n_assert(fromIndex < this->count);
640 #endif
641
642 // nothing to move?
643 if (fromIndex == toIndex)
644 {
645 return;
646 }
647
648 // compute number of elements to move
649 SizeT num = this->count - fromIndex;
650
651 // check if array needs to grow
652 SizeT neededSize = toIndex + num;
653 while (neededSize > this->capacity)
654 {
655 this->Grow();
656 }
657
658 if (fromIndex > toIndex)
659 {
660 // this is a backward move
661 this->MoveRange(&this->elements[toIndex], &this->elements[fromIndex], num);
662 this->DestroyRange(toIndex + num, this->count);
663 }
664 else
665 {
666 // this is a forward move
667 int i; // NOTE: this must remain signed for the following loop to work!!!
668 for (i = num - 1; i >= 0; --i)
669 {
670 this->elements[toIndex + i] = this->elements[fromIndex + i];
671 }
672
673 // destroy freed elements
674 this->DestroyRange(fromIndex, toIndex);
675 }
676
677 // adjust array size
678 this->count = toIndex + num;
679}
680
681//------------------------------------------------------------------------------
684template<class TYPE, int SMALL_VECTOR_SIZE>
685inline void
687{
688 if constexpr (!std::is_trivially_destructible<TYPE>::value)
689 {
690 for (IndexT i = fromIndex; i < toIndex; i++)
691 {
692 this->Reset(&(this->elements[i]));
693 }
694 }
695 else
696 {
697 Memory::Clear((void*)&this->elements[fromIndex], sizeof(TYPE) * (toIndex - fromIndex));
698 }
699}
700
701//------------------------------------------------------------------------------
704template<class TYPE, int SMALL_VECTOR_SIZE>
705inline void
707{
708 // this is a backward move
709 if constexpr (!std::is_trivially_copyable<TYPE>::value)
710 {
711 IndexT i;
712 for (i = 0; i < num; i++)
713 {
714 to[i] = from[i];
715 }
716 }
717 else
718 {
719 Memory::CopyElements(from, to, num);
720 }
721}
722
723//------------------------------------------------------------------------------
726template<class TYPE, int SMALL_VECTOR_SIZE>
727inline void
729{
730 // Use bitwise moves only for trivially copyable types.
731 // For non-trivial types, move-assign element-wise.
732 if constexpr (std::is_trivially_copyable<TYPE>::value)
733 {
734 Memory::MoveElements(from, to, num);
735 }
736 else
737 {
738 IndexT i;
739 for (i = 0; i < num; i++)
740 {
741 to[i] = std::move(from[i]);
742 }
743 }
744}
745
746//------------------------------------------------------------------------------
749template<class TYPE, int SMALL_VECTOR_SIZE>
750inline TYPE&
752{
753#if NEBULA_BOUNDSCHECKS
754 n_assert(this->elements != nullptr);
755 n_assert(this->count > index);
756#endif
757 return this->elements[index];
758}
759
760//------------------------------------------------------------------------------
763template<class TYPE, int SMALL_VECTOR_SIZE>
764void
766{
767 // grow allocated space if exhausted
768 if (this->count == this->capacity)
769 {
770 this->Grow();
771 }
772 #if NEBULA_BOUNDSCHECKS
773 n_assert(this->elements);
774 #endif
775 this->elements[this->count++] = elm;
776}
777
778//------------------------------------------------------------------------------
781template<class TYPE, int SMALL_VECTOR_SIZE>
782void
784{
785 // grow allocated space if exhausted
786 if (this->count == this->capacity)
787 {
788 this->Grow();
789 }
790#if NEBULA_BOUNDSCHECKS
791 n_assert(this->elements);
792#endif
793 this->elements[this->count++] = std::move(elm);
794}
795
796//------------------------------------------------------------------------------
799template<class TYPE, int SMALL_VECTOR_SIZE>
800void
802{
803 SizeT neededCapacity = this->count + rhs.count;
804 if (neededCapacity > this->capacity)
805 {
806 this->GrowTo(neededCapacity);
807 }
808
809 // forward elements from array
810 IndexT i;
811 for (i = 0; i < rhs.count; i++)
812 {
813 this->elements[this->count + i] = rhs.elements[i];
814 }
815 this->count += rhs.count;
816}
817
818//------------------------------------------------------------------------------
821template<class TYPE, int SMALL_VECTOR_SIZE>
822void
824{
825 SizeT neededCapacity = this->count + count;
826 if (neededCapacity > this->capacity)
827 {
828 this->GrowTo(neededCapacity);
829 }
830
831 // forward elements from array
832 IndexT i;
833 for (i = 0; i < count; i++)
834 {
835 this->elements[this->count + i] = arr[i];
836 }
837 this->count += count;
838}
839
840//------------------------------------------------------------------------------
843template<class TYPE, int SMALL_VECTOR_SIZE>
844TYPE&
846{
847 // grow allocated space if exhausted
848 if (this->count == this->capacity)
849 {
850 this->Grow();
851 }
852#if NEBULA_BOUNDSCHECKS
853 n_assert(this->elements);
854#endif
855 this->elements[this->count] = TYPE();
856 return this->elements[this->count++];
857}
858
859//------------------------------------------------------------------------------
862template<class TYPE, int SMALL_VECTOR_SIZE>
863TYPE*
865{
866 SizeT neededCapacity = this->count + count;
867 if (neededCapacity > this->capacity)
868 {
869 this->GrowTo(neededCapacity);
870 }
871
872 // forward elements from array
873 IndexT i;
874 for (i = 0; i < count; i++)
875 {
876 this->elements[this->count + i] = TYPE();
877 }
878 TYPE* first = &this->elements[this->count];
879 this->count += count;
880 return first;
881}
882
883//------------------------------------------------------------------------------
893template<class TYPE, int SMALL_VECTOR_SIZE>
894void
896{
897#if NEBULA_BOUNDSCHECKS
898 n_assert(num >= 0);
899#endif
900
901 SizeT neededCapacity = this->count + num;
902 if (neededCapacity > this->capacity)
903 {
904 this->GrowTo(neededCapacity);
905 }
906}
907
908//------------------------------------------------------------------------------
911template<class TYPE, int SMALL_VECTOR_SIZE>
912const SizeT
914{
915 return this->count;
916}
917
918//------------------------------------------------------------------------------
921template<class TYPE, int SMALL_VECTOR_SIZE>
922const SizeT
924{
925 return this->count * sizeof(TYPE);
926}
927
928//------------------------------------------------------------------------------
931template<class TYPE, int SMALL_VECTOR_SIZE>
932const SizeT
934{
935 return this->capacity;
936}
937
938//------------------------------------------------------------------------------
943template<class TYPE, int SMALL_VECTOR_SIZE>
944TYPE&
946{
947 #if NEBULA_BOUNDSCHECKS
948 n_assert(this->elements && (index < this->count) && (index >= 0));
949 #endif
950 return this->elements[index];
951}
952
953//------------------------------------------------------------------------------
958template<class TYPE, int SMALL_VECTOR_SIZE>
959TYPE&
961{
962#if NEBULA_BOUNDSCHECKS
963 n_assert(this->elements && (index < this->count) && (index >= 0));
964#endif
965 return this->elements[index];
966}
967
968//------------------------------------------------------------------------------
973template<class TYPE, int SMALL_VECTOR_SIZE>
974bool
976{
977 if (rhs.Size() == this->Size())
978 {
979 IndexT i;
980 SizeT num = this->Size();
981 for (i = 0; i < num; i++)
982 {
983 if (!(this->elements[i] == rhs.elements[i]))
984 {
985 return false;
986 }
987 }
988 return true;
989 }
990 else
991 {
992 return false;
993 }
994}
995
996//------------------------------------------------------------------------------
1001template<class TYPE, int SMALL_VECTOR_SIZE>
1002bool
1004{
1005 return !(*this == rhs);
1006}
1007
1008//------------------------------------------------------------------------------
1011template<class TYPE, int SMALL_VECTOR_SIZE>
1012TYPE&
1014{
1015 #if NEBULA_BOUNDSCHECKS
1016 n_assert(this->elements && (this->count > 0));
1017 #endif
1018 return this->elements[0];
1019}
1020
1021//------------------------------------------------------------------------------
1024template<class TYPE, int SMALL_VECTOR_SIZE>
1025TYPE&
1027{
1028 #if NEBULA_BOUNDSCHECKS
1029 n_assert(this->elements && (this->count > 0));
1030 #endif
1031 return this->elements[this->count - 1];
1032}
1033
1034//------------------------------------------------------------------------------
1037template<class TYPE, int SMALL_VECTOR_SIZE>
1038void
1040{
1041 this->Append(item);
1042}
1043
1044//------------------------------------------------------------------------------
1047template<class TYPE, int SMALL_VECTOR_SIZE>
1048bool
1050{
1051 return (this->count == 0);
1052}
1053
1054//------------------------------------------------------------------------------
1057template<class TYPE, int SMALL_VECTOR_SIZE>
1058bool
1060{
1061 return this->elements && (index < this->count) && (index >= 0);
1062}
1063
1064//------------------------------------------------------------------------------
1067template<class TYPE, int SMALL_VECTOR_SIZE>
1068void
1070{
1071 #if NEBULA_BOUNDSCHECKS
1072 n_assert(this->elements && (index < this->count) && (index >= 0));
1073 #endif
1074 if (index == (this->count - 1))
1075 {
1076 // special case: last element
1077 this->EraseBack();
1078 }
1079 else
1080 {
1081 this->Move(index + 1, index);
1082 }
1083}
1084
1085//------------------------------------------------------------------------------
1089template<class TYPE, int SMALL_VECTOR_SIZE>
1090void
1092{
1093 #if NEBULA_BOUNDSCHECKS
1094 n_assert(this->elements && (index < this->count) && (index >= 0));
1095 #endif
1096
1097 // swap with last element, and destroy last element
1098 IndexT lastElementIndex = this->count - 1;
1099 if (index < lastElementIndex)
1100 {
1101 this->elements[index] = std::move(this->elements[lastElementIndex]);
1102 this->Reset(&this->elements[lastElementIndex]);
1103 }
1104 else
1105 {
1106 this->Reset(&this->elements[index]);
1107 }
1108 this->count--;
1109}
1110
1111//------------------------------------------------------------------------------
1114template<class TYPE, int SMALL_VECTOR_SIZE>
1117{
1118 #if NEBULA_BOUNDSCHECKS
1119 n_assert(this->elements && (iter >= this->elements) && (iter < (this->elements + this->count)));
1120 #endif
1121 this->EraseIndex(IndexT(iter - this->elements));
1122 return iter;
1123}
1124
1125//------------------------------------------------------------------------------
1129template<class TYPE, int SMALL_VECTOR_SIZE>
1132{
1133 #if NEBULA_BOUNDSCHECKS
1134 n_assert(this->elements && (iter >= this->elements) && (iter < (this->elements + this->count)));
1135 #endif
1136 this->EraseIndexSwap(IndexT(iter - this->elements));
1137 return iter;
1138}
1139
1140//------------------------------------------------------------------------------
1143template<class TYPE, int SMALL_VECTOR_SIZE>
1144void
1146{
1147 n_assert(end >= start);
1148 n_assert(end <= this->count);
1149 if (start == end)
1150 this->EraseIndex(start);
1151 else
1152 {
1153 // add 1 to end to remove and move including that element
1154 this->DestroyRange(start, end);
1155 SizeT numMove = this->count - end;
1156 this->MoveRange(&this->elements[start], &this->elements[end], numMove);
1157 this->count -= end - start;
1158 }
1159}
1160
1161//------------------------------------------------------------------------------
1164template<class TYPE, int SMALL_VECTOR_SIZE>
1165void
1167{
1168 n_assert(this->count > 0);
1169 this->Reset(&(this->elements[this->count - 1]));
1170 this->count--;
1171}
1172
1173//------------------------------------------------------------------------------
1176template<class TYPE, int SMALL_VECTOR_SIZE>
1177void
1182
1183//------------------------------------------------------------------------------
1186template<class TYPE, int SMALL_VECTOR_SIZE>
1187inline TYPE
1189{
1190#if NEBULA_BOUNDSCHECKS
1191 n_assert(this->count > 0);
1192#endif
1193 TYPE ret = std::move(this->elements[0]);
1194 this->EraseIndex(0);
1195 return ret;
1196}
1197
1198//------------------------------------------------------------------------------
1201template<class TYPE, int SMALL_VECTOR_SIZE>
1202inline TYPE
1204{
1205#if NEBULA_BOUNDSCHECKS
1206 n_assert(this->count > 0);
1207#endif
1208 IndexT index = this->count - 1;
1209 TYPE ret = std::move(this->elements[index]);
1210 this->Reset(&(this->elements[index]));
1211 this->count = index;
1212 return ret;
1213}
1214
1215//------------------------------------------------------------------------------
1218template<class TYPE, int SMALL_VECTOR_SIZE>
1219void
1221{
1222 this->InsertInternal(index, elm);
1223}
1224
1225//------------------------------------------------------------------------------
1228template<class TYPE, int SMALL_VECTOR_SIZE>
1229void
1231{
1232 this->InsertInternal(index, std::move(elm));
1233}
1234
1235//------------------------------------------------------------------------------
1238template<class TYPE, int SMALL_VECTOR_SIZE>
1239template<typename ELEM>
1240void
1242{
1243 #if NEBULA_BOUNDSCHECKS
1244 n_assert(index <= this->count && (index >= 0));
1245 #endif
1246 if (index == this->count)
1247 {
1248 // special case: append element to back
1249 this->Append(std::forward<ELEM>(elm));
1250 }
1251 else
1252 {
1253 this->Move(index, index + 1);
1254 this->elements[index] = std::forward<ELEM>(elm);
1255 }
1256}
1257
1258//------------------------------------------------------------------------------
1263template<class TYPE, int SMALL_VECTOR_SIZE>
1264void
1266{
1267 if (this->count > 0)
1268 {
1269 this->DestroyRange(0, this->count);
1270 this->count = 0;
1271 }
1272}
1273
1274//------------------------------------------------------------------------------
1279template<class TYPE, int SMALL_VECTOR_SIZE>
1280void
1282{
1283 this->count = 0;
1284}
1285
1286//------------------------------------------------------------------------------
1290template<class TYPE, int SMALL_VECTOR_SIZE>
1291void
1293{
1294 this->Delete();
1295 this->grow = 16;
1296}
1297
1298//------------------------------------------------------------------------------
1301template<class TYPE, int SMALL_VECTOR_SIZE>
1304{
1305 return this->elements;
1306}
1307
1308//------------------------------------------------------------------------------
1311template<class TYPE, int SMALL_VECTOR_SIZE>
1317
1318//------------------------------------------------------------------------------
1321template<class TYPE, int SMALL_VECTOR_SIZE>
1324{
1325 return this->elements + this->count;
1326}
1327
1328//------------------------------------------------------------------------------
1331template<class TYPE, int SMALL_VECTOR_SIZE>
1337
1338//------------------------------------------------------------------------------
1346template<class TYPE, int SMALL_VECTOR_SIZE>
1348Array<TYPE, SMALL_VECTOR_SIZE>::Find(const TYPE& elm, const IndexT start) const
1349{
1350 n_assert(start <= this->count);
1351 IndexT index;
1352 for (index = start; index < this->count; index++)
1353 {
1354 if (this->elements[index] == elm)
1355 {
1356 return &(this->elements[index]);
1357 }
1358 }
1359 return 0;
1360}
1361
1362//------------------------------------------------------------------------------
1370template<class TYPE, int SMALL_VECTOR_SIZE>
1371IndexT
1372Array<TYPE, SMALL_VECTOR_SIZE>::FindIndex(const TYPE& elm, const IndexT start) const
1373{
1374 n_assert(start <= this->count);
1375 IndexT index;
1376 for (index = start; index < this->count; index++)
1377 {
1378 if (this->elements[index] == elm)
1379 {
1380 return index;
1381 }
1382 }
1383 return InvalidIndex;
1384}
1385
1386//------------------------------------------------------------------------------
1389template<class TYPE, int SMALL_VECTOR_SIZE>
1390template<typename ...ELEM_TYPE>
1391inline void
1392Array<TYPE, SMALL_VECTOR_SIZE>::Append(const TYPE& first, const ELEM_TYPE&... elements)
1393{
1394 // The plus one is for the first element
1395 const int size = sizeof...(elements) + 1;
1396 this->Reserve(size);
1397 TYPE res[size] = { first, elements... };
1398 for (IndexT i = 0; i < size; i++)
1399 {
1400 this->elements[this->count++] = res[i];
1401 }
1402}
1403
1404//------------------------------------------------------------------------------
1419template<class TYPE, int SMALL_VECTOR_SIZE>
1420template<typename KEYTYPE>
1421inline IndexT
1422Array<TYPE, SMALL_VECTOR_SIZE>::FindIndex(typename std::enable_if<true, const KEYTYPE&>::type elm, const IndexT start) const
1423{
1424 n_assert(start <= this->count);
1425 IndexT index;
1426 for (index = start; index < this->count; index++)
1427 {
1428 if (this->elements[index] == elm)
1429 {
1430 return index;
1431 }
1432 }
1433 return InvalidIndex;
1434}
1435
1436//------------------------------------------------------------------------------
1445template<class TYPE, int SMALL_VECTOR_SIZE>
1446void
1448{
1449 if ((first + num) > this->count)
1450 {
1451 this->GrowTo(first + num);
1452 this->count = first + num;
1453 }
1454
1455 IndexT i;
1456 for (i = first; i < (first + num); i++)
1457 {
1458 this->elements[i] = elm;
1459 }
1460}
1461
1462//------------------------------------------------------------------------------
1469template<class TYPE, int SMALL_VECTOR_SIZE>
1472{
1474 IndexT i;
1475 SizeT num = rhs.Size();
1476 for (i = 0; i < num; i++)
1477 {
1478 if (0 == this->Find(rhs[i]))
1479 {
1480 diff.Append(rhs[i]);
1481 }
1482 }
1483 return diff;
1484}
1485
1486//------------------------------------------------------------------------------
1490template<class TYPE, int SMALL_VECTOR_SIZE>
1491void
1493{
1494 if (this->Size() == 0)
1495 return;
1496 n_assert(this->elements != nullptr);
1497 std::sort(this->Begin(), this->End());
1498}
1499
1500//------------------------------------------------------------------------------
1504template <class TYPE, int SMALL_VECTOR_SIZE>
1505void
1507{
1508 if (this->Size() == 0)
1509 {
1510 return;
1511 }
1512 n_assert(this->elements != nullptr);
1513 std::qsort(
1514 this->Begin(),
1515 this->Size(),
1516 sizeof(TYPE),
1517 [](const void* a, const void* b)
1518 {
1519 TYPE arg1 = *static_cast<const TYPE*>(a);
1520 TYPE arg2 = *static_cast<const TYPE*>(b);
1521 return (arg1 > arg2) - (arg1 < arg2);
1522 }
1523 );
1524}
1525
1526//------------------------------------------------------------------------------
1529template<class TYPE, int SMALL_VECTOR_SIZE>
1530void
1531Util::Array<TYPE, SMALL_VECTOR_SIZE>::SortWithFunc(bool (*func)(const TYPE& lhs, const TYPE& rhs))
1532{
1533 n_assert(func != nullptr);
1534 if (this->Size() == 0)
1535 {
1536 return;
1537 }
1538 n_assert(this->elements != nullptr);
1539 std::sort(this->Begin(), this->End(), func);
1540}
1541
1542//------------------------------------------------------------------------------
1545template <class TYPE, int SMALL_VECTOR_SIZE>
1546void
1547Array<TYPE, SMALL_VECTOR_SIZE>::QuickSortWithFunc(int (*func)(const void* lhs, const void* rhs))
1548{
1549 n_assert(func != nullptr);
1550 if (this->Size() == 0)
1551 return;
1552 n_assert(this->elements != nullptr);
1553 std::qsort(
1554 this->Begin(),
1555 this->Size(),
1556 sizeof(TYPE),
1557 func
1558 );
1559}
1560
1561//------------------------------------------------------------------------------
1566template<class TYPE, int SMALL_VECTOR_SIZE>
1567IndexT
1569{
1570 SizeT num = this->Size();
1571 if (num > 0)
1572 {
1573 IndexT half;
1574 IndexT lo = 0;
1575 IndexT hi = num - 1;
1576 IndexT mid;
1577 while (lo <= hi)
1578 {
1579 if (0 != (half = num/2))
1580 {
1581 mid = lo + ((num & 1) ? half : (half - 1));
1582 if (elm < this->elements[mid])
1583 {
1584 hi = mid - 1;
1585 num = num & 1 ? half : half - 1;
1586 }
1587 else if (elm > this->elements[mid])
1588 {
1589 lo = mid + 1;
1590 num = half;
1591 }
1592 else
1593 {
1594 return mid;
1595 }
1596 }
1597 else if (0 != num)
1598 {
1599 if (elm != this->elements[lo])
1600 {
1601 return InvalidIndex;
1602 }
1603 else
1604 {
1605 return lo;
1606 }
1607 }
1608 else
1609 {
1610 break;
1611 }
1612 }
1613 }
1614 return InvalidIndex;
1615}
1616
1617//------------------------------------------------------------------------------
1626template<class TYPE, int SMALL_VECTOR_SIZE>
1627template<typename KEYTYPE> inline IndexT
1628Array<TYPE, SMALL_VECTOR_SIZE>::BinarySearchIndex(typename std::enable_if<true, const KEYTYPE&>::type elm) const
1629{
1630 SizeT num = this->Size();
1631 if (num > 0)
1632 {
1633 IndexT half;
1634 IndexT lo = 0;
1635 IndexT hi = num - 1;
1636 IndexT mid;
1637 while (lo <= hi)
1638 {
1639 if (0 != (half = num / 2))
1640 {
1641 mid = lo + ((num & 1) ? half : (half - 1));
1642 if (this->elements[mid] > elm)
1643 {
1644 hi = mid - 1;
1645 num = num & 1 ? half : half - 1;
1646 }
1647 else if (this->elements[mid] < elm)
1648 {
1649 lo = mid + 1;
1650 num = half;
1651 }
1652 else
1653 {
1654 return mid;
1655 }
1656 }
1657 else if (0 != num)
1658 {
1659 if (this->elements[lo] != elm)
1660 {
1661 return InvalidIndex;
1662 }
1663 else
1664 {
1665 return lo;
1666 }
1667 }
1668 else
1669 {
1670 break;
1671 }
1672 }
1673 }
1674 return InvalidIndex;
1675}
1676
1677//------------------------------------------------------------------------------
1680template<class TYPE, int SMALL_VECTOR_SIZE>
1681void
1683{
1684 if (num < this->count)
1685 {
1686 this->DestroyRange(num, this->count);
1687 }
1688 else if (num > this->capacity)
1689 {
1690 this->GrowTo(num);
1691 }
1692
1693 this->count = num;
1694}
1695
1696//------------------------------------------------------------------------------
1699template<class TYPE, int SMALL_VECTOR_SIZE>
1700template<typename ...ARGS>
1702{
1703 if (num < this->count)
1704 {
1705 this->DestroyRange(num, this->count);
1706 }
1707 else
1708 {
1709 if (num > this->capacity)
1710 {
1711 this->GrowTo(num);
1712 }
1713 for (IndexT i = this->count; i < num; i++)
1714 {
1715 this->elements[i] = TYPE(args...);
1716 }
1717 }
1718
1719 this->count = num;
1720}
1721
1722//------------------------------------------------------------------------------
1725template<class TYPE, int SMALL_VECTOR_SIZE>
1727{
1728 if (num > this->capacity)
1729 {
1730 this->GrowTo(num);
1731 }
1732 this->count = Math::max(this->count, num);
1733}
1734
1735//------------------------------------------------------------------------------
1738template<class TYPE, int SMALL_VECTOR_SIZE>
1739void
1741{
1742 this->Clear();
1743}
1744
1745//------------------------------------------------------------------------------
1748template<class TYPE, int SMALL_VECTOR_SIZE>
1749inline void
1751{
1752 TYPE* newArray = ArrayAlloc<TYPE>(this->count);
1753 if (this->elements)
1754 {
1755 this->MoveRange(newArray, this->elements, this->count);
1756 if (this->elements != this->stackElements.data())
1757 ArrayFree(this->capacity, this->elements);
1758 }
1759 this->elements = newArray;
1760
1761 this->capacity = this->count;
1762}
1763
1764//------------------------------------------------------------------------------
1767template<class TYPE, int SMALL_VECTOR_SIZE>
1768inline constexpr SizeT
1770{
1771 return sizeof(TYPE);
1772}
1773
1774//------------------------------------------------------------------------------
1777template<class TYPE, int SMALL_VECTOR_SIZE>
1778size_t
1780{
1781 return this->count;
1782}
1783
1784
1785//------------------------------------------------------------------------------
1788template<class TYPE, int SMALL_VECTOR_SIZE>
1791{
1792 return this->elements;
1793}
1794
1795//------------------------------------------------------------------------------
1798template<class TYPE, int SMALL_VECTOR_SIZE>
1801{
1802 return this->elements + this->count;
1803}
1804
1805//------------------------------------------------------------------------------
1808template<class TYPE, int SMALL_VECTOR_SIZE>
1809void
1811{
1812 if (static_cast<SizeT>(s) > this->capacity)
1813 {
1814 this->GrowTo(static_cast<SizeT>(s));
1815 }
1816 this->count = static_cast<SizeT>(s);
1817}
1818
1819
1820//------------------------------------------------------------------------------
1825template<class TYPE, int SMALL_VECTOR_SIZE>
1826bool
1828{
1829 if (this->count > 1)
1830 {
1831 IndexT i;
1832 for (i = 0; i < this->count - 1; i++)
1833 {
1834 if (this->elements[i] > this->elements[i + 1])
1835 {
1836 return false;
1837 }
1838 }
1839 }
1840 return true;
1841}
1842
1843//------------------------------------------------------------------------------
1849template<class TYPE, int SMALL_VECTOR_SIZE>
1850IndexT
1852{
1853 return this->InsertAtEndOfIdenticalRangeInternal(startIndex, elm);
1854}
1855
1856//------------------------------------------------------------------------------
1862template<class TYPE, int SMALL_VECTOR_SIZE>
1863IndexT
1865{
1866 return this->InsertAtEndOfIdenticalRangeInternal(startIndex, std::move(elm));
1867}
1868
1869//------------------------------------------------------------------------------
1872template<class TYPE, int SMALL_VECTOR_SIZE>
1873template<typename ELEM>
1874IndexT
1876{
1877 const TYPE& probe = elm;
1878 IndexT i = startIndex + 1;
1879 for (; i < this->count; i++)
1880 {
1881 if (this->elements[i] != probe)
1882 {
1883 this->InsertInternal(i, std::forward<ELEM>(elm));
1884 return i;
1885 }
1886 }
1887
1888 // fallthrough: new element needs to be appended to end
1889 this->Append(std::forward<ELEM>(elm));
1890 return (this->Size() - 1);
1891}
1892
1893//------------------------------------------------------------------------------
1898template<class TYPE, int SMALL_VECTOR_SIZE>
1899IndexT
1901{
1902 return this->InsertSortedInternal(elm);
1903}
1904
1905//------------------------------------------------------------------------------
1910template<class TYPE, int SMALL_VECTOR_SIZE>
1911IndexT
1913{
1914 return this->InsertSortedInternal(std::move(elm));
1915}
1916
1917//------------------------------------------------------------------------------
1920template<class TYPE, int SMALL_VECTOR_SIZE>
1921template<typename ELEM>
1922IndexT
1924{
1925 const TYPE& probe = elm;
1926 SizeT num = this->Size();
1927 if (num == 0)
1928 {
1929 // array is currently empty
1930 this->Append(std::forward<ELEM>(elm));
1931 return this->Size() - 1;
1932 }
1933 else
1934 {
1935 IndexT half;
1936 IndexT lo = 0;
1937 IndexT hi = num - 1;
1938 IndexT mid;
1939 while (lo <= hi)
1940 {
1941 if (0 != (half = num/2))
1942 {
1943 mid = lo + ((num & 1) ? half : (half - 1));
1944 if (probe < this->elements[mid])
1945 {
1946 hi = mid - 1;
1947 num = num & 1 ? half : half - 1;
1948 }
1949 else if (probe > this->elements[mid])
1950 {
1951 lo = mid + 1;
1952 num = half;
1953 }
1954 else
1955 {
1956 // element already exists at [mid], append the
1957 // new element to the end of the range
1958 return this->InsertAtEndOfIdenticalRangeInternal(mid, std::forward<ELEM>(elm));
1959 }
1960 }
1961 else if (0 != num)
1962 {
1963 if (probe < this->elements[lo])
1964 {
1965 this->InsertInternal(lo, std::forward<ELEM>(elm));
1966 return lo;
1967 }
1968 else if (probe > this->elements[lo])
1969 {
1970 this->InsertInternal(lo + 1, std::forward<ELEM>(elm));
1971 return lo + 1;
1972 }
1973 else
1974 {
1975 // element already exists at [low], append
1976 // the new element to the end of the range
1977 return this->InsertAtEndOfIdenticalRangeInternal(lo, std::forward<ELEM>(elm));
1978 }
1979 }
1980 else
1981 {
1982 #if NEBULA_BOUNDSCHECKS
1983 n_assert(0 == lo);
1984 #endif
1985 this->InsertInternal(lo, std::forward<ELEM>(elm));
1986 return lo;
1987 }
1988 }
1989 if (probe < this->elements[lo])
1990 {
1991 this->InsertInternal(lo, std::forward<ELEM>(elm));
1992 return lo;
1993 }
1994 else if (probe > this->elements[lo])
1995 {
1996 this->InsertInternal(lo + 1, std::forward<ELEM>(elm));
1997 return lo + 1;
1998 }
1999 else
2000 {
2001 // can't happen(?)
2002 }
2003 }
2004 // can't happen
2005 n_error("Array::InsertSorted: Can't happen!");
2006 return InvalidIndex;
2007}
2008
2009template<class TYPE, int STACK_SIZE>
2011
2012} // namespace Util
2013//------------------------------------------------------------------------------
Definition half.h:20
Nebula's dynamic array class.
Definition array.h:61
IndexT InsertAtEndOfIdenticalRangeInternal(IndexT startIndex, ELEM &&elm)
Array(std::nullptr_t)
construct an empty fixed array
Definition array.h:364
void Move(IndexT fromIndex, IndexT toIndex)
const TYPE * ConstIterator
Definition array.h:65
void Extend(SizeT num)
Resize to fit the provided value, but don't shrink if the new size is smaller.
Definition array.h:1726
void InsertInternal(IndexT index, ELEM &&elm)
void Insert(IndexT index, TYPE &&elm)
insert rvalue element before element at index
Definition array.h:1230
Array(SizeT initialCapacity, SizeT initialGrow)
constuctor with initial size and grow size
Definition array.h:287
void Reserve(SizeT num)
increase capacity to fit N more elements into the array.
Definition array.h:895
void Fill(IndexT first, SizeT num, const TYPE &elm)
fill array range with element
Definition array.h:1447
IndexT FindIndex(const TYPE &elm, const IndexT start=0) const
find identical element in array, return index, InvalidIndex if not found
Definition array.h:1372
Iterator End() const
return iterator to end of array
Definition array.h:1323
SizeT capacity
Definition array.h:264
SizeT count
Definition array.h:265
TYPE * EmplaceArray(const SizeT count)
Emplace range of items and return pointer to first.
Definition array.h:864
~Array()
destructor
Definition array.h:487
Iterator Find(const TYPE &elm, const IndexT start=0) const
find identical element in array, return iterator
Definition array.h:1348
IndexT FindIndex(typename std::enable_if< true, const KEYTYPE & >::type elm, const IndexT start=0) const
find identical element using a specific key type
Definition array.h:1422
bool operator!=(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs) const
inequality operator
Definition array.h:1003
TYPE * Iterator
define iterator
Definition array.h:64
void EraseFront()
erase front
Definition array.h:1178
TYPE & Back() const
return reference to last element
Definition array.h:1026
IndexT InsertAtEndOfIdenticalRange(IndexT startIndex, TYPE &&elm)
insert rvalue element at the first non-identical position, return index of inclusion position
Definition array.h:1864
void Copy(const Array< TYPE, SMALL_VECTOR_SIZE > &src)
const SizeT Capacity() const
get overall allocated size of array in number of elements
Definition array.h:933
void Clear()
clear array (calls destructors)
Definition array.h:1265
TYPE * elements
Definition array.h:266
IndexT InsertAtEndOfIdenticalRange(IndexT startIndex, const TYPE &elm)
insert element at the first non-identical position, return index of inclusion position
Definition array.h:1851
ConstIterator ConstEnd() const
return const iterator to end of array
Definition array.h:1333
constexpr SizeT TypeSize() const
Returns sizeof(TYPE).
Definition array.h:1769
Array(std::initializer_list< TYPE > list)
constructor from initializer list
Definition array.h:345
void EraseRange(IndexT start, IndexT end)
erase range, excluding the element at end
Definition array.h:1145
IndexT BinarySearchIndex(typename std::enable_if< true, const KEYTYPE & >::type elm) const
do a binary search using a specific key type
Definition array.h:1628
void Sort()
sort the array
Definition array.h:1492
SizeT grow
Definition array.h:263
void operator=(Array< TYPE, SMALL_VECTOR_SIZE > &&rhs) noexcept
move operator
Definition array.h:546
void QuickSort()
quick sort the array
Definition array.h:1506
void Append(TYPE &&elm)
append an element which is being forwarded
Definition array.h:783
void DestroyRange(IndexT fromIndex, IndexT toIndex)
Array< TYPE, SMALL_VECTOR_SIZE > ArrayT
Definition array.h:67
TYPE & operator[](IndexT index) const
[] operator
Definition array.h:945
static const SizeT MinGrowSize
Definition array.h:261
Array(ArrayT &&rhs) noexcept
move constructor
Definition array.h:389
void SortWithFunc(bool(*func)(const TYPE &lhs, const TYPE &rhs))
sort with custom function
Definition array.h:1531
void Append(const TYPE &first, const ELEM_TYPE &... elements)
Append multiple elements to the end of the array.
Definition array.h:1392
TYPE & operator[](IndexT index)
[] operator
Definition array.h:960
Iterator begin() const
for range-based iteration
Definition array.h:1790
Iterator EraseSwap(Iterator iter)
erase element at iterator, fill gap by swapping in last element, destroys sorting!
Definition array.h:1131
TYPE & Emplace()
Emplace item (create new item and return reference).
Definition array.h:845
Array(const TYPE *const buf, SizeT num)
constructor from TYPE pointer and size.
Definition array.h:328
void Reset()
reset array (does NOT call destructors)
Definition array.h:1281
void Realloc(SizeT capacity, SizeT grow)
clear contents and preallocate with new attributes
Definition array.h:496
T As() const
convert to "anything"
bool IsEmpty() const
return true if array empty
Definition array.h:1049
IndexT InsertSorted(const TYPE &elm)
insert element into sorted array, return index where element was included
Definition array.h:1900
void AppendArray(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs)
append the contents of an array to this array
Definition array.h:801
void EraseIndex(IndexT index)
erase element at index, keep sorting intact
Definition array.h:1069
static const SizeT MaxGrowSize
Definition array.h:262
const SizeT ByteSize() const
return the byte size of the array.
Definition array.h:923
void EraseIndexSwap(IndexT index)
erase element at index, fill gap by swapping in last element, destroys sorting!
Definition array.h:1091
TYPE PopFront()
Pop front.
Definition array.h:1188
ConstIterator ConstBegin() const
return const iterator to beginning of array
Definition array.h:1313
_smallvector< TYPE, SMALL_VECTOR_SIZE > stackElements
Definition array.h:268
void resize(size_t size)
Definition array.h:1810
Array(SizeT initialSize, SizeT initialGrow, const TYPE &initialValue)
constructor with initial size, grow size and initial values
Definition array.h:304
void operator=(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs)
assignment operator
Definition array.h:516
void Append(const TYPE &elm)
append element to end of array
Definition array.h:765
TYPE & Get(IndexT index) const
Get element (same as operator[] but as a function).
Definition array.h:751
void Insert(IndexT index, const TYPE &elm)
insert element before element at index
Definition array.h:1220
size_t size() const
Definition array.h:1779
void CopyRange(TYPE *to, TYPE *from, SizeT num)
void Resize(SizeT num, ARGS... args)
Resize and fill new elements with arguments.
Definition array.h:1701
bool operator==(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs) const
equality operator
Definition array.h:975
ArrayT Difference(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs)
returns new array with elements which are not in rhs (slow!)
Definition array.h:1471
void EraseBack()
erase back
Definition array.h:1166
bool IsValidIndex(IndexT index) const
check if index is valid
Definition array.h:1059
IndexT InsertSorted(TYPE &&elm)
insert rvalue element into sorted array, return index where element was included
Definition array.h:1912
Iterator Begin() const
return iterator to beginning of array
Definition array.h:1303
bool IsSorted() const
test if the array is sorted, this is a slow operation!
Definition array.h:1827
IndexT BinarySearchIndex(const TYPE &elm) const
do a binary search, requires a sorted array
Definition array.h:1568
void MoveRange(TYPE *to, TYPE *from, SizeT num)
friend class FixedArray
Definition array.h:240
void Resize(SizeT num)
Set size. Grows array if num is greater than capacity. Calls destroy on all objects at index > num!
Definition array.h:1682
void QuickSortWithFunc(int(*func)(const void *lhs, const void *rhs))
quick sort the array
Definition array.h:1547
Array()
constructor with default parameters
Definition array.h:275
void Free()
free memory and reset size
Definition array.h:1292
const SizeT Size() const
get number of elements in array
Definition array.h:913
void AppendArray(const TYPE *arr, const SizeT count)
append from C array
Definition array.h:823
void clear() noexcept
Definition array.h:1740
TYPE & Front() const
return reference to first element
Definition array.h:1013
TYPE PopBack()
Pop back.
Definition array.h:1203
Iterator Erase(Iterator iter)
erase element pointed to by iterator, keep sorting intact
Definition array.h:1116
void Fit()
Fit the size of the array to the amount of elements.
Definition array.h:1750
Array(const ArrayT &rhs)
copy constructor
Definition array.h:376
void __cdecl n_error(const char *msg,...)
This function is called when a serious situation is encountered which requires abortion of the applic...
Definition debug.cc:138
#define n_assert(exp)
Definition debug.h:50
void ArrayFree(size_t size, TYPE *buffer)
Definition memory.h:188
TYPE * ArrayAlloc(size_t size)
Definition memory.h:137
__forceinline TYPE max(TYPE a, TYPE b)
Definition scalar.h:368
void Copy(const void *from, void *to, size_t numBytes)
Copy a chunk of memory (note the argument order is different from memcpy()!
Definition osxmemory.cc:213
__forceinline void CopyElements(const T *from, T *to, size_t numElements)
Copy a chunk of memory (note the argument order is different from memcpy()!
Definition posixmemory.h:229
__forceinline void MoveElements(const T *from, T *to, size_t numElements)
Move a chunk of memory, can handle overlapping regions.
Definition posixmemory.h:205
void Clear(void *ptr, size_t numBytes)
Overwrite a chunk of memory with 0's.
Definition osxmemory.cc:229
A quad tree designed to return regions of free 2D space.
Definition Random.cs:4
Array< TYPE, STACK_SIZE > StackArray
Definition array.h:2010
Nebula's scalar datatype.
TYPE * data()
Definition array.h:57
Definition array.h:48
TYPE stackElements[STACK_SIZE]
Definition array.h:51
TYPE * data()
Definition array.h:49
static const int InvalidIndex
Definition types.h:47
int SizeT
Definition types.h:42
int IndexT
Definition types.h:41