Nebula
Loading...
Searching...
No Matches
fixedarray.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
12#include "core/types.h"
13#include "util/array.h"
14
15
16//------------------------------------------------------------------------------
17namespace Util
18{
19template<class TYPE, bool StackAlloc = false> class FixedArray
20{
21public:
23 typedef TYPE* Iterator;
24
28 FixedArray(const SizeT s);
30 FixedArray(const SizeT s, const TYPE& initialValue);
42 FixedArray(std::initializer_list<TYPE> list);
44 FixedArray(std::nullptr_t);
52 TYPE& operator[](IndexT index) const;
57
59 void SetSize(SizeT s);
61 const SizeT Size() const;
63 const SizeT ByteSize() const;
65 void Resize(SizeT newSize);
67 bool IsEmpty() const;
69 void Clear();
71 void Reset();
73 void Fill(const TYPE& val);
75 void Fill(IndexT first, SizeT num, const TYPE& val);
77 Iterator Begin() const;
79 Iterator End() const;
81 TYPE& Front() const;
83 TYPE& Back() const;
85 Iterator Find(const TYPE& val) const;
87 IndexT FindIndex(const TYPE& val) const;
89 void Sort();
91 IndexT BinarySearchIndex(const TYPE& val) const;
94
96 Iterator begin() const;
97 Iterator end() const;
98 size_t size() const;
99 void resize(size_t size);
100private:
101
102 template<class T, bool S>
103 friend class FixedArray;
104
106 void Delete();
108 void Alloc(SizeT s);
111
113 TYPE* elements;
114};
115
116
117//------------------------------------------------------------------------------
120template<class TYPE, bool StackAlloc>
122 count(0),
123 elements(nullptr)
124{
125 // empty
126}
127
128//------------------------------------------------------------------------------
131template<class TYPE, bool StackAlloc> void
133{
134 if (this->elements)
135 {
136 if constexpr (StackAlloc)
137 {
138 ArrayFreeStack(this->count, this->elements);
139 }
140 else
141 {
142 ArrayFree(this->count, this->elements);
143 }
144
145 this->elements = nullptr;
146
147 }
148 this->count = 0;
149}
150
151//------------------------------------------------------------------------------
154template<class TYPE, bool StackAlloc> void
156{
157 #if NEBULA_BOUNDSCHECKS
158 n_assert(0 == this->elements);
159 #endif
160 if (s > 0)
161 {
162 if constexpr (StackAlloc)
163 {
165 }
166 else
167 {
168 this->elements = ArrayAlloc<TYPE>(s);
169 }
170 }
171 this->count = s;
172}
173
174//------------------------------------------------------------------------------
178template<class TYPE, bool StackAlloc> void
180{
181 if (this->elements != rhs.elements && rhs.count > 0)
182 {
183 this->Alloc(rhs.count);
184 if constexpr (!std::is_trivially_copyable<TYPE>::value)
185 {
186 IndexT i;
187 for (i = 0; i < this->count; i++)
188 {
189 this->elements[i] = rhs.elements[i];
190 }
191 }
192 else
193 memcpy(this->elements, rhs.elements, this->count * sizeof(TYPE));
194 }
195}
196
197//------------------------------------------------------------------------------
200template<class TYPE, bool StackAlloc>
202 count(0),
203 elements(nullptr)
204{
205 this->Alloc(s);
206}
207
208//------------------------------------------------------------------------------
211template<class TYPE, bool StackAlloc>
212FixedArray<TYPE, StackAlloc>::FixedArray(const SizeT s, const TYPE& initialValue) :
213 count(0),
214 elements(nullptr)
215{
216 this->Alloc(s);
217 this->Fill(initialValue);
218}
219
220//------------------------------------------------------------------------------
223template<class TYPE, bool StackAlloc>
225 count(0),
226 elements(nullptr)
227{
228 if (this->elements != rhs.elements && rhs.count > 0)
229 {
230 this->Alloc(rhs.count);
231 if constexpr (!std::is_trivially_copyable<TYPE>::value)
232 {
233 IndexT i;
234 for (i = 0; i < this->count; i++)
235 {
236 this->elements[i] = rhs.elements[i];
237 }
238 }
239 else
240 memcpy(this->elements, rhs.elements, this->count * sizeof(TYPE));
241 }
242}
243
244//------------------------------------------------------------------------------
247template<class TYPE, bool StackAlloc>
249 count(0),
250 elements(nullptr)
251{
252 if (this->elements != rhs.elements && rhs.count > 0)
253 {
254 this->Alloc(rhs.count);
255 if constexpr (!std::is_trivially_copyable<TYPE>::value)
256 {
257 IndexT i;
258 for (i = 0; i < this->count; i++)
259 {
260 this->elements[i] = rhs.elements[i];
261 }
262 }
263 else
264 memcpy(this->elements, rhs.elements, this->count * sizeof(TYPE));
265 }
266}
267
268//------------------------------------------------------------------------------
271template<class TYPE, bool StackAlloc>
273 count(rhs.Size()),
274 elements(nullptr)
275{
276 if (this->count > 0)
277 {
278 this->Alloc(this->count);
279 if constexpr (!std::is_trivially_copyable<TYPE>::value)
280 {
281 IndexT i;
282 for (i = 0; i < this->count; i++)
283 {
284 this->elements[i] = rhs.Begin()[i];
285 }
286 }
287 else
288 memcpy(this->elements, rhs.Begin(), this->count * sizeof(TYPE));
289 }
290}
291
292//------------------------------------------------------------------------------
295template<class TYPE, bool StackAlloc>
297 : elements(nullptr)
298 , count(0)
299{
300 // If array lives on the stack, then we need to allocate
301 if (rhs.count > 0)
302 {
303 if (rhs.stackElements.data() == rhs.elements || StackAlloc)
304 {
305 this->Alloc(rhs.count);
306 if constexpr (!std::is_trivially_copyable<TYPE>::value)
307 {
308 IndexT i;
309 for (i = 0; i < this->count; i++)
310 {
311 this->elements[i] = rhs.Begin()[i];
312 }
313 }
314 else
315 memcpy(this->elements, rhs.Begin(), this->count * sizeof(TYPE));
316 }
317 else
318 {
319 this->elements = rhs.elements;
320 rhs.elements = nullptr;
321 this->count = rhs.count;
322 rhs.capacity = 0;
323 rhs.count = 0;
324 }
325 }
326}
327
328//------------------------------------------------------------------------------
331template<class TYPE, bool StackAlloc>
333 count(rhs.count),
334 elements(rhs.elements)
335{
336 if constexpr (StackAlloc)
337 {
338 this->Alloc(rhs.count);
339 if constexpr (!std::is_trivially_copyable<TYPE>::value)
340 {
341 IndexT i;
342 for (i = 0; i < this->count; i++)
343 {
344 this->elements[i] = rhs.Begin()[i];
345 }
346 }
347 else
348 memcpy(this->elements, rhs.Begin(), this->count * sizeof(TYPE));
349 }
350 else
351 {
352 rhs.count = 0;
353 rhs.elements = nullptr;
354 }
355}
356
357//------------------------------------------------------------------------------
360template<class TYPE, bool StackAlloc>
361FixedArray<TYPE, StackAlloc>::FixedArray(std::initializer_list<TYPE> list) :
362 count(0),
363 elements(nullptr)
364{
365 this->Alloc((SizeT)list.size());
366 if constexpr (!std::is_trivially_copyable<TYPE>::value)
367 {
368 IndexT i;
369 for (i = 0; i < this->count; i++)
370 {
371 this->elements[i] = list.begin()[i];
372 }
373 }
374 else
375 memcpy(this->elements, list.begin(), this->count * sizeof(TYPE));
376}
377
378//------------------------------------------------------------------------------
381template<class TYPE, bool StackAlloc>
383 count(0),
384 elements(nullptr)
385{
386}
387
388//------------------------------------------------------------------------------
391template<class TYPE, bool StackAlloc>
396
397//------------------------------------------------------------------------------
400template<class TYPE, bool StackAlloc> void
402{
403 if (this != &rhs)
404 {
405 this->Delete();
406 this->Copy(rhs);
407 }
408}
409
410//------------------------------------------------------------------------------
413template<class TYPE, bool StackAlloc> void
415{
416 if (this != &rhs)
417 {
418 this->Delete();
419 this->elements = rhs.elements;
420 this->count = rhs.count;
421 rhs.elements = nullptr;
422 rhs.count = 0;
423 }
424}
425
426//------------------------------------------------------------------------------
429template<class TYPE, bool StackAlloc> TYPE&
431{
432 #if NEBULA_BOUNDSCHECKS
433 n_assert(this->elements && (index < this->count));
434 #endif
435 return this->elements[index];
436}
437
438//------------------------------------------------------------------------------
441template<class TYPE, bool StackAlloc> bool
443{
444 if (this->count != rhs.count)
445 {
446 return false;
447 }
448 else
449 {
450 #if NEBULA_BOUNDSCHECKS
451 n_assert(this->elements && rhs.elements);
452 #endif
453 IndexT i;
454 SizeT num = this->count;
455 for (i = 0; i < num; i++)
456 {
457 if (this->elements[i] != rhs.elements[i])
458 {
459 return false;
460 }
461 }
462 return true;
463 }
464}
465
466//------------------------------------------------------------------------------
469template<class TYPE, bool StackAlloc> bool
471{
472 return !(*this == rhs);
473}
474
475//------------------------------------------------------------------------------
478template<class TYPE, bool StackAlloc> void
480{
481 this->Delete();
482 this->Alloc(s);
483}
484
485//------------------------------------------------------------------------------
488template<class TYPE, bool StackAlloc> void
490{
491 // allocate new array and copy over old elements
492 if (newSize == this->count)
493 return;
494
495 TYPE* newElements = 0;
496 if (newSize > 0)
497 {
498 if constexpr (StackAlloc)
499 {
500 newElements = ArrayAllocStack<TYPE>(newSize);
501 }
502 else
503 {
504 newElements = ArrayAlloc<TYPE>(newSize);
505 }
506 SizeT numCopy = this->count;
507 if (numCopy > 0)
508 {
509 if (numCopy > newSize)
510 numCopy = newSize;
511 if constexpr (!std::is_trivially_move_assignable<TYPE>::value && std::is_move_assignable<TYPE>::value)
512 {
513 IndexT i;
514 for (i = 0; i < numCopy; i++)
515 {
516 newElements[i] = std::move(this->elements[i]);
517 }
518 }
519 else
520 {
521 Memory::MoveElements(this->elements, newElements, numCopy);
522 }
523 }
524 }
525
526 // delete old elements
527 this->Delete();
528
529 // set content to new elements
530 this->elements = newElements;
531 this->count = newSize;
532}
533
534//------------------------------------------------------------------------------
537template<class TYPE, bool StackAlloc> const SizeT
539{
540 return this->count;
541}
542
543//------------------------------------------------------------------------------
546template<class TYPE, bool StackAlloc> const SizeT
548{
549 return this->count * sizeof(TYPE);
550}
551
552//------------------------------------------------------------------------------
555template<class TYPE, bool StackAlloc> bool
557{
558 return 0 == this->count;
559}
560
561//------------------------------------------------------------------------------
564template<class TYPE, bool StackAlloc> void
569
570//------------------------------------------------------------------------------
573template<class TYPE, bool StackAlloc>
575{
576 if (this->count > 0)
577 {
578 if (std::is_trivially_destructible<TYPE>::value)
579 {
580 memset(this->elements, 0, this->count * sizeof(TYPE));
581 }
582 else
583 {
584 IndexT i;
585 for (i = 0; i < this->count; i++)
586 {
587 this->elements[i].~TYPE();
588 }
589 }
590 }
591}
592
593//------------------------------------------------------------------------------
596template<class TYPE, bool StackAlloc> void
598{
599 IndexT i;
600 for (i = 0; i < this->count; i++)
601 {
602 this->elements[i] = val;
603 }
604}
605
606//------------------------------------------------------------------------------
609template<class TYPE, bool StackAlloc> void
611{
612 #if NEBULA_BOUNDSCHECKS
613 n_assert((first + num) <= this->count);
614 n_assert(0 != this->elements);
615 #endif
616 IndexT i;
617 for (i = first; i < (first + num); i++)
618 {
619 this->elements[i] = val;
620 }
621}
622
623//------------------------------------------------------------------------------
626template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
628{
629 return this->elements;
630}
631
632//------------------------------------------------------------------------------
635template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
637{
638 return this->elements + this->count;
639}
640
641//------------------------------------------------------------------------------
644template<class TYPE, bool StackAlloc>
646{
647 return this->elements[0];
648}
649
650//------------------------------------------------------------------------------
653template<class TYPE, bool StackAlloc>
655{
656 return this->elements[this->count - 1];
657}
658
659//------------------------------------------------------------------------------
662template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
664{
665 IndexT i;
666 for (i = 0; i < this->count; i++)
667 {
668 if (elm == this->elements[i])
669 {
670 return &(this->elements[i]);
671 }
672 }
673 return 0;
674}
675
676//------------------------------------------------------------------------------
679template<class TYPE, bool StackAlloc> IndexT
681{
682 IndexT i;
683 for (i = 0; i < this->count; i++)
684 {
685 if (elm == this->elements[i])
686 {
687 return i;
688 }
689 }
690 return InvalidIndex;
691}
692
693//------------------------------------------------------------------------------
696template<class TYPE, bool StackAlloc> void
698{
699 std::sort(this->Begin(), this->End());
700}
701
702//------------------------------------------------------------------------------
706template<class TYPE, bool StackAlloc> IndexT
708{
709 SizeT num = this->Size();
710 if (num > 0)
711 {
712 IndexT half;
713 IndexT lo = 0;
714 IndexT hi = num - 1;
715 IndexT mid;
716 while (lo <= hi)
717 {
718 if (0 != (half = num/2))
719 {
720 mid = lo + ((num & 1) ? half : (half - 1));
721 if (elm < this->elements[mid])
722 {
723 hi = mid - 1;
724 num = num & 1 ? half : half - 1;
725 }
726 else if (elm > this->elements[mid])
727 {
728 lo = mid + 1;
729 num = half;
730 }
731 else
732 {
733 return mid;
734 }
735 }
736 else if (num)
737 {
738 if (elm != this->elements[lo])
739 {
740 return InvalidIndex;
741 }
742 else
743 {
744 return lo;
745 }
746 }
747 else
748 {
749 break;
750 }
751 }
752 }
753 return InvalidIndex;
754}
755
756//------------------------------------------------------------------------------
759template<class TYPE, bool StackAlloc> Array<TYPE>
761{
762 Array<TYPE> result;
763 result.Reserve(this->count);
764 IndexT i;
765 for (i = 0; i < this->count; i++)
766 {
767 result.Append(this->elements[i]);
768 }
769 return result;
770}
771
772//------------------------------------------------------------------------------
775template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
777{
778 return this->elements;
779}
780
781//------------------------------------------------------------------------------
784template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
786{
787 return this->elements + this->count;
788}
789
790//------------------------------------------------------------------------------
793template<class TYPE, bool StackAlloc> void
795{
796 n_error("Trying to resize a fixed array");
797}
798
799//------------------------------------------------------------------------------
802template<class TYPE, bool StackAlloc> size_t
804{
805 return this->count;
806}
807
808} // namespace Util
809//------------------------------------------------------------------------------
Definition half.h:20
Nebula's dynamic array class.
Definition array.h:60
void Reserve(SizeT num)
increase capacity to fit N more elements into the array.
Definition array.h:862
void Append(const TYPE &first, const ELEM_TYPE &... elements)
Append multiple elements to the end of the array.
Definition array.h:1334
Iterator Begin() const
return iterator to beginning of array
Definition array.h:1245
void Delete()
delete content
Definition fixedarray.h:132
void operator=(const FixedArray< TYPE, StackAlloc > &rhs)
assignment operator
Definition fixedarray.h:401
Iterator End() const
get iterator past last element
Definition fixedarray.h:636
IndexT BinarySearchIndex(const TYPE &val) const
do a binary search, requires a sorted array
Definition fixedarray.h:707
FixedArray(FixedArray< TYPE, StackAlloc > &&rhs)
move constructor
Definition fixedarray.h:332
TYPE & operator[](IndexT index) const
write [] operator
Definition fixedarray.h:430
Iterator Find(const TYPE &val) const
find identical element in unsorted array (slow)
Definition fixedarray.h:663
Array< TYPE > AsArray() const
return content as Array (slow!)
Definition fixedarray.h:760
void Fill(const TYPE &val)
fill the entire array with a value
Definition fixedarray.h:597
bool operator==(const FixedArray< TYPE, StackAlloc > &rhs) const
equality operator
Definition fixedarray.h:442
Iterator end() const
Definition fixedarray.h:785
FixedArray(const FixedArray< TYPE, false > &rhs)
copy constructor
Definition fixedarray.h:248
Iterator Begin() const
get iterator to first element
Definition fixedarray.h:627
FixedArray(const SizeT s)
constructor with size
Definition fixedarray.h:201
const SizeT ByteSize() const
get total byte size
Definition fixedarray.h:547
size_t size() const
Definition fixedarray.h:803
const SizeT Size() const
get number of elements
Definition fixedarray.h:538
void resize(size_t size)
Definition fixedarray.h:794
FixedArray(const FixedArray< TYPE, true > &rhs)
copy constructor
Definition fixedarray.h:224
TYPE & Back() const
return reference to last element
Definition fixedarray.h:654
IndexT FindIndex(const TYPE &val) const
find index of identical element in unsorted array (slow)
Definition fixedarray.h:680
TYPE & Front() const
return reference to first element
Definition fixedarray.h:645
void operator=(FixedArray< TYPE, StackAlloc > &&rhs) noexcept
move assignment operator
Definition fixedarray.h:414
bool operator!=(const FixedArray< TYPE, StackAlloc > &rhs) const
inequality operator
Definition fixedarray.h:470
void Clear()
clear the array, free elements
Definition fixedarray.h:565
ComponentId * Iterator
Definition fixedarray.h:23
FixedArray()
default constructor
Definition fixedarray.h:121
FixedArray(std::initializer_list< TYPE > list)
constructor from initializer list
Definition fixedarray.h:361
bool IsEmpty() const
return true if array if empty (has no elements)
Definition fixedarray.h:556
void Fill(IndexT first, SizeT num, const TYPE &val)
fill array range with element
Definition fixedarray.h:610
FixedArray(const Array< TYPE > &rhs)
construct from array
Definition fixedarray.h:272
void Resize(SizeT newSize)
resize array without deleting existing content
Definition fixedarray.h:489
void Reset()
Reset the size and destroy all elements.
Definition fixedarray.h:574
void SetSize(SizeT s)
set number of elements (clears existing content)
Definition fixedarray.h:479
~FixedArray()
destructor
Definition fixedarray.h:392
ComponentId * elements
Definition fixedarray.h:113
void Copy(const FixedArray< TYPE, StackAlloc > &src)
copy content
Definition fixedarray.h:179
friend class FixedArray
Definition fixedarray.h:103
void Alloc(SizeT s)
allocate array for given size
Definition fixedarray.h:155
FixedArray(const SizeT s, const TYPE &initialValue)
constructor with size and initial value
Definition fixedarray.h:212
FixedArray(std::nullptr_t)
construct an empty fixed array
Definition fixedarray.h:382
SizeT count
Definition fixedarray.h:112
FixedArray(Array< TYPE > &&rhs)
move from array
Definition fixedarray.h:296
Iterator begin() const
for range-based iteration (C++11)
Definition fixedarray.h:776
void Sort()
sort the array
Definition fixedarray.h:697
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 ArrayFreeStack(size_t size, TYPE *buffer)
Definition memory.h:205
TYPE * ArrayAllocStack(size_t size)
Definition memory.h:155
void ArrayFree(size_t size, TYPE *buffer)
Definition memory.h:188
TYPE * ArrayAlloc(size_t size)
Definition memory.h:137
__forceinline void MoveElements(const T *from, T *to, size_t numElements)
Move a chunk of memory, can handle overlapping regions.
Definition posixmemory.h:197
A quad tree designed to return regions of free 2D space.
Definition String.cs:6
#define StackAlloc(size)
Definition posixmemory.h:31
static const int InvalidIndex
Definition types.h:47
int SizeT
Definition types.h:42
int IndexT
Definition types.h:41