Nebula
Loading...
Searching...
No Matches
arraystack.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
16#include "core/types.h"
17
18//------------------------------------------------------------------------------
19namespace Util
20{
21template<class TYPE, int STACK_SIZE> class ArrayStack
22{
23public:
25 typedef TYPE* Iterator;
26
28 ArrayStack();
30 ArrayStack(SizeT initialCapacity, SizeT initialGrow);
32 ArrayStack(SizeT initialSize, SizeT initialGrow, const TYPE& initialValue);
38 ArrayStack(std::initializer_list<TYPE> list);
41
45 void operator=(ArrayStack<TYPE, STACK_SIZE>&& rhs) noexcept;
47 TYPE& operator[](IndexT index) const;
49 bool operator==(const ArrayStack<TYPE, STACK_SIZE>& rhs) const;
51 bool operator!=(const ArrayStack<TYPE, STACK_SIZE>& rhs) const;
53 template<typename T> T As() const;
54
56 template <typename ...ELEM_TYPE>
57 void Append(const TYPE& first, const ELEM_TYPE&... elements);
59 void Append(const TYPE& elm);
61 void Append(TYPE&& elm);
65 void AppendArray(const TYPE* arr, const SizeT count);
67 void Reserve(SizeT num);
69 const SizeT Size() const;
71 const SizeT ByteSize() const;
73 const SizeT Capacity() const;
75 TYPE& Front() const;
77 TYPE& Back() const;
79 bool IsEmpty() const;
81 void EraseIndex(IndexT index);
85 void EraseIndexSwap(IndexT index);
89 void EraseBack();
91 void EraseFront();
93 void Insert(IndexT index, const TYPE& elm);
95 IndexT InsertSorted(const TYPE& elm);
97 IndexT InsertAtEndOfIdenticalRange(IndexT startIndex, const TYPE& elm);
99 bool IsSorted() const;
101 void Clear();
103 void Reset();
105 void Free();
107 Iterator Begin() const;
109 Iterator End() const;
111 Iterator Find(const TYPE& elm) const;
113 IndexT FindIndex(const TYPE& elm) const;
115 template <typename KEYTYPE> IndexT FindIndex(typename std::enable_if<true, const KEYTYPE&>::type elm) const;
117 void Fill(IndexT first, SizeT num, const TYPE& elm);
123 void Sort();
125 void SortWithFunc(bool (*func)(const TYPE& lhs, const TYPE& rhs));
127 IndexT BinarySearchIndex(const TYPE& elm) const;
129 template <typename KEYTYPE> IndexT BinarySearchIndex(typename std::enable_if<true, const KEYTYPE&>::type elm) const;
130
132 const bool IsStackUsed() const;
133
135 Iterator begin() const;
136 Iterator end() const;
137 size_t size() const;
138 void push_back(const TYPE& item);
139private:
141 void Destroy(TYPE* elm);
143 void Reset(TYPE* elm);
145 void Copy(const ArrayStack<TYPE, STACK_SIZE>& src);
147 void Delete();
149 void Grow();
151 void GrowTo(SizeT newCapacity);
153 void Move(IndexT fromIndex, IndexT toIndex);
154
155 static const SizeT MinGrowSize = 16;
156 static const SizeT MaxGrowSize = 65536; // FIXME: big grow size needed for mesh tools
157 SizeT grow; // grow by this number of elements if array exhausted
158 SizeT capacity; // number of elements allocated
159 SizeT count; // number of elements in array
160 TYPE smallVector[STACK_SIZE];
161 TYPE* elements; // pointer to element array
162};
163
164//------------------------------------------------------------------------------
167template<class TYPE, int STACK_SIZE>
170 capacity(STACK_SIZE),
171 count(0),
173{
174 // empty
175}
176
177//------------------------------------------------------------------------------
180template<class TYPE, int STACK_SIZE>
182 grow(_grow),
183 capacity(_capacity),
184 count(0)
185{
186 if (0 == this->grow)
187 {
188 this->grow = 16;
189 }
190 if (this->capacity > 0)
191 {
192 if (this->capacity > STACK_SIZE)
193 this->elements = new TYPE[this->capacity];
194 else
195 {
196 this->capacity = STACK_SIZE;
197 this->elements = smallVector;
198 }
199 }
200 else
201 {
202 this->capacity = STACK_SIZE;
203 this->elements = smallVector;
204 }
205}
206
207//------------------------------------------------------------------------------
210template<class TYPE, int STACK_SIZE>
211ArrayStack<TYPE, STACK_SIZE>::ArrayStack(SizeT initialSize, SizeT _grow, const TYPE& initialValue) :
212 grow(_grow),
213 capacity(initialSize),
214 count(initialSize)
215{
216 if (0 == this->grow)
217 {
218 this->grow = 16;
219 }
220 if (this->capacity > 0)
221 {
222 if (this->capacity > STACK_SIZE)
223 this->elements = new TYPE[this->capacity];
224 else
225 {
226 this->capacity = STACK_SIZE;
227 this->elements = smallVector;
228 }
229
230 IndexT i;
231 for (i = 0; i < this->capacity; i++)
232 {
233 this->elements[i] = initialValue;
234 }
235 }
236 else
237 {
238 this->capacity = STACK_SIZE;
239 this->elements = smallVector;
240 }
241}
242
243//------------------------------------------------------------------------------
246template<class TYPE, int STACK_SIZE>
247ArrayStack<TYPE, STACK_SIZE>::ArrayStack(std::initializer_list<TYPE> list) :
248 grow(16),
249 capacity((SizeT)list.size()),
250 count((SizeT)list.size())
251{
252 if (this->capacity > 0)
253 {
254 if (this->capacity > STACK_SIZE)
255 this->elements = new TYPE[this->capacity];
256 else
257 {
258 this->capacity = STACK_SIZE;
259 this->elements = smallVector;
260 }
261
262 IndexT i;
263 for (i = 0; i < this->count; i++)
264 {
265 this->elements[i] = list.begin()[i];
266 }
267 }
268 else
269 {
270 this->capacity = STACK_SIZE;
271 this->elements = smallVector;
272 }
273}
274
275//------------------------------------------------------------------------------
278template<class TYPE, int STACK_SIZE>
280 grow(0),
281 capacity(0),
282 count(0),
284{
285 this->Copy(rhs);
286}
287
288//------------------------------------------------------------------------------
291template<class TYPE, int STACK_SIZE>
293{
294 this->capacity = rhs.capacity;
295 this->count = rhs.count;
296 this->grow = rhs.grow;
297
298 if (this->capacity <= STACK_SIZE)
299 {
300 for (IndexT i = 0; i < rhs.count; ++i)
301 {
302 this->smallVector[i] = rhs.smallVector[i];
303 }
304
305 this->elements = this->smallVector;
306 }
307 else
308 this->elements = rhs.elements;
309
310 rhs.count = 0;
311 rhs.capacity = 0;
312 rhs.elements = nullptr;
313}
314
315//------------------------------------------------------------------------------
318template<class TYPE, int STACK_SIZE> void
320{
321 #if NEBULA_BOUNDSCHECKS
322 if (this->elements != this->smallVector)
323 n_assert(0 == this->elements);
324 #endif
325
326 this->grow = src.grow;
327 this->capacity = src.count; // don't copy capacity, make this new copy smaller
328 this->count = src.count;
329 if (this->capacity > 0)
330 {
331 if (this->capacity > STACK_SIZE)
332 this->elements = new TYPE[this->capacity];
333 else
334 this->elements = smallVector;
335
336 IndexT i;
337 for (i = 0; i < this->count; i++)
338 {
339 this->elements[i] = src.elements[i];
340 }
341 }
342}
343
344//------------------------------------------------------------------------------
347template<class TYPE, int STACK_SIZE> void
349{
350 this->grow = 0;
351 this->capacity = 0;
352 this->count = 0;
353 if (this->elements)
354 {
355 if (this->elements != this->smallVector)
356 delete[] this->elements;
357
358 this->elements = this->smallVector;
359 }
360}
361
362//------------------------------------------------------------------------------
365template<class TYPE, int STACK_SIZE> void
367{
368 elm->~TYPE();
369}
370
371//------------------------------------------------------------------------------
374template<class TYPE, int STACK_SIZE> void
376{
377 if constexpr (!std::is_trivially_destructible<TYPE>::value)
378 {
379 this->Destroy(elm);
380 ::new ((void*)elm) TYPE();
381 }
382}
383
384//------------------------------------------------------------------------------
387template<class TYPE, int STACK_SIZE>
392
393//------------------------------------------------------------------------------
396template<class TYPE, int STACK_SIZE> void
398{
399 this->Delete();
400 this->grow = _grow;
401 this->capacity = _capacity;
402 this->count = _capacity;
403 if (this->capacity > 0)
404 {
405 if (this->capacity > STACK_SIZE)
406 this->elements = new TYPE[this->capacity];
407 else
408 this->elements = smallVector;
409 }
410 else
411 {
412 this->elements = smallVector;
413 }
414}
415
416//------------------------------------------------------------------------------
419template<class TYPE, int STACK_SIZE> void
421{
422 if (this != &rhs)
423 {
424 if ((this->capacity > 0) && (rhs.count <= this->capacity))
425 {
426 // source array fits into our capacity, copy in place
427 n_assert(0 != this->elements);
428 IndexT i;
429 for (i = 0; i < rhs.count; i++)
430 {
431 this->elements[i] = rhs.elements[i];
432 }
433
434 // properly reset remaining original elements
435 for (; i < this->count; i++)
436 {
437 this->Reset(&(this->elements[i]));
438 }
439 this->grow = rhs.grow;
440 this->count = rhs.count;
441 }
442 else
443 {
444 // source array doesn't fit into our capacity, need to reallocate
445 this->Delete();
446 this->Copy(rhs);
447 }
448 }
449}
450
451//------------------------------------------------------------------------------
454template<class TYPE, int STACK_SIZE>
456{
457 if (this == &rhs)
458 {
459 return;
460 }
461 if (this->elements && this->capacity > STACK_SIZE)
462 {
463 delete[] this->elements;
464 }
465
466 this->capacity = rhs.capacity;
467 this->count = rhs.count;
468 this->grow = rhs.grow;
469
470 if (this->capacity <= STACK_SIZE)
471 {
472 for (IndexT i = 0; i < rhs.count; ++i)
473 {
474 this->smallVector[i] = rhs.smallVector[i];
475 }
476
477 this->elements = this->smallVector;
478 }
479 else
480 {
481 this->elements = rhs.elements;
482 }
483
484 rhs.count = 0;
485 rhs.capacity = 0;
486 rhs.elements = nullptr;
487}
488
489//------------------------------------------------------------------------------
492template<class TYPE, int STACK_SIZE> void
494{
495 if (newCapacity > STACK_SIZE)
496 {
497 TYPE* newArray = new TYPE[newCapacity];
498 if (this->elements)
499 {
500 // copy over contents
501 IndexT i;
502 for (i = 0; i < this->count; i++)
503 {
504 newArray[i] = this->elements[i];
505 }
506
507 // discard old array
508 if (this->elements != this->smallVector)
509 delete[] this->elements;
510 }
511 this->elements = newArray;
512 }
513 this->capacity = newCapacity;
514
515}
516
517//------------------------------------------------------------------------------
520template<class TYPE, int STACK_SIZE> void
522{
523 #if NEBULA_BOUNDSCHECKS
524 n_assert(this->grow > 0);
525 #endif
526
527 SizeT growToSize;
528 if (0 == this->capacity)
529 {
530 growToSize = this->grow;
531 }
532 else
533 {
534 // grow by half of the current capacity, but never more then MaxGrowSize
535 SizeT growBy = this->capacity >> 1;
536 if (growBy == 0)
537 {
538 growBy = MinGrowSize;
539 }
540 else if (growBy > MaxGrowSize)
541 {
542 growBy = MaxGrowSize;
543 }
544 growToSize = this->capacity + growBy;
545 }
546 this->GrowTo(growToSize);
547}
548
549//------------------------------------------------------------------------------
554template<class TYPE, int STACK_SIZE> void
556{
557 #if NEBULA_BOUNDSCHECKS
558 n_assert(this->elements);
559 n_assert(fromIndex < this->count);
560 #endif
561
562 // nothing to move?
563 if (fromIndex == toIndex)
564 {
565 return;
566 }
567
568 // compute number of elements to move
569 SizeT num = this->count - fromIndex;
570
571 // check if array needs to grow
572 SizeT neededSize = toIndex + num;
573 while (neededSize > this->capacity)
574 {
575 this->Grow();
576 }
577
578 if (fromIndex > toIndex)
579 {
580 // this is a backward move
581 IndexT i;
582 for (i = 0; i < num; i++)
583 {
584 this->elements[toIndex + i] = this->elements[fromIndex + i];
585 }
586
587 // reset remaining elements
588 for (i = (fromIndex + i) - 1; i < this->count; i++)
589 {
590 this->Reset(&(this->elements[i]));
591 }
592 }
593 else
594 {
595 // this is a forward move
596 IndexT i; // NOTE: this must remain signed for the following loop to work!!!
597 for (i = num - 1; i >= 0; --i)
598 {
599 this->elements[toIndex + i] = this->elements[fromIndex + i];
600 }
601
602 // reset freed elements
603 for (i = int(fromIndex); i < int(toIndex); i++)
604 {
605 this->Reset(&(this->elements[i]));
606 }
607 }
608
609 // adjust array size
610 this->count = toIndex + num;
611}
612
613//------------------------------------------------------------------------------
616template<class TYPE, int STACK_SIZE> void
618{
619 // grow allocated space if exhausted
620 if (this->count == this->capacity)
621 {
622 this->Grow();
623 }
624 #if NEBULA_BOUNDSCHECKS
625 n_assert(this->elements);
626 #endif
627 this->elements[this->count++] = elm;
628}
629
630//------------------------------------------------------------------------------
633template<class TYPE, int STACK_SIZE> inline void
635{
636 // grow allocated space if exhausted
637 if (this->count == this->capacity)
638 {
639 this->Grow();
640 }
641#if NEBULA_BOUNDSCHECKS
642 n_assert(this->elements);
643#endif
644 this->elements[this->count++] = std::forward<TYPE>(elm);
645}
646
647//------------------------------------------------------------------------------
650template<class TYPE, int STACK_SIZE> void
652{
653 SizeT neededCapacity = this->count + rhs.count;
654 if (neededCapacity > this->capacity)
655 {
656 this->GrowTo(neededCapacity);
657 }
658
659 // forward elements from array
660 IndexT i;
661 for (i = 0; i < rhs.count; i++)
662 {
663 this->elements[this->count + i] = rhs.elements[i];
664 }
665 this->count += rhs.count;
666}
667
668//------------------------------------------------------------------------------
671template<class TYPE, int STACK_SIZE> void
673{
674 SizeT neededCapacity = this->count + count;
675 if (neededCapacity > this->capacity)
676 {
677 this->GrowTo(neededCapacity);
678 }
679
680 // forward elements from array
681 IndexT i;
682 for (i = 0; i < count; i++)
683 {
684 this->elements[this->count + i] = arr[i];
685 }
686 this->count += count;
687}
688
689//------------------------------------------------------------------------------
699template<class TYPE, int STACK_SIZE> void
701{
702 #if NEBULA_BOUNDSCHECKS
703 n_assert(num > 0);
704 #endif
705 SizeT neededCapacity = this->count + num;
706 if (neededCapacity > this->capacity)
707 {
708 this->GrowTo(neededCapacity);
709 }
710}
711
712//------------------------------------------------------------------------------
715template<class TYPE, int STACK_SIZE> const SizeT
717{
718 return this->count;
719}
720
721//------------------------------------------------------------------------------
724template<class TYPE, int STACK_SIZE> size_t
726{
727 return this->count;
728}
729
730//------------------------------------------------------------------------------
733template<class TYPE, int STACK_SIZE> void
735{
736 this->Append(item);
737}
738
739//------------------------------------------------------------------------------
742template<class TYPE, int STACK_SIZE> const SizeT
744{
745 return this->count * sizeof(TYPE);
746}
747
748//------------------------------------------------------------------------------
751template<class TYPE, int STACK_SIZE> const SizeT
753{
754 return this->capacity;
755}
756
757//------------------------------------------------------------------------------
762template<class TYPE, int STACK_SIZE> TYPE&
764{
765 #if NEBULA_BOUNDSCHECKS
766 n_assert(this->elements && (index < this->count));
767 #endif
768 return this->elements[index];
769}
770
771//------------------------------------------------------------------------------
776template<class TYPE, int STACK_SIZE> bool
778{
779 if (rhs.Size() == this->Size())
780 {
781 IndexT i;
782 SizeT num = this->Size();
783 for (i = 0; i < num; i++)
784 {
785 if (!(this->elements[i] == rhs.elements[i]))
786 {
787 return false;
788 }
789 }
790 return true;
791 }
792 else
793 {
794 return false;
795 }
796}
797
798//------------------------------------------------------------------------------
803template<class TYPE, int STACK_SIZE> bool
805{
806 return !(*this == rhs);
807}
808
809//------------------------------------------------------------------------------
812template<class TYPE, int STACK_SIZE> TYPE&
814{
815 #if NEBULA_BOUNDSCHECKS
816 n_assert(this->elements && (this->count > 0));
817 #endif
818 return this->elements[0];
819}
820
821//------------------------------------------------------------------------------
824template<class TYPE, int STACK_SIZE> TYPE&
826{
827 #if NEBULA_BOUNDSCHECKS
828 n_assert(this->elements && (this->count > 0));
829 #endif
830 return this->elements[this->count - 1];
831}
832
833//------------------------------------------------------------------------------
836template<class TYPE, int STACK_SIZE> bool
838{
839 return (this->count == 0);
840}
841
842//------------------------------------------------------------------------------
845template<class TYPE, int STACK_SIZE> void
847{
848 #if NEBULA_BOUNDSCHECKS
849 n_assert(this->elements && (index < this->count));
850 #endif
851 if (index == (this->count - 1))
852 {
853 // special case: last element
854 this->EraseBack();
855 }
856 else
857 {
858 this->Move(index + 1, index);
859 }
860}
861
862//------------------------------------------------------------------------------
866template<class TYPE, int STACK_SIZE> void
868{
869 #if NEBULA_BOUNDSCHECKS
870 n_assert(this->elements && (index < this->count));
871 #endif
872
873 // swap with last element, and destroy last element
874 IndexT lastElementIndex = this->count - 1;
875 if (index < lastElementIndex)
876 {
877 this->elements[index] = std::move(this->elements[lastElementIndex]);
878 this->Reset(&(this->elements[lastElementIndex]));
879 }
880 else
881 {
882 this->Reset(&(this->elements[index]));
883 }
884 this->count--;
885}
886
887//------------------------------------------------------------------------------
890template<class TYPE, int STACK_SIZE> typename ArrayStack<TYPE, STACK_SIZE>::Iterator
892{
893 #if NEBULA_BOUNDSCHECKS
894 n_assert(this->elements && (iter >= this->elements) && (iter < (this->elements + this->count)));
895 #endif
896 this->EraseIndex(IndexT(iter - this->elements));
897 return iter;
898}
899
900//------------------------------------------------------------------------------
904template<class TYPE, int STACK_SIZE> typename ArrayStack<TYPE, STACK_SIZE>::Iterator
906{
907 #if NEBULA_BOUNDSCHECKS
908 n_assert(this->elements && (iter >= this->elements) && (iter < (this->elements + this->count)));
909 #endif
910 this->EraseIndexSwap(IndexT(iter - this->elements));
911 return iter;
912}
913
914//------------------------------------------------------------------------------
917template<class TYPE, int STACK_SIZE> void
919{
920 n_assert(this->count > 0);
921 this->Reset(&(this->elements[this->count - 1]));
922 this->count--;
923}
924
925//------------------------------------------------------------------------------
928template<class TYPE, int STACK_SIZE> void
933
934//------------------------------------------------------------------------------
937template<class TYPE, int STACK_SIZE> void
939{
940 #if NEBULA_BOUNDSCHECKS
941 n_assert(index <= this->count);
942 #endif
943 if (index == this->count)
944 {
945 // special case: append element to back
946 this->Append(elm);
947 }
948 else
949 {
950 this->Move(index, index + 1);
951 this->elements[index] = elm;
952 }
953}
954
955//------------------------------------------------------------------------------
960template<class TYPE, int STACK_SIZE> void
962{
963 IndexT i;
964 for (i = 0; i < this->count; i++)
965 {
966 this->Reset(&(this->elements[i]));
967 }
968 this->count = 0;
969}
970
971//------------------------------------------------------------------------------
976template<class TYPE, int STACK_SIZE> void
981
982//------------------------------------------------------------------------------
986template<class TYPE, int STACK_SIZE> void
988{
989 this->Delete();
990 this->grow = 8;
991}
992
993//------------------------------------------------------------------------------
996template<class TYPE, int STACK_SIZE> typename ArrayStack<TYPE, STACK_SIZE>::Iterator
998{
999 return this->elements;
1000}
1001
1002//------------------------------------------------------------------------------
1005template<class TYPE, int STACK_SIZE> typename ArrayStack<TYPE, STACK_SIZE>::Iterator
1007{
1008 return this->elements + this->count;
1009}
1010
1011//------------------------------------------------------------------------------
1019template<class TYPE, int STACK_SIZE> typename ArrayStack<TYPE, STACK_SIZE>::Iterator
1021{
1022 IndexT index;
1023 for (index = 0; index < this->count; index++)
1024 {
1025 if (this->elements[index] == elm)
1026 {
1027 return &(this->elements[index]);
1028 }
1029 }
1030 return 0;
1031}
1032
1033//------------------------------------------------------------------------------
1041template<class TYPE, int STACK_SIZE> IndexT
1043{
1044 IndexT index;
1045 for (index = 0; index < this->count; index++)
1046 {
1047 if (this->elements[index] == elm)
1048 {
1049 return index;
1050 }
1051 }
1052 return InvalidIndex;
1053}
1054
1055//------------------------------------------------------------------------------
1058template<class TYPE, int STACK_SIZE>
1059template<typename ...ELEM_TYPE>
1060inline void
1061ArrayStack<TYPE, STACK_SIZE>::Append(const TYPE& first, const ELEM_TYPE&... elements)
1062{
1063 this->Reserve(sizeof...(elements) + 1);
1064 this->Append(first);
1065 this->Append(std::forward<const ELEM_TYPE&>(elements)...);
1066}
1067
1068//------------------------------------------------------------------------------
1083template<class TYPE, int STACK_SIZE>
1084template<typename KEYTYPE> inline IndexT
1085ArrayStack<TYPE, STACK_SIZE>::FindIndex(typename std::enable_if<true, const KEYTYPE&>::type elm) const
1086{
1087 IndexT index;
1088 for (index = 0; index < this->count; index++)
1089 {
1090 if (this->elements[index] == elm)
1091 {
1092 return index;
1093 }
1094 }
1095 return InvalidIndex;
1096}
1097
1098//------------------------------------------------------------------------------
1108template<class TYPE, int STACK_SIZE> void
1110{
1111 if ((first + num) > this->count)
1112 {
1113 this->GrowTo(first + num);
1114 this->count = first + num;
1115 }
1116 IndexT i;
1117 for (i = first; i < (first + num); i++)
1118 {
1119 this->elements[i] = elm;
1120 }
1121}
1122
1123//------------------------------------------------------------------------------
1130template<class TYPE, int STACK_SIZE> ArrayStack<TYPE, STACK_SIZE>
1132{
1134 IndexT i;
1135 SizeT num = rhs.Size();
1136 for (i = 0; i < num; i++)
1137 {
1138 if (0 == this->Find(rhs[i]))
1139 {
1140 diff.Append(rhs[i]);
1141 }
1142 }
1143 return diff;
1144}
1145
1146//------------------------------------------------------------------------------
1150template<class TYPE, int STACK_SIZE> void
1152{
1153 std::sort(this->Begin(), this->End());
1154}
1155
1156//------------------------------------------------------------------------------
1159template<class TYPE, int STACK_SIZE> void
1160Util::ArrayStack<TYPE, STACK_SIZE>::SortWithFunc(bool (*func)(const TYPE& lhs, const TYPE& rhs))
1161{
1162 std::sort(this->Begin(), this->End(), func);
1163}
1164
1165//------------------------------------------------------------------------------
1170template<class TYPE, int STACK_SIZE> IndexT
1172{
1173 SizeT num = this->Size();
1174 if (num > 0)
1175 {
1176 IndexT half;
1177 IndexT lo = 0;
1178 IndexT hi = num - 1;
1179 IndexT mid;
1180 while (lo <= hi)
1181 {
1182 if (0 != (half = num/2))
1183 {
1184 mid = lo + ((num & 1) ? half : (half - 1));
1185 if (elm < this->elements[mid])
1186 {
1187 hi = mid - 1;
1188 num = num & 1 ? half : half - 1;
1189 }
1190 else if (elm > this->elements[mid])
1191 {
1192 lo = mid + 1;
1193 num = half;
1194 }
1195 else
1196 {
1197 return mid;
1198 }
1199 }
1200 else if (0 != num)
1201 {
1202 if (elm != this->elements[lo])
1203 {
1204 return InvalidIndex;
1205 }
1206 else
1207 {
1208 return lo;
1209 }
1210 }
1211 else
1212 {
1213 break;
1214 }
1215 }
1216 }
1217 return InvalidIndex;
1218}
1219
1220//------------------------------------------------------------------------------
1229template<class TYPE, int STACK_SIZE>
1230template<typename KEYTYPE> inline IndexT
1231ArrayStack<TYPE, STACK_SIZE>::BinarySearchIndex(typename std::enable_if<true, const KEYTYPE&>::type elm) const
1232{
1233 SizeT num = this->Size();
1234 if (num > 0)
1235 {
1236 IndexT half;
1237 IndexT lo = 0;
1238 IndexT hi = num - 1;
1239 IndexT mid;
1240 while (lo <= hi)
1241 {
1242 if (0 != (half = num / 2))
1243 {
1244 mid = lo + ((num & 1) ? half : (half - 1));
1245 if (this->elements[mid] > elm)
1246 {
1247 hi = mid - 1;
1248 num = num & 1 ? half : half - 1;
1249 }
1250 else if (this->elements[mid] < elm)
1251 {
1252 lo = mid + 1;
1253 num = half;
1254 }
1255 else
1256 {
1257 return mid;
1258 }
1259 }
1260 else if (0 != num)
1261 {
1262 if (this->elements[lo] != elm)
1263 {
1264 return InvalidIndex;
1265 }
1266 else
1267 {
1268 return lo;
1269 }
1270 }
1271 else
1272 {
1273 break;
1274 }
1275 }
1276 }
1277 return InvalidIndex;
1278}
1279
1280
1281//------------------------------------------------------------------------------
1284template<class TYPE, int STACK_SIZE>
1286{
1287 return this->elements == this->smallVector;
1288}
1289
1290//------------------------------------------------------------------------------
1293template<class TYPE, int STACK_SIZE> typename ArrayStack<TYPE, STACK_SIZE>::Iterator
1295{
1296 return this->elements;
1297}
1298
1299//------------------------------------------------------------------------------
1302template<class TYPE, int STACK_SIZE> typename ArrayStack<TYPE, STACK_SIZE>::Iterator
1304{
1305 return this->elements + this->count;
1306}
1307
1308//------------------------------------------------------------------------------
1313template<class TYPE, int STACK_SIZE> bool
1315{
1316 if (this->count > 1)
1317 {
1318 IndexT i;
1319 for (i = 0; i < this->count - 1; i++)
1320 {
1321 if (this->elements[i] > this->elements[i + 1])
1322 {
1323 return false;
1324 }
1325 }
1326 }
1327 return true;
1328}
1329
1330//------------------------------------------------------------------------------
1336template<class TYPE, int STACK_SIZE> IndexT
1338{
1339 IndexT i = startIndex + 1;
1340 for (; i < this->count; i++)
1341 {
1342 if (this->elements[i] != elm)
1343 {
1344 this->Insert(i, elm);
1345 return i;
1346 }
1347 }
1348
1349 // fallthrough: new element needs to be appended to end
1350 this->Append(elm);
1351 return (this->Size() - 1);
1352}
1353
1354//------------------------------------------------------------------------------
1359template<class TYPE, int STACK_SIZE> IndexT
1361{
1362 SizeT num = this->Size();
1363 if (num == 0)
1364 {
1365 // array is currently empty
1366 this->Append(elm);
1367 return this->Size() - 1;
1368 }
1369 else
1370 {
1371 IndexT half;
1372 IndexT lo = 0;
1373 IndexT hi = num - 1;
1374 IndexT mid;
1375 while (lo <= hi)
1376 {
1377 if (0 != (half = num/2))
1378 {
1379 mid = lo + ((num & 1) ? half : (half - 1));
1380 if (elm < this->elements[mid])
1381 {
1382 hi = mid - 1;
1383 num = num & 1 ? half : half - 1;
1384 }
1385 else if (elm > this->elements[mid])
1386 {
1387 lo = mid + 1;
1388 num = half;
1389 }
1390 else
1391 {
1392 // element already exists at [mid], append the
1393 // new element to the end of the range
1394 return this->InsertAtEndOfIdenticalRange(mid, elm);
1395 }
1396 }
1397 else if (0 != num)
1398 {
1399 if (elm < this->elements[lo])
1400 {
1401 this->Insert(lo, elm);
1402 return lo;
1403 }
1404 else if (elm > this->elements[lo])
1405 {
1406 this->Insert(lo + 1, elm);
1407 return lo + 1;
1408 }
1409 else
1410 {
1411 // element already exists at [low], append
1412 // the new element to the end of the range
1413 return this->InsertAtEndOfIdenticalRange(lo, elm);
1414 }
1415 }
1416 else
1417 {
1418 #if NEBULA_BOUNDSCHECKS
1419 n_assert(0 == lo);
1420 #endif
1421 this->Insert(lo, elm);
1422 return lo;
1423 }
1424 }
1425 if (elm < this->elements[lo])
1426 {
1427 this->Insert(lo, elm);
1428 return lo;
1429 }
1430 else if (elm > this->elements[lo])
1431 {
1432 this->Insert(lo + 1, elm);
1433 return lo + 1;
1434 }
1435 else
1436 {
1437 // can't happen(?)
1438 }
1439 }
1440 // can't happen
1441 n_error("Array::InsertSorted: Can't happen!");
1442 return InvalidIndex;
1443}
1444
1445} // namespace Core
1446//------------------------------------------------------------------------------
Definition half.h:20
Nebula's small vector optimized array.
Definition arraystack.h:22
bool IsSorted() const
test if the array is sorted, this is a slow operation!
Definition arraystack.h:1314
static const SizeT MinGrowSize
Definition arraystack.h:155
void Destroy(TYPE *elm)
destroy an element (call destructor without freeing memory)
Definition arraystack.h:366
SizeT capacity
Definition arraystack.h:158
void Fill(IndexT first, SizeT num, const TYPE &elm)
fill array range with element
Definition arraystack.h:1109
TYPE & operator[](IndexT index) const
[] operator
Definition arraystack.h:763
Iterator Find(const TYPE &elm) const
find identical element in array, return iterator
Definition arraystack.h:1020
void Realloc(SizeT capacity, SizeT grow)
clear contents and preallocate with new attributes
Definition arraystack.h:397
void Free()
free memory and reset size
Definition arraystack.h:987
void EraseFront()
erase first element
Definition arraystack.h:929
SizeT grow
Definition arraystack.h:157
void GrowTo(SizeT newCapacity)
grow array to target size
Definition arraystack.h:493
void operator=(const ArrayStack< TYPE, STACK_SIZE > &rhs)
assignment operator
Definition arraystack.h:420
static const SizeT MaxGrowSize
Definition arraystack.h:156
void Append(const TYPE &first, const ELEM_TYPE &... elements)
Append multiple elements to the end of the array.
Definition arraystack.h:1061
IndexT InsertSorted(const TYPE &elm)
insert element into sorted array, return index where element was included
Definition arraystack.h:1360
Iterator EraseSwap(Iterator iter)
erase element at iterator, fill gap by swapping in last element, destroys sorting!
Definition arraystack.h:905
ArrayStack()
constructor with default parameters
Definition arraystack.h:168
void push_back(const TYPE &item)
Definition arraystack.h:734
void Copy(const ArrayStack< TYPE, STACK_SIZE > &src)
copy content
Definition arraystack.h:319
IndexT BinarySearchIndex(const TYPE &elm) const
do a binary search, requires a sorted array
Definition arraystack.h:1171
void SortWithFunc(bool(*func)(const TYPE &lhs, const TYPE &rhs))
sort with custom function
Definition arraystack.h:1160
void AppendArray(const ArrayStack< TYPE, STACK_SIZE > &rhs)
append the contents of an array to this array
Definition arraystack.h:651
Iterator begin() const
for range-based iteration
Definition arraystack.h:1294
void EraseIndex(IndexT index)
erase element at index, keep sorting intact
Definition arraystack.h:846
SizeT count
Definition arraystack.h:159
bool operator!=(const ArrayStack< TYPE, STACK_SIZE > &rhs) const
inequality operator
Definition arraystack.h:804
bool IsEmpty() const
return true if array empty
Definition arraystack.h:837
TYPE * elements
Definition arraystack.h:161
ArrayStack< TYPE, STACK_SIZE > Difference(const ArrayStack< TYPE, STACK_SIZE > &rhs)
returns new array with elements which are not in rhs (slow!)
Definition arraystack.h:1131
void Reserve(SizeT num)
increase capacity to fit N more elements into the array
Definition arraystack.h:700
IndexT InsertAtEndOfIdenticalRange(IndexT startIndex, const TYPE &elm)
insert element at the first non-identical position, return index of inclusion position
Definition arraystack.h:1337
void EraseBack()
erase last element
Definition arraystack.h:918
const bool IsStackUsed() const
returns true if the stack is used
Definition arraystack.h:1285
TYPE & Front() const
return reference to first element
Definition arraystack.h:813
const SizeT Capacity() const
get overall allocated size of array in number of elements
Definition arraystack.h:752
const SizeT ByteSize() const
return the byte size of the array.
Definition arraystack.h:743
void Grow()
grow array
Definition arraystack.h:521
T As() const
convert to "anything"
void Delete()
delete content
Definition arraystack.h:348
Iterator end() const
Definition arraystack.h:1303
bool operator==(const ArrayStack< TYPE, STACK_SIZE > &rhs) const
equality operator
Definition arraystack.h:777
size_t size() const
Definition arraystack.h:725
Iterator Begin() const
return iterator to beginning of array
Definition arraystack.h:997
void Move(IndexT fromIndex, IndexT toIndex)
move elements, grows array if needed
Definition arraystack.h:555
void EraseIndexSwap(IndexT index)
erase element at index, fill gap by swapping in last element, destroys sorting!
Definition arraystack.h:867
TYPE & Back() const
return reference to last element
Definition arraystack.h:825
~ArrayStack()
destructor
Definition arraystack.h:388
const SizeT Size() const
get number of elements in array
Definition arraystack.h:716
TYPE smallVector[STACK_SIZE]
Definition arraystack.h:160
TYPE * Iterator
define iterator
Definition arraystack.h:25
void Insert(IndexT index, const TYPE &elm)
insert element before element at index
Definition arraystack.h:938
IndexT FindIndex(const TYPE &elm) const
find identical element in array, return index, InvalidIndex if not found
Definition arraystack.h:1042
Iterator End() const
return iterator to end of array
Definition arraystack.h:1006
void Reset()
reset array (does NOT call destructors)
Definition arraystack.h:977
void Sort()
sort the array
Definition arraystack.h:1151
Iterator Erase(Iterator iter)
erase element pointed to by iterator, keep sorting intact
Definition arraystack.h:891
void Clear()
clear array (calls destructors)
Definition arraystack.h:961
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
A quad tree designed to return regions of free 2D space.
Definition String.cs:6
static const int InvalidIndex
Definition types.h:47
int SizeT
Definition types.h:42
int IndexT
Definition types.h:41