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 n_assert(this->elements != nullptr);
1495 std::sort(this->Begin(), this->End());
1496}
1497
1498//------------------------------------------------------------------------------
1502template <class TYPE, int SMALL_VECTOR_SIZE>
1503void
1505{
1506 n_assert(this->Size() > 0);
1507 n_assert(this->elements != nullptr);
1508 std::qsort(
1509 this->Begin(),
1510 this->Size(),
1511 sizeof(TYPE),
1512 [](const void* a, const void* b)
1513 {
1514 TYPE arg1 = *static_cast<const TYPE*>(a);
1515 TYPE arg2 = *static_cast<const TYPE*>(b);
1516 return (arg1 > arg2) - (arg1 < arg2);
1517 }
1518 );
1519}
1520
1521//------------------------------------------------------------------------------
1524template<class TYPE, int SMALL_VECTOR_SIZE>
1525void
1526Util::Array<TYPE, SMALL_VECTOR_SIZE>::SortWithFunc(bool (*func)(const TYPE& lhs, const TYPE& rhs))
1527{
1528 n_assert(func != nullptr);
1529 n_assert(this->Size() > 0);
1530 n_assert(this->elements != nullptr);
1531 std::sort(this->Begin(), this->End(), func);
1532}
1533
1534//------------------------------------------------------------------------------
1537template <class TYPE, int SMALL_VECTOR_SIZE>
1538void
1539Array<TYPE, SMALL_VECTOR_SIZE>::QuickSortWithFunc(int (*func)(const void* lhs, const void* rhs))
1540{
1541 n_assert(func != nullptr);
1542 n_assert(this->Size() > 0);
1543 n_assert(this->elements != nullptr);
1544 std::qsort(
1545 this->Begin(),
1546 this->Size(),
1547 sizeof(TYPE),
1548 func
1549 );
1550}
1551
1552//------------------------------------------------------------------------------
1557template<class TYPE, int SMALL_VECTOR_SIZE>
1558IndexT
1560{
1561 SizeT num = this->Size();
1562 if (num > 0)
1563 {
1564 IndexT half;
1565 IndexT lo = 0;
1566 IndexT hi = num - 1;
1567 IndexT mid;
1568 while (lo <= hi)
1569 {
1570 if (0 != (half = num/2))
1571 {
1572 mid = lo + ((num & 1) ? half : (half - 1));
1573 if (elm < this->elements[mid])
1574 {
1575 hi = mid - 1;
1576 num = num & 1 ? half : half - 1;
1577 }
1578 else if (elm > this->elements[mid])
1579 {
1580 lo = mid + 1;
1581 num = half;
1582 }
1583 else
1584 {
1585 return mid;
1586 }
1587 }
1588 else if (0 != num)
1589 {
1590 if (elm != this->elements[lo])
1591 {
1592 return InvalidIndex;
1593 }
1594 else
1595 {
1596 return lo;
1597 }
1598 }
1599 else
1600 {
1601 break;
1602 }
1603 }
1604 }
1605 return InvalidIndex;
1606}
1607
1608//------------------------------------------------------------------------------
1617template<class TYPE, int SMALL_VECTOR_SIZE>
1618template<typename KEYTYPE> inline IndexT
1619Array<TYPE, SMALL_VECTOR_SIZE>::BinarySearchIndex(typename std::enable_if<true, const KEYTYPE&>::type elm) const
1620{
1621 SizeT num = this->Size();
1622 if (num > 0)
1623 {
1624 IndexT half;
1625 IndexT lo = 0;
1626 IndexT hi = num - 1;
1627 IndexT mid;
1628 while (lo <= hi)
1629 {
1630 if (0 != (half = num / 2))
1631 {
1632 mid = lo + ((num & 1) ? half : (half - 1));
1633 if (this->elements[mid] > elm)
1634 {
1635 hi = mid - 1;
1636 num = num & 1 ? half : half - 1;
1637 }
1638 else if (this->elements[mid] < elm)
1639 {
1640 lo = mid + 1;
1641 num = half;
1642 }
1643 else
1644 {
1645 return mid;
1646 }
1647 }
1648 else if (0 != num)
1649 {
1650 if (this->elements[lo] != elm)
1651 {
1652 return InvalidIndex;
1653 }
1654 else
1655 {
1656 return lo;
1657 }
1658 }
1659 else
1660 {
1661 break;
1662 }
1663 }
1664 }
1665 return InvalidIndex;
1666}
1667
1668//------------------------------------------------------------------------------
1671template<class TYPE, int SMALL_VECTOR_SIZE>
1672void
1674{
1675 if (num < this->count)
1676 {
1677 this->DestroyRange(num, this->count);
1678 }
1679 else if (num > this->capacity)
1680 {
1681 this->GrowTo(num);
1682 }
1683
1684 this->count = num;
1685}
1686
1687//------------------------------------------------------------------------------
1690template<class TYPE, int SMALL_VECTOR_SIZE>
1691template<typename ...ARGS>
1693{
1694 if (num < this->count)
1695 {
1696 this->DestroyRange(num, this->count);
1697 }
1698 else
1699 {
1700 if (num > this->capacity)
1701 {
1702 this->GrowTo(num);
1703 }
1704 for (IndexT i = this->count; i < num; i++)
1705 {
1706 this->elements[i] = TYPE(args...);
1707 }
1708 }
1709
1710 this->count = num;
1711}
1712
1713//------------------------------------------------------------------------------
1716template<class TYPE, int SMALL_VECTOR_SIZE>
1718{
1719 if (num > this->capacity)
1720 {
1721 this->GrowTo(num);
1722 }
1723 this->count = Math::max(this->count, num);
1724}
1725
1726//------------------------------------------------------------------------------
1729template<class TYPE, int SMALL_VECTOR_SIZE>
1730void
1732{
1733 this->Clear();
1734}
1735
1736//------------------------------------------------------------------------------
1739template<class TYPE, int SMALL_VECTOR_SIZE>
1740inline void
1742{
1743 TYPE* newArray = ArrayAlloc<TYPE>(this->count);
1744 if (this->elements)
1745 {
1746 this->MoveRange(newArray, this->elements, this->count);
1747 if (this->elements != this->stackElements.data())
1748 ArrayFree(this->capacity, this->elements);
1749 }
1750 this->elements = newArray;
1751
1752 this->capacity = this->count;
1753}
1754
1755//------------------------------------------------------------------------------
1758template<class TYPE, int SMALL_VECTOR_SIZE>
1759inline constexpr SizeT
1761{
1762 return sizeof(TYPE);
1763}
1764
1765//------------------------------------------------------------------------------
1768template<class TYPE, int SMALL_VECTOR_SIZE>
1769size_t
1771{
1772 return this->count;
1773}
1774
1775
1776//------------------------------------------------------------------------------
1779template<class TYPE, int SMALL_VECTOR_SIZE>
1782{
1783 return this->elements;
1784}
1785
1786//------------------------------------------------------------------------------
1789template<class TYPE, int SMALL_VECTOR_SIZE>
1792{
1793 return this->elements + this->count;
1794}
1795
1796//------------------------------------------------------------------------------
1799template<class TYPE, int SMALL_VECTOR_SIZE>
1800void
1802{
1803 if (static_cast<SizeT>(s) > this->capacity)
1804 {
1805 this->GrowTo(static_cast<SizeT>(s));
1806 }
1807 this->count = static_cast<SizeT>(s);
1808}
1809
1810
1811//------------------------------------------------------------------------------
1816template<class TYPE, int SMALL_VECTOR_SIZE>
1817bool
1819{
1820 if (this->count > 1)
1821 {
1822 IndexT i;
1823 for (i = 0; i < this->count - 1; i++)
1824 {
1825 if (this->elements[i] > this->elements[i + 1])
1826 {
1827 return false;
1828 }
1829 }
1830 }
1831 return true;
1832}
1833
1834//------------------------------------------------------------------------------
1840template<class TYPE, int SMALL_VECTOR_SIZE>
1841IndexT
1843{
1844 return this->InsertAtEndOfIdenticalRangeInternal(startIndex, elm);
1845}
1846
1847//------------------------------------------------------------------------------
1853template<class TYPE, int SMALL_VECTOR_SIZE>
1854IndexT
1856{
1857 return this->InsertAtEndOfIdenticalRangeInternal(startIndex, std::move(elm));
1858}
1859
1860//------------------------------------------------------------------------------
1863template<class TYPE, int SMALL_VECTOR_SIZE>
1864template<typename ELEM>
1865IndexT
1867{
1868 const TYPE& probe = elm;
1869 IndexT i = startIndex + 1;
1870 for (; i < this->count; i++)
1871 {
1872 if (this->elements[i] != probe)
1873 {
1874 this->InsertInternal(i, std::forward<ELEM>(elm));
1875 return i;
1876 }
1877 }
1878
1879 // fallthrough: new element needs to be appended to end
1880 this->Append(std::forward<ELEM>(elm));
1881 return (this->Size() - 1);
1882}
1883
1884//------------------------------------------------------------------------------
1889template<class TYPE, int SMALL_VECTOR_SIZE>
1890IndexT
1892{
1893 return this->InsertSortedInternal(elm);
1894}
1895
1896//------------------------------------------------------------------------------
1901template<class TYPE, int SMALL_VECTOR_SIZE>
1902IndexT
1904{
1905 return this->InsertSortedInternal(std::move(elm));
1906}
1907
1908//------------------------------------------------------------------------------
1911template<class TYPE, int SMALL_VECTOR_SIZE>
1912template<typename ELEM>
1913IndexT
1915{
1916 const TYPE& probe = elm;
1917 SizeT num = this->Size();
1918 if (num == 0)
1919 {
1920 // array is currently empty
1921 this->Append(std::forward<ELEM>(elm));
1922 return this->Size() - 1;
1923 }
1924 else
1925 {
1926 IndexT half;
1927 IndexT lo = 0;
1928 IndexT hi = num - 1;
1929 IndexT mid;
1930 while (lo <= hi)
1931 {
1932 if (0 != (half = num/2))
1933 {
1934 mid = lo + ((num & 1) ? half : (half - 1));
1935 if (probe < this->elements[mid])
1936 {
1937 hi = mid - 1;
1938 num = num & 1 ? half : half - 1;
1939 }
1940 else if (probe > this->elements[mid])
1941 {
1942 lo = mid + 1;
1943 num = half;
1944 }
1945 else
1946 {
1947 // element already exists at [mid], append the
1948 // new element to the end of the range
1949 return this->InsertAtEndOfIdenticalRangeInternal(mid, std::forward<ELEM>(elm));
1950 }
1951 }
1952 else if (0 != num)
1953 {
1954 if (probe < this->elements[lo])
1955 {
1956 this->InsertInternal(lo, std::forward<ELEM>(elm));
1957 return lo;
1958 }
1959 else if (probe > this->elements[lo])
1960 {
1961 this->InsertInternal(lo + 1, std::forward<ELEM>(elm));
1962 return lo + 1;
1963 }
1964 else
1965 {
1966 // element already exists at [low], append
1967 // the new element to the end of the range
1968 return this->InsertAtEndOfIdenticalRangeInternal(lo, std::forward<ELEM>(elm));
1969 }
1970 }
1971 else
1972 {
1973 #if NEBULA_BOUNDSCHECKS
1974 n_assert(0 == lo);
1975 #endif
1976 this->InsertInternal(lo, std::forward<ELEM>(elm));
1977 return lo;
1978 }
1979 }
1980 if (probe < this->elements[lo])
1981 {
1982 this->InsertInternal(lo, std::forward<ELEM>(elm));
1983 return lo;
1984 }
1985 else if (probe > this->elements[lo])
1986 {
1987 this->InsertInternal(lo + 1, std::forward<ELEM>(elm));
1988 return lo + 1;
1989 }
1990 else
1991 {
1992 // can't happen(?)
1993 }
1994 }
1995 // can't happen
1996 n_error("Array::InsertSorted: Can't happen!");
1997 return InvalidIndex;
1998}
1999
2000template<class TYPE, int STACK_SIZE>
2002
2003} // namespace Util
2004//------------------------------------------------------------------------------
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:1717
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:1855
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:1842
ConstIterator ConstEnd() const
return const iterator to end of array
Definition array.h:1333
constexpr SizeT TypeSize() const
Returns sizeof(TYPE).
Definition array.h:1760
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:1619
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:1504
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:1526
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:1781
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:1891
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:1801
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:1770
void CopyRange(TYPE *to, TYPE *from, SizeT num)
void Resize(SizeT num, ARGS... args)
Resize and fill new elements with arguments.
Definition array.h:1692
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:1903
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:1818
IndexT BinarySearchIndex(const TYPE &elm) const
do a binary search, requires a sorted array
Definition array.h:1559
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:1673
void QuickSortWithFunc(int(*func)(const void *lhs, const void *rhs))
quick sort the array
Definition array.h:1539
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:1731
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:1741
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:221
__forceinline void MoveElements(const T *from, T *to, size_t numElements)
Move a chunk of memory, can handle overlapping regions.
Definition posixmemory.h:197
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 String.cs:6
Array< TYPE, STACK_SIZE > StackArray
Definition array.h:2001
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