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
39
40
41//------------------------------------------------------------------------------
42namespace Util
43{
44
45template<class TYPE, int STACK_SIZE>
47{
48 TYPE* data() { return stackElements; }
49private:
50 TYPE stackElements[STACK_SIZE];
51};
52
53template<class TYPE>
54struct _smallvector<TYPE, 0>
55{
56 TYPE* data() { return nullptr; }
57};
58
59template<class TYPE, int SMALL_VECTOR_SIZE = 0> class Array
60{
61public:
63 typedef TYPE* Iterator;
64 typedef const TYPE* ConstIterator;
65
67
71 Array(SizeT initialCapacity, SizeT initialGrow);
73 Array(SizeT initialSize, SizeT initialGrow, const TYPE& initialValue);
75 Array(const ArrayT& rhs);
77 Array(ArrayT&& rhs) noexcept;
79 Array(std::initializer_list<TYPE> list);
81 Array(std::nullptr_t);
83 Array(const TYPE* const buf, SizeT num);
86
92 TYPE& operator[](IndexT index) const;
94 TYPE& operator[](IndexT index);
100 template<typename T> T As() const;
101
103 TYPE& Get(IndexT index) const;
104
106 template <typename ...ELEM_TYPE>
107 void Append(const TYPE& first, const ELEM_TYPE&... elements);
109 void Append(const TYPE& elm);
111 void Append(TYPE&& elm);
115 void AppendArray(const TYPE* arr, const SizeT count);
117 TYPE& Emplace();
121 void Reserve(SizeT num);
122
124 const SizeT Size() const;
126 const SizeT ByteSize() const;
128 const SizeT Capacity() const;
130 TYPE& Front() const;
132 TYPE& Back() const;
134 bool IsEmpty() const;
136 bool IsValidIndex(IndexT index) const;
138 void EraseIndex(IndexT index);
148 void EraseBack();
152 TYPE PopFront();
154 TYPE PopBack();
156 void Insert(IndexT index, const TYPE& elm);
158 IndexT InsertSorted(const TYPE& elm);
160 IndexT InsertAtEndOfIdenticalRange(IndexT startIndex, const TYPE& elm);
162 bool IsSorted() const;
164 void Clear();
166 void Reset();
168 void Free();
174 Iterator End() const;
178 Iterator Find(const TYPE& elm, const IndexT start = 0) const;
180 IndexT FindIndex(const TYPE& elm, const IndexT start = 0) const;
182 template <typename KEYTYPE> IndexT FindIndex(typename std::enable_if<true, const KEYTYPE&>::type elm, const IndexT start = 0) const;
184 void Fill(IndexT first, SizeT num, const TYPE& elm);
190 void Sort();
192 void QuickSort();
194 void SortWithFunc(bool (*func)(const TYPE& lhs, const TYPE& rhs));
196 void QuickSortWithFunc(int (*func)(const void* lhs, const void* rhs));
198 IndexT BinarySearchIndex(const TYPE& elm) const;
200 template <typename KEYTYPE> IndexT BinarySearchIndex(typename std::enable_if<true, const KEYTYPE&>::type elm) const;
201
203 void Resize(SizeT num);
205 template <typename ...ARGS> void Resize(SizeT num, ARGS... args);
207 void Extend(SizeT num);
209 void Fit();
210
212 constexpr SizeT TypeSize() const;
213
216 Iterator end() const;
217 size_t size() const;
218 void resize(size_t size);
219 void clear() noexcept;
220 void push_back(const TYPE& item);
221
223 void Grow();
224protected:
225 template<class T, bool S>
226 friend class FixedArray;
227
229 void Destroy(TYPE* elm);
231 void Copy(const Array<TYPE, SMALL_VECTOR_SIZE>& src);
233 void Delete();
235 void GrowTo(SizeT newCapacity);
237 void Move(IndexT fromIndex, IndexT toIndex);
239 void DestroyRange(IndexT fromIndex, IndexT toIndex);
241 void CopyRange(TYPE* to, TYPE* from, SizeT num);
243 void MoveRange(TYPE* to, TYPE* from, SizeT num);
244
245 static const SizeT MinGrowSize = 16;
246 static const SizeT MaxGrowSize = 65536; // FIXME: big grow size needed for mesh tools
247 SizeT grow; // grow by this number of elements if array exhausted
248 SizeT capacity; // number of elements allocated
249 SizeT count; // number of elements in array
250 TYPE* elements; // pointer to element array
251
252 _smallvector<TYPE, SMALL_VECTOR_SIZE> stackElements;
253};
254
255//------------------------------------------------------------------------------
258template<class TYPE, int SMALL_VECTOR_SIZE>
259Array<TYPE, SMALL_VECTOR_SIZE>::Array() :
260 grow(16),
261 capacity(SMALL_VECTOR_SIZE),
262 count(0),
263 elements(this->stackElements.data())
264{
265}
266
267//------------------------------------------------------------------------------
270template<class TYPE, int SMALL_VECTOR_SIZE>
272 grow(_grow),
273 capacity(SMALL_VECTOR_SIZE),
274 count(0),
275 elements(this->stackElements.data())
276{
277 if (0 == this->grow)
278 {
279 this->grow = 16;
280 }
281 this->GrowTo(_capacity);
282}
283
284//------------------------------------------------------------------------------
287template<class TYPE, int SMALL_VECTOR_SIZE>
288Array<TYPE, SMALL_VECTOR_SIZE>::Array(SizeT initialSize, SizeT _grow, const TYPE& initialValue) :
289 grow(_grow),
290 capacity(SMALL_VECTOR_SIZE),
291 count(0),
292 elements(stackElements.data())
293{
294 if (0 == this->grow)
295 {
296 this->grow = 16;
297 }
298
299 this->GrowTo(initialSize);
300 this->count = initialSize;
301 IndexT i;
302 for (i = 0; i < initialSize; i++)
303 {
304 this->elements[i] = initialValue;
305 }
306}
307
308//------------------------------------------------------------------------------
311template<class TYPE, int SMALL_VECTOR_SIZE>
312Array<TYPE, SMALL_VECTOR_SIZE>::Array(const TYPE* const buf, SizeT num) :
313 grow(16),
314 capacity(SMALL_VECTOR_SIZE),
315 count(0),
316 elements(stackElements.data())
317{
318 static_assert(std::is_trivially_copyable<TYPE>::value, "TYPE is not trivially copyable; Util::Array cannot be constructed from pointer of TYPE.");
319 this->GrowTo(num);
320 this->count = num;
321 const SizeT bytes = num * sizeof(TYPE);
322 Memory::Copy(buf, this->elements, bytes);
323}
324
325//------------------------------------------------------------------------------
328template<class TYPE, int SMALL_VECTOR_SIZE>
329Array<TYPE, SMALL_VECTOR_SIZE>::Array(std::initializer_list<TYPE> list) :
330 grow(16),
331 capacity(SMALL_VECTOR_SIZE),
332 count(0),
333 elements(stackElements.data())
334{
335 this->GrowTo((SizeT)list.size());
336 this->count = (SizeT)list.size();
337 IndexT i;
338 for (i = 0; i < this->count; i++)
339 {
340 this->elements[i] = list.begin()[i];
341 }
342}
343
344//------------------------------------------------------------------------------
347template<class TYPE, int SMALL_VECTOR_SIZE>
349 grow(16),
350 capacity(SMALL_VECTOR_SIZE),
351 count(0),
352 elements(stackElements.data())
353{
354}
355
356//------------------------------------------------------------------------------
359template<class TYPE, int SMALL_VECTOR_SIZE>
361 grow(16),
362 capacity(SMALL_VECTOR_SIZE),
363 count(0),
364 elements(this->stackElements.data())
365{
366 this->Copy(rhs);
367}
368
369//------------------------------------------------------------------------------
372template<class TYPE, int SMALL_VECTOR_SIZE>
374 grow(rhs.grow),
375 capacity(rhs.capacity),
376 count(rhs.count),
377 elements(this->stackElements.data())
378{
379 // If data is on the stack, copy data over
380 if (rhs.capacity <= SMALL_VECTOR_SIZE)
381 {
382 for (IndexT i = 0; i < rhs.capacity; i++)
383 this->elements[i] = rhs.elements[i];
384 }
385 else
386 {
387 // Otherwise, exchange pointers and invalidate
388 this->elements = rhs.elements;
389 rhs.elements = rhs.stackElements.data();
390 }
391 rhs.count = 0;
392 rhs.capacity = SMALL_VECTOR_SIZE;
393}
394
395//------------------------------------------------------------------------------
398template<class TYPE, int SMALL_VECTOR_SIZE>
399void
401{
402 #if NEBULA_BOUNDSCHECKS
403 // Make sure array is either empty, or stack array before copy
404 n_assert(this->stackElements.data() == this->elements);
405 #endif
406
407 this->GrowTo(src.capacity);
408 this->grow = src.grow;
409 this->count = src.count;
410 IndexT i;
411 for (i = 0; i < this->count; i++)
412 {
413 this->elements[i] = src.elements[i];
414 }
415}
416
417//------------------------------------------------------------------------------
420template<class TYPE, int SMALL_VECTOR_SIZE>
421void
423{
424 this->grow = 16;
425
426 if (this->capacity > 0)
427 {
428 if (this->elements != this->stackElements.data())
429 {
430 ArrayFree(this->capacity, this->elements);
431 }
432 else
433 {
434 // If in small vector, run destructor
435 this->DestroyRange(0, this->count);
436 }
437 }
438 this->elements = this->stackElements.data();
439 this->count = 0;
440 this->capacity = SMALL_VECTOR_SIZE;
441}
442
443//------------------------------------------------------------------------------
446template<class TYPE, int SMALL_VECTOR_SIZE> void
448{
449 elm->~TYPE();
450}
451
452//------------------------------------------------------------------------------
455template<class TYPE, int SMALL_VECTOR_SIZE>
457{
458 this->Delete();
459}
460
461//------------------------------------------------------------------------------
464template<class TYPE, int SMALL_VECTOR_SIZE> void
466{
467 this->Delete();
468 this->grow = _grow;
469 this->capacity = _capacity;
470 this->count = _capacity;
471 if (this->capacity > 0)
472 {
473 this->GrowTo(this->capacity);
474 }
475 else
476 {
477 this->elements = 0;
478 }
479}
480
481//------------------------------------------------------------------------------
484template<class TYPE, int SMALL_VECTOR_SIZE> void
486{
487 if (this != &rhs)
488 {
489 if ((this->capacity > 0) && (rhs.count <= this->capacity))
490 {
491 // source array fits into our capacity, copy in place
492 n_assert(0 != this->elements);
493
494 this->CopyRange(this->elements, rhs.elements, rhs.count);
495 if (rhs.count < this->count)
496 {
497 this->DestroyRange(rhs.count, this->count);
498 }
499 this->grow = rhs.grow;
500 this->count = rhs.count;
501 }
502 else
503 {
504 // source array doesn't fit into our capacity, need to reallocate
505 this->Delete();
506 this->Copy(rhs);
507 }
508 }
509}
510
511//------------------------------------------------------------------------------
514template<class TYPE, int SMALL_VECTOR_SIZE> void
516{
517 if (this != &rhs)
518 {
519 this->Delete();
520
521 // If rhs is not using stack, simply reassign pointers
522 if (rhs.elements != rhs.stackElements.data())
523 {
524 this->elements = rhs.elements;
525 rhs.elements = nullptr;
526 }
527 else
528 {
529 // Otherwise, move every element over to the stack of this array
530 this->MoveRange(this->elements, rhs.elements, rhs.count);
531 }
532
533 this->grow = rhs.grow;
534 this->count = rhs.count;
535 this->capacity = rhs.capacity;
536 rhs.count = 0;
537 rhs.capacity = 0;
538 }
539}
540
541//------------------------------------------------------------------------------
544template<class TYPE, int SMALL_VECTOR_SIZE> void
546{
547 if (newCapacity > SMALL_VECTOR_SIZE)
548 {
549 TYPE* newArray = ArrayAlloc<TYPE>(newCapacity);
550 if (this->elements)
551 {
552 this->MoveRange(newArray, this->elements, this->count);
553
554 // discard old array if not the stack array
555 if (this->elements != this->stackElements.data())
556 ArrayFree(this->capacity, this->elements);
557 }
558 this->elements = newArray;
559 this->capacity = newCapacity;
560 }
561}
562
563//------------------------------------------------------------------------------
566template<class TYPE, int SMALL_VECTOR_SIZE>
567void
569{
570 #if NEBULA_BOUNDSCHECKS
571 n_assert(this->grow > 0);
572 #endif
573
574 SizeT growToSize;
575 if (0 == this->capacity)
576 {
577 growToSize = this->grow;
578 }
579 else
580 {
581 // grow by half of the current capacity, but never more then MaxGrowSize
582 SizeT growBy = this->capacity >> 1;
583 if (growBy == 0)
584 {
585 growBy = MinGrowSize;
586 }
587 else if (growBy > MaxGrowSize)
588 {
589 growBy = MaxGrowSize;
590 }
591 growToSize = this->capacity + growBy;
592 }
593 this->GrowTo(growToSize);
594}
595
596//------------------------------------------------------------------------------
601template<class TYPE, int SMALL_VECTOR_SIZE>
602void
604{
605 #if NEBULA_BOUNDSCHECKS
606 n_assert(this->elements);
607 n_assert(fromIndex < this->count);
608 #endif
609
610 // nothing to move?
611 if (fromIndex == toIndex)
612 {
613 return;
614 }
615
616 // compute number of elements to move
617 SizeT num = this->count - fromIndex;
618
619 // check if array needs to grow
620 SizeT neededSize = toIndex + num;
621 while (neededSize > this->capacity)
622 {
623 this->Grow();
624 }
625
626 if (fromIndex > toIndex)
627 {
628 // this is a backward move
629 this->MoveRange(&this->elements[toIndex], &this->elements[fromIndex], num);
630 this->DestroyRange(fromIndex + num - 1, this->count);
631 }
632 else
633 {
634 // this is a forward move
635 int i; // NOTE: this must remain signed for the following loop to work!!!
636 for (i = num - 1; i >= 0; --i)
637 {
638 this->elements[toIndex + i] = this->elements[fromIndex + i];
639 }
640
641 // destroy freed elements
642 this->DestroyRange(fromIndex, toIndex);
643 }
644
645 // adjust array size
646 this->count = toIndex + num;
647}
648
649//------------------------------------------------------------------------------
652template<class TYPE, int SMALL_VECTOR_SIZE>
653inline void
655{
656 if constexpr (!std::is_trivially_destructible<TYPE>::value)
657 {
658 for (IndexT i = fromIndex; i < toIndex; i++)
659 {
660 this->Destroy(&(this->elements[i]));
661 }
662 }
663 else
664 {
665 Memory::Clear((void*)&this->elements[fromIndex], sizeof(TYPE) * (toIndex - fromIndex));
666 }
667}
668
669//------------------------------------------------------------------------------
672template<class TYPE, int SMALL_VECTOR_SIZE>
673inline void
675{
676 // this is a backward move
677 if constexpr (!std::is_trivially_copyable<TYPE>::value)
678 {
679 IndexT i;
680 for (i = 0; i < num; i++)
681 {
682 to[i] = from[i];
683 }
684 }
685 else
686 {
687 Memory::CopyElements(from, to, num);
688 }
689}
690
691//------------------------------------------------------------------------------
694template<class TYPE, int SMALL_VECTOR_SIZE>
695inline void
697{
698 // copy over contents
699 if constexpr (!std::is_trivially_move_assignable<TYPE>::value && std::is_move_assignable<TYPE>::value)
700 {
701 IndexT i;
702 for (i = 0; i < num; i++)
703 {
704 to[i] = std::move(from[i]);
705 }
706 }
707 else
708 {
709 Memory::MoveElements(from, to, num);
710 }
711}
712
713//------------------------------------------------------------------------------
716template<class TYPE, int SMALL_VECTOR_SIZE>
717inline TYPE&
719{
720#if NEBULA_BOUNDSCHECKS
721 n_assert(this->elements != nullptr);
722 n_assert(this->capacity > index);
723#endif
724 return this->elements[index];
725}
726
727//------------------------------------------------------------------------------
730template<class TYPE, int SMALL_VECTOR_SIZE>
731void
733{
734 // grow allocated space if exhausted
735 if (this->count == this->capacity)
736 {
737 this->Grow();
738 }
739 #if NEBULA_BOUNDSCHECKS
740 n_assert(this->elements);
741 #endif
742 this->elements[this->count++] = elm;
743}
744
745//------------------------------------------------------------------------------
748template<class TYPE, int SMALL_VECTOR_SIZE>
749void
751{
752 // grow allocated space if exhausted
753 if (this->count == this->capacity)
754 {
755 this->Grow();
756 }
757#if NEBULA_BOUNDSCHECKS
758 n_assert(this->elements);
759#endif
760 this->elements[this->count++] = std::move(elm);
761}
762
763//------------------------------------------------------------------------------
766template<class TYPE, int SMALL_VECTOR_SIZE>
767void
769{
770 SizeT neededCapacity = this->count + rhs.count;
771 if (neededCapacity > this->capacity)
772 {
773 this->GrowTo(neededCapacity);
774 }
775
776 // forward elements from array
777 IndexT i;
778 for (i = 0; i < rhs.count; i++)
779 {
780 this->elements[this->count + i] = rhs.elements[i];
781 }
782 this->count += rhs.count;
783}
784
785//------------------------------------------------------------------------------
788template<class TYPE, int SMALL_VECTOR_SIZE>
789void
791{
792 SizeT neededCapacity = this->count + count;
793 if (neededCapacity > this->capacity)
794 {
795 this->GrowTo(neededCapacity);
796 }
797
798 // forward elements from array
799 IndexT i;
800 for (i = 0; i < count; i++)
801 {
802 this->elements[this->count + i] = arr[i];
803 }
804 this->count += count;
805}
806
807//------------------------------------------------------------------------------
810template<class TYPE, int SMALL_VECTOR_SIZE>
811TYPE&
813{
814 // grow allocated space if exhausted
815 if (this->count == this->capacity)
816 {
817 this->Grow();
818 }
819#if NEBULA_BOUNDSCHECKS
820 n_assert(this->elements);
821#endif
822 this->elements[this->count] = TYPE();
823 return this->elements[this->count++];
824}
825
826//------------------------------------------------------------------------------
829template<class TYPE, int SMALL_VECTOR_SIZE>
830TYPE*
832{
833 SizeT neededCapacity = this->count + count;
834 if (neededCapacity > this->capacity)
835 {
836 this->GrowTo(neededCapacity);
837 }
838
839 // forward elements from array
840 IndexT i;
841 for (i = 0; i < count; i++)
842 {
843 this->elements[this->count + i] = TYPE();
844 }
845 TYPE* first = &this->elements[this->count];
846 this->count += count;
847 return first;
848}
849
850//------------------------------------------------------------------------------
860template<class TYPE, int SMALL_VECTOR_SIZE>
861void
863{
864#if NEBULA_BOUNDSCHECKS
865 n_assert(num >= 0);
866#endif
867
868 SizeT neededCapacity = this->count + num;
869 if (neededCapacity > this->capacity)
870 {
871 this->GrowTo(neededCapacity);
872 }
873}
874
875//------------------------------------------------------------------------------
878template<class TYPE, int SMALL_VECTOR_SIZE>
879const SizeT
881{
882 return this->count;
883}
884
885//------------------------------------------------------------------------------
888template<class TYPE, int SMALL_VECTOR_SIZE>
889const SizeT
891{
892 return this->count * sizeof(TYPE);
893}
894
895//------------------------------------------------------------------------------
898template<class TYPE, int SMALL_VECTOR_SIZE>
899const SizeT
901{
902 return this->capacity;
903}
904
905//------------------------------------------------------------------------------
910template<class TYPE, int SMALL_VECTOR_SIZE>
911TYPE&
913{
914 #if NEBULA_BOUNDSCHECKS
915 n_assert(this->elements && (index < this->count) && (index >= 0));
916 #endif
917 return this->elements[index];
918}
919
920//------------------------------------------------------------------------------
925template<class TYPE, int SMALL_VECTOR_SIZE>
926TYPE&
928{
929#if NEBULA_BOUNDSCHECKS
930 n_assert(this->elements && (index < this->count) && (index >= 0));
931#endif
932 return this->elements[index];
933}
934
935//------------------------------------------------------------------------------
940template<class TYPE, int SMALL_VECTOR_SIZE>
941bool
943{
944 if (rhs.Size() == this->Size())
945 {
946 IndexT i;
947 SizeT num = this->Size();
948 for (i = 0; i < num; i++)
949 {
950 if (!(this->elements[i] == rhs.elements[i]))
951 {
952 return false;
953 }
954 }
955 return true;
956 }
957 else
958 {
959 return false;
960 }
961}
962
963//------------------------------------------------------------------------------
968template<class TYPE, int SMALL_VECTOR_SIZE>
969bool
971{
972 return !(*this == rhs);
973}
974
975//------------------------------------------------------------------------------
978template<class TYPE, int SMALL_VECTOR_SIZE>
979TYPE&
981{
982 #if NEBULA_BOUNDSCHECKS
983 n_assert(this->elements && (this->count > 0));
984 #endif
985 return this->elements[0];
986}
987
988//------------------------------------------------------------------------------
991template<class TYPE, int SMALL_VECTOR_SIZE>
992TYPE&
994{
995 #if NEBULA_BOUNDSCHECKS
996 n_assert(this->elements && (this->count > 0));
997 #endif
998 return this->elements[this->count - 1];
999}
1000
1001//------------------------------------------------------------------------------
1004template<class TYPE, int SMALL_VECTOR_SIZE>
1005void
1007{
1008 this->Append(item);
1009}
1010
1011//------------------------------------------------------------------------------
1014template<class TYPE, int SMALL_VECTOR_SIZE>
1015bool
1017{
1018 return (this->count == 0);
1019}
1020
1021//------------------------------------------------------------------------------
1024template<class TYPE, int SMALL_VECTOR_SIZE>
1025bool
1027{
1028 return this->elements && (index < this->count) && (index >= 0);
1029}
1030
1031//------------------------------------------------------------------------------
1034template<class TYPE, int SMALL_VECTOR_SIZE>
1035void
1037{
1038 #if NEBULA_BOUNDSCHECKS
1039 n_assert(this->elements && (index < this->count) && (index >= 0));
1040 #endif
1041 if (index == (this->count - 1))
1042 {
1043 // special case: last element
1044 this->EraseBack();
1045 }
1046 else
1047 {
1048 this->Move(index + 1, index);
1049 }
1050}
1051
1052//------------------------------------------------------------------------------
1056template<class TYPE, int SMALL_VECTOR_SIZE>
1057void
1059{
1060 #if NEBULA_BOUNDSCHECKS
1061 n_assert(this->elements && (index < this->count) && (index >= 0));
1062 #endif
1063
1064 // swap with last element, and destroy last element
1065 IndexT lastElementIndex = this->count - 1;
1066 if (index < lastElementIndex)
1067 {
1068 if constexpr (!std::is_trivially_move_assignable<TYPE>::value)
1069 this->elements[index] = std::move(this->elements[lastElementIndex]);
1070 else
1071 this->elements[index] = this->elements[lastElementIndex];
1072 }
1073 this->count--;
1074}
1075
1076//------------------------------------------------------------------------------
1079template<class TYPE, int SMALL_VECTOR_SIZE>
1082{
1083 #if NEBULA_BOUNDSCHECKS
1084 n_assert(this->elements && (iter >= this->elements) && (iter < (this->elements + this->count)));
1085 #endif
1086 this->EraseIndex(IndexT(iter - this->elements));
1087 return iter;
1088}
1089
1090//------------------------------------------------------------------------------
1094template<class TYPE, int SMALL_VECTOR_SIZE>
1097{
1098 #if NEBULA_BOUNDSCHECKS
1099 n_assert(this->elements && (iter >= this->elements) && (iter < (this->elements + this->count)));
1100 #endif
1101 this->EraseIndexSwap(IndexT(iter - this->elements));
1102 return iter;
1103}
1104
1105//------------------------------------------------------------------------------
1108template<class TYPE, int SMALL_VECTOR_SIZE>
1109void
1111{
1112 n_assert(end >= start);
1113 n_assert(end <= this->count);
1114 if (start == end)
1115 this->EraseIndex(start);
1116 else
1117 {
1118 // add 1 to end to remove and move including that element
1119 this->DestroyRange(start, end);
1120 SizeT numMove = this->count - end;
1121 this->MoveRange(&this->elements[start], &this->elements[end], numMove);
1122 this->count -= end - start;
1123 }
1124}
1125
1126//------------------------------------------------------------------------------
1129template<class TYPE, int SMALL_VECTOR_SIZE>
1130void
1132{
1133 n_assert(this->count > 0);
1134 if constexpr (!std::is_trivially_destructible<TYPE>::value)
1135 this->Destroy(&(this->elements[this->count - 1]));
1136 this->count--;
1137}
1138
1139//------------------------------------------------------------------------------
1142template<class TYPE, int SMALL_VECTOR_SIZE>
1143void
1145{
1146 this->EraseIndex(0);
1147}
1148
1149//------------------------------------------------------------------------------
1152template<class TYPE, int SMALL_VECTOR_SIZE>
1153inline TYPE
1155{
1156#if NEBULA_BOUNDSCHECKS
1157 n_assert(this->count > 0);
1158#endif
1159 TYPE ret = std::move(this->elements[0]);
1160 this->EraseIndex(0);
1161 return ret;
1162}
1163
1164//------------------------------------------------------------------------------
1167template<class TYPE, int SMALL_VECTOR_SIZE>
1168inline TYPE
1170{
1171#if NEBULA_BOUNDSCHECKS
1172 n_assert(this->count > 0);
1173#endif
1174 this->count--;
1175 return std::move(this->elements[this->count]);
1176}
1177
1178//------------------------------------------------------------------------------
1181template<class TYPE, int SMALL_VECTOR_SIZE>
1182void
1184{
1185 #if NEBULA_BOUNDSCHECKS
1186 n_assert(index <= this->count && (index >= 0));
1187 #endif
1188 if (index == this->count)
1189 {
1190 // special case: append element to back
1191 this->Append(elm);
1192 }
1193 else
1194 {
1195 this->Move(index, index + 1);
1196 this->elements[index] = elm;
1197 }
1198}
1199
1200//------------------------------------------------------------------------------
1205template<class TYPE, int SMALL_VECTOR_SIZE>
1206void
1208{
1209 if (this->count > 0)
1210 {
1211 this->DestroyRange(0, this->count);
1212 this->count = 0;
1213 }
1214}
1215
1216//------------------------------------------------------------------------------
1221template<class TYPE, int SMALL_VECTOR_SIZE>
1222void
1224{
1225 this->count = 0;
1226}
1227
1228//------------------------------------------------------------------------------
1232template<class TYPE, int SMALL_VECTOR_SIZE>
1233void
1235{
1236 this->Delete();
1237 this->grow = 16;
1238}
1239
1240//------------------------------------------------------------------------------
1243template<class TYPE, int SMALL_VECTOR_SIZE>
1246{
1247 return this->elements;
1248}
1249
1250//------------------------------------------------------------------------------
1253template<class TYPE, int SMALL_VECTOR_SIZE>
1256{
1257 return static_cast<Array<TYPE, SMALL_VECTOR_SIZE>::ConstIterator>(this->elements);
1258}
1259
1260//------------------------------------------------------------------------------
1263template<class TYPE, int SMALL_VECTOR_SIZE>
1266{
1267 return this->elements + this->count;
1268}
1269
1270//------------------------------------------------------------------------------
1273template<class TYPE, int SMALL_VECTOR_SIZE>
1276{
1277 return static_cast<Array<TYPE, SMALL_VECTOR_SIZE>::ConstIterator>(this->elements + this->count);
1278}
1279
1280//------------------------------------------------------------------------------
1288template<class TYPE, int SMALL_VECTOR_SIZE>
1290Array<TYPE, SMALL_VECTOR_SIZE>::Find(const TYPE& elm, const IndexT start) const
1291{
1292 n_assert(start <= this->count);
1293 IndexT index;
1294 for (index = start; index < this->count; index++)
1295 {
1296 if (this->elements[index] == elm)
1297 {
1298 return &(this->elements[index]);
1299 }
1300 }
1301 return 0;
1302}
1303
1304//------------------------------------------------------------------------------
1312template<class TYPE, int SMALL_VECTOR_SIZE>
1313IndexT
1314Array<TYPE, SMALL_VECTOR_SIZE>::FindIndex(const TYPE& elm, const IndexT start) const
1315{
1316 n_assert(start <= this->count);
1317 IndexT index;
1318 for (index = start; index < this->count; index++)
1319 {
1320 if (this->elements[index] == elm)
1321 {
1322 return index;
1323 }
1324 }
1325 return InvalidIndex;
1326}
1327
1328//------------------------------------------------------------------------------
1331template<class TYPE, int SMALL_VECTOR_SIZE>
1332template<typename ...ELEM_TYPE>
1333inline void
1334Array<TYPE, SMALL_VECTOR_SIZE>::Append(const TYPE& first, const ELEM_TYPE&... elements)
1335{
1336 // The plus one is for the first element
1337 const int size = sizeof...(elements) + 1;
1338 this->Reserve(size);
1339 TYPE res[size] = { first, elements... };
1340 for (IndexT i = 0; i < size; i++)
1341 {
1342 this->elements[this->count++] = res[i];
1343 }
1344}
1345
1346//------------------------------------------------------------------------------
1361template<class TYPE, int SMALL_VECTOR_SIZE>
1362template<typename KEYTYPE>
1363inline IndexT
1364Array<TYPE, SMALL_VECTOR_SIZE>::FindIndex(typename std::enable_if<true, const KEYTYPE&>::type elm, const IndexT start) const
1365{
1366 n_assert(start <= this->count);
1367 IndexT index;
1368 for (index = start; index < this->count; index++)
1369 {
1370 if (this->elements[index] == elm)
1371 {
1372 return index;
1373 }
1374 }
1375 return InvalidIndex;
1376}
1377
1378//------------------------------------------------------------------------------
1387template<class TYPE, int SMALL_VECTOR_SIZE>
1388void
1390{
1391 if ((first + num) > this->count)
1392 {
1393 this->GrowTo(first + num);
1394 this->count = first + num;
1395 }
1396
1397 IndexT i;
1398 for (i = first; i < (first + num); i++)
1399 {
1400 this->elements[i] = elm;
1401 }
1402}
1403
1404//------------------------------------------------------------------------------
1411template<class TYPE, int SMALL_VECTOR_SIZE>
1414{
1416 IndexT i;
1417 SizeT num = rhs.Size();
1418 for (i = 0; i < num; i++)
1419 {
1420 if (0 == this->Find(rhs[i]))
1421 {
1422 diff.Append(rhs[i]);
1423 }
1424 }
1425 return diff;
1426}
1427
1428//------------------------------------------------------------------------------
1432template<class TYPE, int SMALL_VECTOR_SIZE>
1433void
1435{
1436 std::sort(this->Begin(), this->End());
1437}
1438
1439//------------------------------------------------------------------------------
1443template <class TYPE, int SMALL_VECTOR_SIZE>
1444void
1446{
1447 std::qsort(
1448 this->Begin(),
1449 this->Size(),
1450 sizeof(TYPE),
1451 [](const void* a, const void* b)
1452 {
1453 TYPE arg1 = *static_cast<const TYPE*>(a);
1454 TYPE arg2 = *static_cast<const TYPE*>(b);
1455 return (arg1 > arg2) - (arg1 < arg2);
1456 }
1457 );
1458}
1459
1460//------------------------------------------------------------------------------
1463template<class TYPE, int SMALL_VECTOR_SIZE>
1464void
1465Util::Array<TYPE, SMALL_VECTOR_SIZE>::SortWithFunc(bool (*func)(const TYPE& lhs, const TYPE& rhs))
1466{
1467 std::sort(this->Begin(), this->End(), func);
1468}
1469
1470//------------------------------------------------------------------------------
1473template <class TYPE, int SMALL_VECTOR_SIZE>
1474void
1475Array<TYPE, SMALL_VECTOR_SIZE>::QuickSortWithFunc(int (*func)(const void* lhs, const void* rhs))
1476{
1477 std::qsort(
1478 this->Begin(),
1479 this->Size(),
1480 sizeof(TYPE),
1481 func
1482 );
1483}
1484
1485//------------------------------------------------------------------------------
1490template<class TYPE, int SMALL_VECTOR_SIZE>
1491IndexT
1493{
1494 SizeT num = this->Size();
1495 if (num > 0)
1496 {
1497 IndexT half;
1498 IndexT lo = 0;
1499 IndexT hi = num - 1;
1500 IndexT mid;
1501 while (lo <= hi)
1502 {
1503 if (0 != (half = num/2))
1504 {
1505 mid = lo + ((num & 1) ? half : (half - 1));
1506 if (elm < this->elements[mid])
1507 {
1508 hi = mid - 1;
1509 num = num & 1 ? half : half - 1;
1510 }
1511 else if (elm > this->elements[mid])
1512 {
1513 lo = mid + 1;
1514 num = half;
1515 }
1516 else
1517 {
1518 return mid;
1519 }
1520 }
1521 else if (0 != num)
1522 {
1523 if (elm != this->elements[lo])
1524 {
1525 return InvalidIndex;
1526 }
1527 else
1528 {
1529 return lo;
1530 }
1531 }
1532 else
1533 {
1534 break;
1535 }
1536 }
1537 }
1538 return InvalidIndex;
1539}
1540
1541//------------------------------------------------------------------------------
1550template<class TYPE, int SMALL_VECTOR_SIZE>
1551template<typename KEYTYPE> inline IndexT
1552Array<TYPE, SMALL_VECTOR_SIZE>::BinarySearchIndex(typename std::enable_if<true, const KEYTYPE&>::type elm) const
1553{
1554 SizeT num = this->Size();
1555 if (num > 0)
1556 {
1557 IndexT half;
1558 IndexT lo = 0;
1559 IndexT hi = num - 1;
1560 IndexT mid;
1561 while (lo <= hi)
1562 {
1563 if (0 != (half = num / 2))
1564 {
1565 mid = lo + ((num & 1) ? half : (half - 1));
1566 if (this->elements[mid] > elm)
1567 {
1568 hi = mid - 1;
1569 num = num & 1 ? half : half - 1;
1570 }
1571 else if (this->elements[mid] < elm)
1572 {
1573 lo = mid + 1;
1574 num = half;
1575 }
1576 else
1577 {
1578 return mid;
1579 }
1580 }
1581 else if (0 != num)
1582 {
1583 if (this->elements[lo] != elm)
1584 {
1585 return InvalidIndex;
1586 }
1587 else
1588 {
1589 return lo;
1590 }
1591 }
1592 else
1593 {
1594 break;
1595 }
1596 }
1597 }
1598 return InvalidIndex;
1599}
1600
1601//------------------------------------------------------------------------------
1604template<class TYPE, int SMALL_VECTOR_SIZE>
1605void
1607{
1608 if (num < this->count)
1609 {
1610 this->DestroyRange(num, this->count);
1611 }
1612 else if (num > this->capacity)
1613 {
1614 this->GrowTo(num);
1615 }
1616
1617 this->count = num;
1618}
1619
1620//------------------------------------------------------------------------------
1623template<class TYPE, int SMALL_VECTOR_SIZE>
1624template<typename ...ARGS>
1626{
1627 if (num < this->count)
1628 {
1629 this->DestroyRange(num, this->count);
1630 }
1631 else if (num > this->capacity)
1632 {
1633 SizeT oldCapacity = this->capacity;
1634 this->GrowTo(num);
1635 for (IndexT i = oldCapacity; i < this->capacity; i++)
1636 this->elements[i] = TYPE(args...);
1637 }
1638
1639 this->count = num;
1640}
1641
1642//------------------------------------------------------------------------------
1645template<class TYPE, int SMALL_VECTOR_SIZE>
1647{
1648 if (num > this->capacity)
1649 {
1650 this->GrowTo(num);
1651 this->count = num;
1652 }
1653}
1654
1655//------------------------------------------------------------------------------
1658template<class TYPE, int SMALL_VECTOR_SIZE>
1659void
1661{
1662 this->Clear();
1663}
1664
1665//------------------------------------------------------------------------------
1668template<class TYPE, int SMALL_VECTOR_SIZE>
1669inline void
1671{
1672 TYPE* newArray = ArrayAlloc<TYPE>(this->count);
1673 if (this->elements)
1674 {
1675 this->MoveRange(newArray, this->elements, this->count);
1676 if (this->elements != this->stackElements.data())
1677 ArrayFree(this->capacity, this->elements);
1678 }
1679 this->elements = newArray;
1680
1681 this->capacity = this->count;
1682}
1683
1684//------------------------------------------------------------------------------
1687template<class TYPE, int SMALL_VECTOR_SIZE>
1688inline constexpr SizeT
1690{
1691 return sizeof(TYPE);
1692}
1693
1694//------------------------------------------------------------------------------
1697template<class TYPE, int SMALL_VECTOR_SIZE>
1698size_t
1700{
1701 return this->count;
1702}
1703
1704
1705//------------------------------------------------------------------------------
1708template<class TYPE, int SMALL_VECTOR_SIZE>
1711{
1712 return this->elements;
1713}
1714
1715//------------------------------------------------------------------------------
1718template<class TYPE, int SMALL_VECTOR_SIZE>
1721{
1722 return this->elements + this->count;
1723}
1724
1725//------------------------------------------------------------------------------
1728template<class TYPE, int SMALL_VECTOR_SIZE>
1729void
1731{
1732 if (static_cast<SizeT>(s) > this->capacity)
1733 {
1734 this->GrowTo(static_cast<SizeT>(s));
1735 }
1736 this->count = static_cast<SizeT>(s);
1737}
1738
1739
1740//------------------------------------------------------------------------------
1745template<class TYPE, int SMALL_VECTOR_SIZE>
1746bool
1748{
1749 if (this->count > 1)
1750 {
1751 IndexT i;
1752 for (i = 0; i < this->count - 1; i++)
1753 {
1754 if (this->elements[i] > this->elements[i + 1])
1755 {
1756 return false;
1757 }
1758 }
1759 }
1760 return true;
1761}
1762
1763//------------------------------------------------------------------------------
1769template<class TYPE, int SMALL_VECTOR_SIZE>
1770IndexT
1772{
1773 IndexT i = startIndex + 1;
1774 for (; i < this->count; i++)
1775 {
1776 if (this->elements[i] != elm)
1777 {
1778 this->Insert(i, elm);
1779 return i;
1780 }
1781 }
1782
1783 // fallthrough: new element needs to be appended to end
1784 this->Append(elm);
1785 return (this->Size() - 1);
1786}
1787
1788//------------------------------------------------------------------------------
1793template<class TYPE, int SMALL_VECTOR_SIZE>
1794IndexT
1796{
1797 SizeT num = this->Size();
1798 if (num == 0)
1799 {
1800 // array is currently empty
1801 this->Append(elm);
1802 return this->Size() - 1;
1803 }
1804 else
1805 {
1806 IndexT half;
1807 IndexT lo = 0;
1808 IndexT hi = num - 1;
1809 IndexT mid;
1810 while (lo <= hi)
1811 {
1812 if (0 != (half = num/2))
1813 {
1814 mid = lo + ((num & 1) ? half : (half - 1));
1815 if (elm < this->elements[mid])
1816 {
1817 hi = mid - 1;
1818 num = num & 1 ? half : half - 1;
1819 }
1820 else if (elm > this->elements[mid])
1821 {
1822 lo = mid + 1;
1823 num = half;
1824 }
1825 else
1826 {
1827 // element already exists at [mid], append the
1828 // new element to the end of the range
1829 return this->InsertAtEndOfIdenticalRange(mid, elm);
1830 }
1831 }
1832 else if (0 != num)
1833 {
1834 if (elm < this->elements[lo])
1835 {
1836 this->Insert(lo, elm);
1837 return lo;
1838 }
1839 else if (elm > this->elements[lo])
1840 {
1841 this->Insert(lo + 1, elm);
1842 return lo + 1;
1843 }
1844 else
1845 {
1846 // element already exists at [low], append
1847 // the new element to the end of the range
1848 return this->InsertAtEndOfIdenticalRange(lo, elm);
1849 }
1850 }
1851 else
1852 {
1853 #if NEBULA_BOUNDSCHECKS
1854 n_assert(0 == lo);
1855 #endif
1856 this->Insert(lo, elm);
1857 return lo;
1858 }
1859 }
1860 if (elm < this->elements[lo])
1861 {
1862 this->Insert(lo, elm);
1863 return lo;
1864 }
1865 else if (elm > this->elements[lo])
1866 {
1867 this->Insert(lo + 1, elm);
1868 return lo + 1;
1869 }
1870 else
1871 {
1872 // can't happen(?)
1873 }
1874 }
1875 // can't happen
1876 n_error("Array::InsertSorted: Can't happen!");
1877 return InvalidIndex;
1878}
1879
1880template<class TYPE, int STACK_SIZE>
1882
1883} // namespace Util
1884//------------------------------------------------------------------------------
Definition half.h:20
Nebula's dynamic array class.
Definition array.h:60
Array(std::nullptr_t)
construct an empty fixed array
Definition array.h:348
void Move(IndexT fromIndex, IndexT toIndex)
move elements, grows array if needed
Definition array.h:603
void Extend(SizeT num)
Resize to fit the provided value, but don't shrink if the new size is smaller.
Definition array.h:1646
Array(SizeT initialCapacity, SizeT initialGrow)
constuctor with initial size and grow size
Definition array.h:271
void Reserve(SizeT num)
increase capacity to fit N more elements into the array.
Definition array.h:862
void Fill(IndexT first, SizeT num, const TYPE &elm)
fill array range with element
Definition array.h:1389
IndexT FindIndex(const TYPE &elm, const IndexT start=0) const
find identical element in array, return index, InvalidIndex if not found
Definition array.h:1314
void Destroy(TYPE *elm)
destroy an element (call destructor without freeing memory)
Definition array.h:447
Iterator End() const
return iterator to end of array
Definition array.h:1265
SizeT capacity
Definition array.h:248
SizeT count
Definition array.h:249
TYPE * EmplaceArray(const SizeT count)
Emplace range of items and return pointer to first.
Definition array.h:831
~Array()
destructor
Definition array.h:456
TYPE * Iterator
define iterator
Definition array.h:63
Iterator Find(const TYPE &elm, const IndexT start=0) const
find identical element in array, return iterator
Definition array.h:1290
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:1364
bool operator!=(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs) const
inequality operator
Definition array.h:970
void EraseFront()
erase front
Definition array.h:1144
TYPE & Back() const
return reference to last element
Definition array.h:993
void Copy(const Array< TYPE, SMALL_VECTOR_SIZE > &src)
copy content
Definition array.h:400
const SizeT Capacity() const
get overall allocated size of array in number of elements
Definition array.h:900
void Clear()
clear array (calls destructors)
Definition array.h:1207
TYPE * elements
Definition array.h:250
IndexT InsertAtEndOfIdenticalRange(IndexT startIndex, const TYPE &elm)
insert element at the first non-identical position, return index of inclusion position
Definition array.h:1771
ConstIterator ConstEnd() const
return const iterator to end of array
Definition array.h:1275
constexpr SizeT TypeSize() const
Returns sizeof(TYPE)
Definition array.h:1689
Array(std::initializer_list< TYPE > list)
constructor from initializer list
Definition array.h:329
void EraseRange(IndexT start, IndexT end)
erase range, excluding the element at end
Definition array.h:1110
IndexT BinarySearchIndex(typename std::enable_if< true, const KEYTYPE & >::type elm) const
do a binary search using a specific key type
Definition array.h:1552
void Sort()
sort the array
Definition array.h:1434
SizeT grow
Definition array.h:247
void operator=(Array< TYPE, SMALL_VECTOR_SIZE > &&rhs) noexcept
move operator
Definition array.h:515
void QuickSort()
quick sort the array
Definition array.h:1445
void Delete()
delete content
Definition array.h:422
void Append(TYPE &&elm)
append an element which is being forwarded
Definition array.h:750
void DestroyRange(IndexT fromIndex, IndexT toIndex)
destroy range of elements
Definition array.h:654
Iterator end() const
Definition array.h:1720
TYPE & operator[](IndexT index) const
[] operator
Definition array.h:912
static const SizeT MinGrowSize
Definition array.h:245
Array(ArrayT &&rhs) noexcept
move constructor
Definition array.h:373
void SortWithFunc(bool(*func)(const TYPE &lhs, const TYPE &rhs))
sort with custom function
void Append(const TYPE &first, const ELEM_TYPE &... elements)
Append multiple elements to the end of the array.
Definition array.h:1334
TYPE & operator[](IndexT index)
[] operator
Definition array.h:927
Iterator begin() const
for range-based iteration
Definition array.h:1710
Iterator EraseSwap(Iterator iter)
erase element at iterator, fill gap by swapping in last element, destroys sorting!
Definition array.h:1096
TYPE & Emplace()
Emplace item (create new item and return reference)
Definition array.h:812
Array(const TYPE *const buf, SizeT num)
constructor from TYPE pointer and size.
Definition array.h:312
void Reset()
reset array (does NOT call destructors)
Definition array.h:1223
void Realloc(SizeT capacity, SizeT grow)
clear contents and preallocate with new attributes
Definition array.h:465
T As() const
convert to "anything"
bool IsEmpty() const
return true if array empty
Definition array.h:1016
IndexT InsertSorted(const TYPE &elm)
insert element into sorted array, return index where element was included
Definition array.h:1795
void AppendArray(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs)
append the contents of an array to this array
Definition array.h:768
void Grow()
grow array with grow value
Definition array.h:568
void EraseIndex(IndexT index)
erase element at index, keep sorting intact
Definition array.h:1036
static const SizeT MaxGrowSize
Definition array.h:246
const SizeT ByteSize() const
return the byte size of the array.
Definition array.h:890
void EraseIndexSwap(IndexT index)
erase element at index, fill gap by swapping in last element, destroys sorting!
Definition array.h:1058
TYPE PopFront()
Pop front.
Definition array.h:1154
ConstIterator ConstBegin() const
return const iterator to beginning of array
Definition array.h:1255
_smallvector< TYPE, SMALL_VECTOR_SIZE > stackElements
Definition array.h:252
void resize(size_t size)
Definition array.h:1730
Array(SizeT initialSize, SizeT initialGrow, const TYPE &initialValue)
constructor with initial size, grow size and initial values
Definition array.h:288
void operator=(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs)
assignment operator
Definition array.h:485
void Append(const TYPE &elm)
append element to end of array
Definition array.h:732
void GrowTo(SizeT newCapacity)
grow array to target size
Definition array.h:545
TYPE & Get(IndexT index) const
Get element (same as operator[] but as a function)
Definition array.h:718
void Insert(IndexT index, const TYPE &elm)
insert element before element at index
Definition array.h:1183
void push_back(const TYPE &item)
Definition array.h:1006
size_t size() const
Definition array.h:1699
void CopyRange(TYPE *to, TYPE *from, SizeT num)
copy range
Definition array.h:674
void Resize(SizeT num, ARGS... args)
Resize and fill new elements with arguments.
Definition array.h:1625
bool operator==(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs) const
equality operator
Definition array.h:942
ArrayT Difference(const Array< TYPE, SMALL_VECTOR_SIZE > &rhs)
returns new array with elements which are not in rhs (slow!)
Definition array.h:1413
void EraseBack()
erase back
Definition array.h:1131
bool IsValidIndex(IndexT index) const
check if index is valid
Definition array.h:1026
Iterator Begin() const
return iterator to beginning of array
Definition array.h:1245
bool IsSorted() const
test if the array is sorted, this is a slow operation!
Definition array.h:1747
IndexT BinarySearchIndex(const TYPE &elm) const
do a binary search, requires a sorted array
Definition array.h:1492
void MoveRange(TYPE *to, TYPE *from, SizeT num)
move range
Definition array.h:696
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:1606
void QuickSortWithFunc(int(*func)(const void *lhs, const void *rhs))
quick sort the array
Definition array.h:1475
Array()
constructor with default parameters
Definition array.h:259
void Free()
free memory and reset size
Definition array.h:1234
const SizeT Size() const
get number of elements in array
Definition array.h:880
void AppendArray(const TYPE *arr, const SizeT count)
append from C array
Definition array.h:790
void clear() noexcept
Definition array.h:1660
TYPE & Front() const
return reference to first element
Definition array.h:980
TYPE PopBack()
Pop back.
Definition array.h:1169
const TYPE * ConstIterator
Definition array.h:64
Iterator Erase(Iterator iter)
erase element pointed to by iterator, keep sorting intact
Definition array.h:1081
void Fit()
Fit the size of the array to the amount of elements.
Definition array.h:1670
Array(const ArrayT &rhs)
copy constructor
Definition array.h:360
Implements a fixed size one-dimensional array.
Definition fixedarray.h:20
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:63
TYPE * ArrayAlloc(size_t size)
Definition memory.h:27
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:209
__forceinline void MoveElements(const T *from, T *to, size_t numElements)
Move a chunk of memory, can handle overlapping regions.
Definition posixmemory.h:192
void Clear(void *ptr, size_t numBytes)
Overwrite a chunk of memory with 0's.
Definition osxmemory.cc:229
A pinned array is an array which manages its own virtual memory.
Definition String.cs:6
Nebula's scalar datatype.
TYPE * data()
Definition array.h:56
Definition array.h:47
TYPE stackElements[STACK_SIZE]
Definition array.h:50
TYPE * data()
Definition array.h:48
static const int InvalidIndex
Definition types.h:54
int SizeT
Definition types.h:49
int IndexT
Definition types.h:48