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.elements == rhs.stackElements.data())
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 // elm may be an element of this array, so copy it before growing frees it
771 TYPE copy(elm);
772 this->Grow();
773 #if NEBULA_BOUNDSCHECKS
774 n_assert(this->elements);
775 #endif
776 this->elements[this->count++] = std::move(copy);
777 return;
778 }
779 #if NEBULA_BOUNDSCHECKS
780 n_assert(this->elements);
781 #endif
782 this->elements[this->count++] = elm;
783}
784
785//------------------------------------------------------------------------------
788template<class TYPE, int SMALL_VECTOR_SIZE>
789void
791{
792 // grow allocated space if exhausted
793 if (this->count == this->capacity)
794 {
795 // elm may be an element of this array, so take it before growing frees it
796 TYPE moved(std::move(elm));
797 this->Grow();
798#if NEBULA_BOUNDSCHECKS
799 n_assert(this->elements);
800#endif
801 this->elements[this->count++] = std::move(moved);
802 return;
803 }
804#if NEBULA_BOUNDSCHECKS
805 n_assert(this->elements);
806#endif
807 this->elements[this->count++] = std::move(elm);
808}
809
810//------------------------------------------------------------------------------
813template<class TYPE, int SMALL_VECTOR_SIZE>
814void
816{
817 SizeT neededCapacity = this->count + rhs.count;
818 if (neededCapacity > this->capacity)
819 {
820 this->GrowTo(neededCapacity);
821 }
822
823 // forward elements from array
824 IndexT i;
825 for (i = 0; i < rhs.count; i++)
826 {
827 this->elements[this->count + i] = rhs.elements[i];
828 }
829 this->count += rhs.count;
830}
831
832//------------------------------------------------------------------------------
835template<class TYPE, int SMALL_VECTOR_SIZE>
836void
838{
839 SizeT neededCapacity = this->count + count;
840 if (neededCapacity > this->capacity)
841 {
842 // arr may point into this array, rebase it since growing frees the old buffer
843 const bool isAliased = (arr >= this->elements) && (arr < this->elements + this->count);
844 const PtrDiff aliasOffset = arr - this->elements;
845 this->GrowTo(neededCapacity);
846 if (isAliased)
847 {
848 arr = this->elements + aliasOffset;
849 }
850 }
851
852 // forward elements from array
853 IndexT i;
854 for (i = 0; i < count; i++)
855 {
856 this->elements[this->count + i] = arr[i];
857 }
858 this->count += count;
859}
860
861//------------------------------------------------------------------------------
864template<class TYPE, int SMALL_VECTOR_SIZE>
865TYPE&
867{
868 // grow allocated space if exhausted
869 if (this->count == this->capacity)
870 {
871 this->Grow();
872 }
873#if NEBULA_BOUNDSCHECKS
874 n_assert(this->elements);
875#endif
876 this->elements[this->count] = TYPE();
877 return this->elements[this->count++];
878}
879
880//------------------------------------------------------------------------------
883template<class TYPE, int SMALL_VECTOR_SIZE>
884TYPE*
886{
887 SizeT neededCapacity = this->count + count;
888 if (neededCapacity > this->capacity)
889 {
890 this->GrowTo(neededCapacity);
891 }
892
893 // forward elements from array
894 IndexT i;
895 for (i = 0; i < count; i++)
896 {
897 this->elements[this->count + i] = TYPE();
898 }
899 TYPE* first = &this->elements[this->count];
900 this->count += count;
901 return first;
902}
903
904//------------------------------------------------------------------------------
914template<class TYPE, int SMALL_VECTOR_SIZE>
915void
917{
918#if NEBULA_BOUNDSCHECKS
919 n_assert(num >= 0);
920#endif
921
922 SizeT neededCapacity = this->count + num;
923 if (neededCapacity > this->capacity)
924 {
925 this->GrowTo(neededCapacity);
926 }
927}
928
929//------------------------------------------------------------------------------
932template<class TYPE, int SMALL_VECTOR_SIZE>
933const SizeT
935{
936 return this->count;
937}
938
939//------------------------------------------------------------------------------
942template<class TYPE, int SMALL_VECTOR_SIZE>
943const SizeT
945{
946 return this->count * sizeof(TYPE);
947}
948
949//------------------------------------------------------------------------------
952template<class TYPE, int SMALL_VECTOR_SIZE>
953const SizeT
955{
956 return this->capacity;
957}
958
959//------------------------------------------------------------------------------
964template<class TYPE, int SMALL_VECTOR_SIZE>
965TYPE&
967{
968 #if NEBULA_BOUNDSCHECKS
969 n_assert(this->elements && (index < this->count) && (index >= 0));
970 #endif
971 return this->elements[index];
972}
973
974//------------------------------------------------------------------------------
979template<class TYPE, int SMALL_VECTOR_SIZE>
980TYPE&
982{
983#if NEBULA_BOUNDSCHECKS
984 n_assert(this->elements && (index < this->count) && (index >= 0));
985#endif
986 return this->elements[index];
987}
988
989//------------------------------------------------------------------------------
994template<class TYPE, int SMALL_VECTOR_SIZE>
995bool
997{
998 if (rhs.Size() == this->Size())
999 {
1000 IndexT i;
1001 SizeT num = this->Size();
1002 for (i = 0; i < num; i++)
1003 {
1004 if (!(this->elements[i] == rhs.elements[i]))
1005 {
1006 return false;
1007 }
1008 }
1009 return true;
1010 }
1011 else
1012 {
1013 return false;
1014 }
1015}
1016
1017//------------------------------------------------------------------------------
1022template<class TYPE, int SMALL_VECTOR_SIZE>
1023bool
1025{
1026 return !(*this == rhs);
1027}
1028
1029//------------------------------------------------------------------------------
1032template<class TYPE, int SMALL_VECTOR_SIZE>
1033TYPE&
1035{
1036 #if NEBULA_BOUNDSCHECKS
1037 n_assert(this->elements && (this->count > 0));
1038 #endif
1039 return this->elements[0];
1040}
1041
1042//------------------------------------------------------------------------------
1045template<class TYPE, int SMALL_VECTOR_SIZE>
1046TYPE&
1048{
1049 #if NEBULA_BOUNDSCHECKS
1050 n_assert(this->elements && (this->count > 0));
1051 #endif
1052 return this->elements[this->count - 1];
1053}
1054
1055//------------------------------------------------------------------------------
1058template<class TYPE, int SMALL_VECTOR_SIZE>
1059void
1061{
1062 this->Append(item);
1063}
1064
1065//------------------------------------------------------------------------------
1068template<class TYPE, int SMALL_VECTOR_SIZE>
1069bool
1071{
1072 return (this->count == 0);
1073}
1074
1075//------------------------------------------------------------------------------
1078template<class TYPE, int SMALL_VECTOR_SIZE>
1079bool
1081{
1082 return this->elements && (index < this->count) && (index >= 0);
1083}
1084
1085//------------------------------------------------------------------------------
1088template<class TYPE, int SMALL_VECTOR_SIZE>
1089void
1091{
1092 #if NEBULA_BOUNDSCHECKS
1093 n_assert(this->elements && (index < this->count) && (index >= 0));
1094 #endif
1095 if (index == (this->count - 1))
1096 {
1097 // special case: last element
1098 this->EraseBack();
1099 }
1100 else
1101 {
1102 this->Move(index + 1, index);
1103 }
1104}
1105
1106//------------------------------------------------------------------------------
1110template<class TYPE, int SMALL_VECTOR_SIZE>
1111void
1113{
1114 #if NEBULA_BOUNDSCHECKS
1115 n_assert(this->elements && (index < this->count) && (index >= 0));
1116 #endif
1117
1118 // swap with last element, and destroy last element
1119 IndexT lastElementIndex = this->count - 1;
1120 if (index < lastElementIndex)
1121 {
1122 this->elements[index] = std::move(this->elements[lastElementIndex]);
1123 this->Reset(&this->elements[lastElementIndex]);
1124 }
1125 else
1126 {
1127 this->Reset(&this->elements[index]);
1128 }
1129 this->count--;
1130}
1131
1132//------------------------------------------------------------------------------
1135template<class TYPE, int SMALL_VECTOR_SIZE>
1138{
1139 #if NEBULA_BOUNDSCHECKS
1140 n_assert(this->elements && (iter >= this->elements) && (iter < (this->elements + this->count)));
1141 #endif
1142 this->EraseIndex(IndexT(iter - this->elements));
1143 return iter;
1144}
1145
1146//------------------------------------------------------------------------------
1150template<class TYPE, int SMALL_VECTOR_SIZE>
1153{
1154 #if NEBULA_BOUNDSCHECKS
1155 n_assert(this->elements && (iter >= this->elements) && (iter < (this->elements + this->count)));
1156 #endif
1157 this->EraseIndexSwap(IndexT(iter - this->elements));
1158 return iter;
1159}
1160
1161//------------------------------------------------------------------------------
1164template<class TYPE, int SMALL_VECTOR_SIZE>
1165void
1167{
1168 n_assert(end >= start);
1169 n_assert(end <= this->count);
1170 if (start == end)
1171 this->EraseIndex(start);
1172 else
1173 {
1174 // add 1 to end to remove and move including that element
1175 this->DestroyRange(start, end);
1176 SizeT numMove = this->count - end;
1177 this->MoveRange(&this->elements[start], &this->elements[end], numMove);
1178 this->count -= end - start;
1179 }
1180}
1181
1182//------------------------------------------------------------------------------
1185template<class TYPE, int SMALL_VECTOR_SIZE>
1186void
1188{
1189 n_assert(this->count > 0);
1190 this->Reset(&(this->elements[this->count - 1]));
1191 this->count--;
1192}
1193
1194//------------------------------------------------------------------------------
1197template<class TYPE, int SMALL_VECTOR_SIZE>
1198void
1203
1204//------------------------------------------------------------------------------
1207template<class TYPE, int SMALL_VECTOR_SIZE>
1208inline TYPE
1210{
1211#if NEBULA_BOUNDSCHECKS
1212 n_assert(this->count > 0);
1213#endif
1214 TYPE ret = std::move(this->elements[0]);
1215 this->EraseIndex(0);
1216 return ret;
1217}
1218
1219//------------------------------------------------------------------------------
1222template<class TYPE, int SMALL_VECTOR_SIZE>
1223inline TYPE
1225{
1226#if NEBULA_BOUNDSCHECKS
1227 n_assert(this->count > 0);
1228#endif
1229 IndexT index = this->count - 1;
1230 TYPE ret = std::move(this->elements[index]);
1231 this->Reset(&(this->elements[index]));
1232 this->count = index;
1233 return ret;
1234}
1235
1236//------------------------------------------------------------------------------
1239template<class TYPE, int SMALL_VECTOR_SIZE>
1240void
1242{
1243 this->InsertInternal(index, elm);
1244}
1245
1246//------------------------------------------------------------------------------
1249template<class TYPE, int SMALL_VECTOR_SIZE>
1250void
1252{
1253 this->InsertInternal(index, std::move(elm));
1254}
1255
1256//------------------------------------------------------------------------------
1259template<class TYPE, int SMALL_VECTOR_SIZE>
1260template<typename ELEM>
1261void
1263{
1264 #if NEBULA_BOUNDSCHECKS
1265 n_assert(index <= this->count && (index >= 0));
1266 #endif
1267 if (index == this->count)
1268 {
1269 // special case: append element to back
1270 this->Append(std::forward<ELEM>(elm));
1271 }
1272 else
1273 {
1274 // elm may be an element of this array, which Move() shifts or frees
1275 TYPE value(std::forward<ELEM>(elm));
1276 this->Move(index, index + 1);
1277 this->elements[index] = std::move(value);
1278 }
1279}
1280
1281//------------------------------------------------------------------------------
1286template<class TYPE, int SMALL_VECTOR_SIZE>
1287void
1289{
1290 if (this->count > 0)
1291 {
1292 this->DestroyRange(0, this->count);
1293 this->count = 0;
1294 }
1295}
1296
1297//------------------------------------------------------------------------------
1302template<class TYPE, int SMALL_VECTOR_SIZE>
1303void
1305{
1306 this->count = 0;
1307}
1308
1309//------------------------------------------------------------------------------
1313template<class TYPE, int SMALL_VECTOR_SIZE>
1314void
1316{
1317 this->Delete();
1318 this->grow = 16;
1319}
1320
1321//------------------------------------------------------------------------------
1324template<class TYPE, int SMALL_VECTOR_SIZE>
1327{
1328 return this->elements;
1329}
1330
1331//------------------------------------------------------------------------------
1334template<class TYPE, int SMALL_VECTOR_SIZE>
1340
1341//------------------------------------------------------------------------------
1344template<class TYPE, int SMALL_VECTOR_SIZE>
1347{
1348 return this->elements + this->count;
1349}
1350
1351//------------------------------------------------------------------------------
1354template<class TYPE, int SMALL_VECTOR_SIZE>
1360
1361//------------------------------------------------------------------------------
1369template<class TYPE, int SMALL_VECTOR_SIZE>
1371Array<TYPE, SMALL_VECTOR_SIZE>::Find(const TYPE& elm, const IndexT start) const
1372{
1373 n_assert(start <= this->count);
1374 IndexT index;
1375 for (index = start; index < this->count; index++)
1376 {
1377 if (this->elements[index] == elm)
1378 {
1379 return &(this->elements[index]);
1380 }
1381 }
1382 return 0;
1383}
1384
1385//------------------------------------------------------------------------------
1393template<class TYPE, int SMALL_VECTOR_SIZE>
1394IndexT
1395Array<TYPE, SMALL_VECTOR_SIZE>::FindIndex(const TYPE& elm, const IndexT start) const
1396{
1397 n_assert(start <= this->count);
1398 IndexT index;
1399 for (index = start; index < this->count; index++)
1400 {
1401 if (this->elements[index] == elm)
1402 {
1403 return index;
1404 }
1405 }
1406 return InvalidIndex;
1407}
1408
1409//------------------------------------------------------------------------------
1412template<class TYPE, int SMALL_VECTOR_SIZE>
1413template<typename ...ELEM_TYPE>
1414inline void
1415Array<TYPE, SMALL_VECTOR_SIZE>::Append(const TYPE& first, const ELEM_TYPE&... elements)
1416{
1417 // The plus one is for the first element
1418 const int size = sizeof...(elements) + 1;
1419 // copy the arguments before reserving, as they may be elements of this array
1420 TYPE res[size] = { first, elements... };
1421 this->Reserve(size);
1422 for (IndexT i = 0; i < size; i++)
1423 {
1424 this->elements[this->count++] = res[i];
1425 }
1426}
1427
1428//------------------------------------------------------------------------------
1443template<class TYPE, int SMALL_VECTOR_SIZE>
1444template<typename KEYTYPE>
1445inline IndexT
1446Array<TYPE, SMALL_VECTOR_SIZE>::FindIndex(typename std::enable_if<true, const KEYTYPE&>::type elm, const IndexT start) const
1447{
1448 n_assert(start <= this->count);
1449 IndexT index;
1450 for (index = start; index < this->count; index++)
1451 {
1452 if (this->elements[index] == elm)
1453 {
1454 return index;
1455 }
1456 }
1457 return InvalidIndex;
1458}
1459
1460//------------------------------------------------------------------------------
1469template<class TYPE, int SMALL_VECTOR_SIZE>
1470void
1472{
1473 // elm may be an element of this array, so copy it before growing frees it
1474 const TYPE value(elm);
1475 if ((first + num) > this->count)
1476 {
1477 if ((first + num) > this->capacity)
1478 {
1479 this->GrowTo(first + num);
1480 }
1481 this->count = first + num;
1482 }
1483
1484 IndexT i;
1485 for (i = first; i < (first + num); i++)
1486 {
1487 this->elements[i] = value;
1488 }
1489}
1490
1491//------------------------------------------------------------------------------
1498template<class TYPE, int SMALL_VECTOR_SIZE>
1501{
1503 IndexT i;
1504 SizeT num = rhs.Size();
1505 for (i = 0; i < num; i++)
1506 {
1507 if (0 == this->Find(rhs[i]))
1508 {
1509 diff.Append(rhs[i]);
1510 }
1511 }
1512 return diff;
1513}
1514
1515//------------------------------------------------------------------------------
1519template<class TYPE, int SMALL_VECTOR_SIZE>
1520void
1522{
1523 if (this->Size() == 0)
1524 return;
1525 n_assert(this->elements != nullptr);
1526 std::sort(this->Begin(), this->End());
1527}
1528
1529//------------------------------------------------------------------------------
1533template <class TYPE, int SMALL_VECTOR_SIZE>
1534void
1536{
1537 if (this->Size() == 0)
1538 {
1539 return;
1540 }
1541 n_assert(this->elements != nullptr);
1542 std::qsort(
1543 this->Begin(),
1544 this->Size(),
1545 sizeof(TYPE),
1546 [](const void* a, const void* b)
1547 {
1548 TYPE arg1 = *static_cast<const TYPE*>(a);
1549 TYPE arg2 = *static_cast<const TYPE*>(b);
1550 return (arg1 > arg2) - (arg1 < arg2);
1551 }
1552 );
1553}
1554
1555//------------------------------------------------------------------------------
1558template<class TYPE, int SMALL_VECTOR_SIZE>
1559void
1560Util::Array<TYPE, SMALL_VECTOR_SIZE>::SortWithFunc(bool (*func)(const TYPE& lhs, const TYPE& rhs))
1561{
1562 n_assert(func != nullptr);
1563 if (this->Size() == 0)
1564 {
1565 return;
1566 }
1567 n_assert(this->elements != nullptr);
1568 std::sort(this->Begin(), this->End(), func);
1569}
1570
1571//------------------------------------------------------------------------------
1574template <class TYPE, int SMALL_VECTOR_SIZE>
1575void
1576Array<TYPE, SMALL_VECTOR_SIZE>::QuickSortWithFunc(int (*func)(const void* lhs, const void* rhs))
1577{
1578 n_assert(func != nullptr);
1579 if (this->Size() == 0)
1580 return;
1581 n_assert(this->elements != nullptr);
1582 std::qsort(
1583 this->Begin(),
1584 this->Size(),
1585 sizeof(TYPE),
1586 func
1587 );
1588}
1589
1590//------------------------------------------------------------------------------
1595template<class TYPE, int SMALL_VECTOR_SIZE>
1596IndexT
1598{
1599 SizeT num = this->Size();
1600 if (num > 0)
1601 {
1602 IndexT half;
1603 IndexT lo = 0;
1604 IndexT hi = num - 1;
1605 IndexT mid;
1606 while (lo <= hi)
1607 {
1608 if (0 != (half = num/2))
1609 {
1610 mid = lo + ((num & 1) ? half : (half - 1));
1611 if (elm < this->elements[mid])
1612 {
1613 hi = mid - 1;
1614 num = num & 1 ? half : half - 1;
1615 }
1616 else if (elm > this->elements[mid])
1617 {
1618 lo = mid + 1;
1619 num = half;
1620 }
1621 else
1622 {
1623 return mid;
1624 }
1625 }
1626 else if (0 != num)
1627 {
1628 if (elm != this->elements[lo])
1629 {
1630 return InvalidIndex;
1631 }
1632 else
1633 {
1634 return lo;
1635 }
1636 }
1637 else
1638 {
1639 break;
1640 }
1641 }
1642 }
1643 return InvalidIndex;
1644}
1645
1646//------------------------------------------------------------------------------
1655template<class TYPE, int SMALL_VECTOR_SIZE>
1656template<typename KEYTYPE> inline IndexT
1657Array<TYPE, SMALL_VECTOR_SIZE>::BinarySearchIndex(typename std::enable_if<true, const KEYTYPE&>::type elm) const
1658{
1659 SizeT num = this->Size();
1660 if (num > 0)
1661 {
1662 IndexT half;
1663 IndexT lo = 0;
1664 IndexT hi = num - 1;
1665 IndexT mid;
1666 while (lo <= hi)
1667 {
1668 if (0 != (half = num / 2))
1669 {
1670 mid = lo + ((num & 1) ? half : (half - 1));
1671 if (this->elements[mid] > elm)
1672 {
1673 hi = mid - 1;
1674 num = num & 1 ? half : half - 1;
1675 }
1676 else if (this->elements[mid] < elm)
1677 {
1678 lo = mid + 1;
1679 num = half;
1680 }
1681 else
1682 {
1683 return mid;
1684 }
1685 }
1686 else if (0 != num)
1687 {
1688 if (this->elements[lo] != elm)
1689 {
1690 return InvalidIndex;
1691 }
1692 else
1693 {
1694 return lo;
1695 }
1696 }
1697 else
1698 {
1699 break;
1700 }
1701 }
1702 }
1703 return InvalidIndex;
1704}
1705
1706//------------------------------------------------------------------------------
1709template<class TYPE, int SMALL_VECTOR_SIZE>
1710void
1712{
1713 if (num < this->count)
1714 {
1715 this->DestroyRange(num, this->count);
1716 }
1717 else if (num > this->capacity)
1718 {
1719 this->GrowTo(num);
1720 }
1721
1722 this->count = num;
1723}
1724
1725//------------------------------------------------------------------------------
1728template<class TYPE, int SMALL_VECTOR_SIZE>
1729template<typename ...ARGS>
1731{
1732 if (num < this->count)
1733 {
1734 this->DestroyRange(num, this->count);
1735 }
1736 else
1737 {
1738 if (num > this->capacity)
1739 {
1740 this->GrowTo(num);
1741 }
1742 for (IndexT i = this->count; i < num; i++)
1743 {
1744 this->elements[i] = TYPE(args...);
1745 }
1746 }
1747
1748 this->count = num;
1749}
1750
1751//------------------------------------------------------------------------------
1754template<class TYPE, int SMALL_VECTOR_SIZE>
1756{
1757 if (num > this->capacity)
1758 {
1759 this->GrowTo(num);
1760 }
1761 this->count = Math::max(this->count, num);
1762}
1763
1764//------------------------------------------------------------------------------
1767template<class TYPE, int SMALL_VECTOR_SIZE>
1768void
1770{
1771 this->Clear();
1772}
1773
1774//------------------------------------------------------------------------------
1777template<class TYPE, int SMALL_VECTOR_SIZE>
1778inline void
1780{
1781 if (this->count <= SMALL_VECTOR_SIZE)
1782 {
1783 // contents fit into the small vector storage, which must be used
1784 // whenever capacity <= SMALL_VECTOR_SIZE
1785 TYPE* stackArray = this->stackElements.data();
1786 if (this->elements != stackArray)
1787 {
1788 this->MoveRange(stackArray, this->elements, this->count);
1789 ArrayFree(this->capacity, this->elements);
1790 this->elements = stackArray;
1791 }
1792 this->capacity = SMALL_VECTOR_SIZE;
1793 }
1794 else if (this->count < this->capacity)
1795 {
1796 // count > SMALL_VECTOR_SIZE means the elements are on the heap
1797 TYPE* newArray = ArrayAlloc<TYPE>(this->count);
1798 this->MoveRange(newArray, this->elements, this->count);
1799 ArrayFree(this->capacity, this->elements);
1800 this->elements = newArray;
1801 this->capacity = this->count;
1802 }
1803}
1804
1805//------------------------------------------------------------------------------
1808template<class TYPE, int SMALL_VECTOR_SIZE>
1809inline constexpr SizeT
1811{
1812 return sizeof(TYPE);
1813}
1814
1815//------------------------------------------------------------------------------
1818template<class TYPE, int SMALL_VECTOR_SIZE>
1819size_t
1821{
1822 return this->count;
1823}
1824
1825
1826//------------------------------------------------------------------------------
1829template<class TYPE, int SMALL_VECTOR_SIZE>
1832{
1833 return this->elements;
1834}
1835
1836//------------------------------------------------------------------------------
1839template<class TYPE, int SMALL_VECTOR_SIZE>
1842{
1843 return this->elements + this->count;
1844}
1845
1846//------------------------------------------------------------------------------
1849template<class TYPE, int SMALL_VECTOR_SIZE>
1850void
1852{
1853 if (static_cast<SizeT>(s) > this->capacity)
1854 {
1855 this->GrowTo(static_cast<SizeT>(s));
1856 }
1857 this->count = static_cast<SizeT>(s);
1858}
1859
1860
1861//------------------------------------------------------------------------------
1866template<class TYPE, int SMALL_VECTOR_SIZE>
1867bool
1869{
1870 if (this->count > 1)
1871 {
1872 IndexT i;
1873 for (i = 0; i < this->count - 1; i++)
1874 {
1875 if (this->elements[i] > this->elements[i + 1])
1876 {
1877 return false;
1878 }
1879 }
1880 }
1881 return true;
1882}
1883
1884//------------------------------------------------------------------------------
1890template<class TYPE, int SMALL_VECTOR_SIZE>
1891IndexT
1893{
1894 return this->InsertAtEndOfIdenticalRangeInternal(startIndex, elm);
1895}
1896
1897//------------------------------------------------------------------------------
1903template<class TYPE, int SMALL_VECTOR_SIZE>
1904IndexT
1906{
1907 return this->InsertAtEndOfIdenticalRangeInternal(startIndex, std::move(elm));
1908}
1909
1910//------------------------------------------------------------------------------
1913template<class TYPE, int SMALL_VECTOR_SIZE>
1914template<typename ELEM>
1915IndexT
1917{
1918 const TYPE& probe = elm;
1919 IndexT i = startIndex + 1;
1920 for (; i < this->count; i++)
1921 {
1922 if (this->elements[i] != probe)
1923 {
1924 this->InsertInternal(i, std::forward<ELEM>(elm));
1925 return i;
1926 }
1927 }
1928
1929 // fallthrough: new element needs to be appended to end
1930 this->Append(std::forward<ELEM>(elm));
1931 return (this->Size() - 1);
1932}
1933
1934//------------------------------------------------------------------------------
1939template<class TYPE, int SMALL_VECTOR_SIZE>
1940IndexT
1942{
1943 return this->InsertSortedInternal(elm);
1944}
1945
1946//------------------------------------------------------------------------------
1951template<class TYPE, int SMALL_VECTOR_SIZE>
1952IndexT
1954{
1955 return this->InsertSortedInternal(std::move(elm));
1956}
1957
1958//------------------------------------------------------------------------------
1961template<class TYPE, int SMALL_VECTOR_SIZE>
1962template<typename ELEM>
1963IndexT
1965{
1966 const TYPE& probe = elm;
1967 SizeT num = this->Size();
1968 if (num == 0)
1969 {
1970 // array is currently empty
1971 this->Append(std::forward<ELEM>(elm));
1972 return this->Size() - 1;
1973 }
1974 else
1975 {
1976 IndexT half;
1977 IndexT lo = 0;
1978 IndexT hi = num - 1;
1979 IndexT mid;
1980 while (lo <= hi)
1981 {
1982 if (0 != (half = num/2))
1983 {
1984 mid = lo + ((num & 1) ? half : (half - 1));
1985 if (probe < this->elements[mid])
1986 {
1987 hi = mid - 1;
1988 num = num & 1 ? half : half - 1;
1989 }
1990 else if (probe > this->elements[mid])
1991 {
1992 lo = mid + 1;
1993 num = half;
1994 }
1995 else
1996 {
1997 // element already exists at [mid], append the
1998 // new element to the end of the range
1999 return this->InsertAtEndOfIdenticalRangeInternal(mid, std::forward<ELEM>(elm));
2000 }
2001 }
2002 else if (0 != num)
2003 {
2004 if (probe < this->elements[lo])
2005 {
2006 this->InsertInternal(lo, std::forward<ELEM>(elm));
2007 return lo;
2008 }
2009 else if (probe > this->elements[lo])
2010 {
2011 this->InsertInternal(lo + 1, std::forward<ELEM>(elm));
2012 return lo + 1;
2013 }
2014 else
2015 {
2016 // element already exists at [low], append
2017 // the new element to the end of the range
2018 return this->InsertAtEndOfIdenticalRangeInternal(lo, std::forward<ELEM>(elm));
2019 }
2020 }
2021 else
2022 {
2023 #if NEBULA_BOUNDSCHECKS
2024 n_assert(0 == lo);
2025 #endif
2026 this->InsertInternal(lo, std::forward<ELEM>(elm));
2027 return lo;
2028 }
2029 }
2030 if (probe < this->elements[lo])
2031 {
2032 this->InsertInternal(lo, std::forward<ELEM>(elm));
2033 return lo;
2034 }
2035 else if (probe > this->elements[lo])
2036 {
2037 this->InsertInternal(lo + 1, std::forward<ELEM>(elm));
2038 return lo + 1;
2039 }
2040 else
2041 {
2042 // can't happen(?)
2043 }
2044 }
2045 // can't happen
2046 n_error("Array::InsertSorted: Can't happen!");
2047 return InvalidIndex;
2048}
2049
2050template<class TYPE, int STACK_SIZE>
2052
2053} // namespace Util
2054//------------------------------------------------------------------------------
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:1755
void InsertInternal(IndexT index, ELEM &&elm)
void Insert(IndexT index, TYPE &&elm)
insert rvalue element before element at index
Definition array.h:1251
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:916
void Fill(IndexT first, SizeT num, const TYPE &elm)
fill array range with element
Definition array.h:1471
IndexT FindIndex(const TYPE &elm, const IndexT start=0) const
find identical element in array, return index, InvalidIndex if not found
Definition array.h:1395
Iterator End() const
return iterator to end of array
Definition array.h:1346
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:885
~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:1371
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:1446
bool operator!=(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs) const
inequality operator
Definition array.h:1024
TYPE * Iterator
define iterator
Definition array.h:64
void EraseFront()
erase front
Definition array.h:1199
TYPE & Back() const
return reference to last element
Definition array.h:1047
IndexT InsertAtEndOfIdenticalRange(IndexT startIndex, TYPE &&elm)
insert rvalue element at the first non-identical position, return index of inclusion position
Definition array.h:1905
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:954
void Clear()
clear array (calls destructors)
Definition array.h:1288
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:1892
ConstIterator ConstEnd() const
return const iterator to end of array
Definition array.h:1356
constexpr SizeT TypeSize() const
Returns sizeof(TYPE).
Definition array.h:1810
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:1166
IndexT BinarySearchIndex(typename std::enable_if< true, const KEYTYPE & >::type elm) const
do a binary search using a specific key type
Definition array.h:1657
void Sort()
sort the array
Definition array.h:1521
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:1535
void Append(TYPE &&elm)
append an element which is being forwarded
Definition array.h:790
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:966
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:1560
void Append(const TYPE &first, const ELEM_TYPE &... elements)
Append multiple elements to the end of the array.
Definition array.h:1415
TYPE & operator[](IndexT index)
[] operator
Definition array.h:981
Iterator begin() const
for range-based iteration
Definition array.h:1831
Iterator EraseSwap(Iterator iter)
erase element at iterator, fill gap by swapping in last element, destroys sorting!
Definition array.h:1152
TYPE & Emplace()
Emplace item (create new item and return reference).
Definition array.h:866
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:1304
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:1070
IndexT InsertSorted(const TYPE &elm)
insert element into sorted array, return index where element was included
Definition array.h:1941
void AppendArray(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs)
append the contents of an array to this array
Definition array.h:815
void EraseIndex(IndexT index)
erase element at index, keep sorting intact
Definition array.h:1090
static const SizeT MaxGrowSize
Definition array.h:262
const SizeT ByteSize() const
return the byte size of the array.
Definition array.h:944
void EraseIndexSwap(IndexT index)
erase element at index, fill gap by swapping in last element, destroys sorting!
Definition array.h:1112
TYPE PopFront()
Pop front.
Definition array.h:1209
ConstIterator ConstBegin() const
return const iterator to beginning of array
Definition array.h:1336
_smallvector< TYPE, SMALL_VECTOR_SIZE > stackElements
Definition array.h:268
void resize(size_t size)
Definition array.h:1851
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:1241
size_t size() const
Definition array.h:1820
void CopyRange(TYPE *to, TYPE *from, SizeT num)
void Resize(SizeT num, ARGS... args)
Resize and fill new elements with arguments.
Definition array.h:1730
bool operator==(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs) const
equality operator
Definition array.h:996
ArrayT Difference(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs)
returns new array with elements which are not in rhs (slow!)
Definition array.h:1500
void EraseBack()
erase back
Definition array.h:1187
bool IsValidIndex(IndexT index) const
check if index is valid
Definition array.h:1080
IndexT InsertSorted(TYPE &&elm)
insert rvalue element into sorted array, return index where element was included
Definition array.h:1953
Iterator Begin() const
return iterator to beginning of array
Definition array.h:1326
bool IsSorted() const
test if the array is sorted, this is a slow operation!
Definition array.h:1868
IndexT BinarySearchIndex(const TYPE &elm) const
do a binary search, requires a sorted array
Definition array.h:1597
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:1711
void QuickSortWithFunc(int(*func)(const void *lhs, const void *rhs))
quick sort the array
Definition array.h:1576
Array()
constructor with default parameters
Definition array.h:275
void Free()
free memory and reset size
Definition array.h:1315
const SizeT Size() const
get number of elements in array
Definition array.h:934
void AppendArray(const TYPE *arr, const SizeT count)
append from C array
Definition array.h:837
void clear() noexcept
Definition array.h:1769
TYPE & Front() const
return reference to first element
Definition array.h:1034
TYPE PopBack()
Pop back.
Definition array.h:1224
Iterator Erase(Iterator iter)
erase element pointed to by iterator, keep sorting intact
Definition array.h:1137
void Fit()
Fit the size of the array to the amount of elements.
Definition array.h:1779
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:58
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:2051
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
ptrdiff PtrDiff
Definition types.h:46
int SizeT
Definition types.h:42
int IndexT
Definition types.h:41