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 Iterator Find(const TYPE& val) const;
83 IndexT FindIndex(const TYPE& val) const;
85 void Sort();
87 IndexT BinarySearchIndex(const TYPE& val) const;
90
92 Iterator begin() const;
93 Iterator end() const;
94 size_t size() const;
95 void resize(size_t size);
96private:
97
98 template<class T, bool S>
99 friend class FixedArray;
100
102 void Delete();
104 void Alloc(SizeT s);
107
109 TYPE* elements;
110};
111
112
113//------------------------------------------------------------------------------
116template<class TYPE, bool StackAlloc>
118 count(0),
119 elements(nullptr)
120{
121 // empty
122}
123
124//------------------------------------------------------------------------------
127template<class TYPE, bool StackAlloc> void
129{
130 if (this->elements)
131 {
132 if constexpr (StackAlloc)
133 {
134 ArrayFreeStack(this->count, this->elements);
135 }
136 else
137 {
138 ArrayFree(this->count, this->elements);
139 }
140
141 this->elements = nullptr;
142
143 }
144 this->count = 0;
145}
146
147//------------------------------------------------------------------------------
150template<class TYPE, bool StackAlloc> void
152{
153 #if NEBULA_BOUNDSCHECKS
154 n_assert(0 == this->elements);
155 #endif
156 if (s > 0)
157 {
158 if constexpr (StackAlloc)
159 {
161 }
162 else
163 {
164 this->elements = ArrayAlloc<TYPE>(s);
165 }
166 }
167 this->count = s;
168}
169
170//------------------------------------------------------------------------------
174template<class TYPE, bool StackAlloc> void
176{
177 if (this->elements != rhs.elements && rhs.count > 0)
178 {
179 this->Alloc(rhs.count);
180 if constexpr (!std::is_trivially_copyable<TYPE>::value)
181 {
182 IndexT i;
183 for (i = 0; i < this->count; i++)
184 {
185 this->elements[i] = rhs.elements[i];
186 }
187 }
188 else
189 memcpy(this->elements, rhs.elements, this->count * sizeof(TYPE));
190 }
191}
192
193//------------------------------------------------------------------------------
196template<class TYPE, bool StackAlloc>
198 count(0),
199 elements(nullptr)
200{
201 this->Alloc(s);
202}
203
204//------------------------------------------------------------------------------
207template<class TYPE, bool StackAlloc>
208FixedArray<TYPE, StackAlloc>::FixedArray(const SizeT s, const TYPE& initialValue) :
209 count(0),
210 elements(nullptr)
211{
212 this->Alloc(s);
213 this->Fill(initialValue);
214}
215
216//------------------------------------------------------------------------------
219template<class TYPE, bool StackAlloc>
221 count(0),
222 elements(nullptr)
223{
224 if (this->elements != rhs.elements && rhs.count > 0)
225 {
226 this->Alloc(rhs.count);
227 if constexpr (!std::is_trivially_copyable<TYPE>::value)
228 {
229 IndexT i;
230 for (i = 0; i < this->count; i++)
231 {
232 this->elements[i] = rhs.elements[i];
233 }
234 }
235 else
236 memcpy(this->elements, rhs.elements, this->count * sizeof(TYPE));
237 }
238}
239
240//------------------------------------------------------------------------------
243template<class TYPE, bool StackAlloc>
245 count(0),
246 elements(nullptr)
247{
248 if (this->elements != rhs.elements && rhs.count > 0)
249 {
250 this->Alloc(rhs.count);
251 if constexpr (!std::is_trivially_copyable<TYPE>::value)
252 {
253 IndexT i;
254 for (i = 0; i < this->count; i++)
255 {
256 this->elements[i] = rhs.elements[i];
257 }
258 }
259 else
260 memcpy(this->elements, rhs.elements, this->count * sizeof(TYPE));
261 }
262}
263
264//------------------------------------------------------------------------------
267template<class TYPE, bool StackAlloc>
269 count(rhs.Size()),
270 elements(nullptr)
271{
272 if (this->count > 0)
273 {
274 this->Alloc(this->count);
275 if constexpr (!std::is_trivially_copyable<TYPE>::value)
276 {
277 IndexT i;
278 for (i = 0; i < this->count; i++)
279 {
280 this->elements[i] = rhs.Begin()[i];
281 }
282 }
283 else
284 memcpy(this->elements, rhs.Begin(), this->count * sizeof(TYPE));
285 }
286}
287
288//------------------------------------------------------------------------------
291template<class TYPE, bool StackAlloc>
293 : elements(nullptr)
294 , count(0)
295{
296 // If array lives on the stack, then we need to allocate
297 if (rhs.count > 0)
298 {
299 if (rhs.stackElements.data() == rhs.elements || StackAlloc)
300 {
301 this->Alloc(rhs.count);
302 if constexpr (!std::is_trivially_copyable<TYPE>::value)
303 {
304 IndexT i;
305 for (i = 0; i < this->count; i++)
306 {
307 this->elements[i] = rhs.Begin()[i];
308 }
309 }
310 else
311 memcpy(this->elements, rhs.Begin(), this->count * sizeof(TYPE));
312 }
313 else
314 {
315 this->elements = rhs.elements;
316 rhs.elements = nullptr;
317 this->count = rhs.count;
318 rhs.capacity = 0;
319 rhs.count = 0;
320 }
321 }
322}
323
324//------------------------------------------------------------------------------
327template<class TYPE, bool StackAlloc>
329 count(rhs.count),
330 elements(rhs.elements)
331{
332 if constexpr (StackAlloc)
333 {
334 this->Alloc(rhs.count);
335 if constexpr (!std::is_trivially_copyable<TYPE>::value)
336 {
337 IndexT i;
338 for (i = 0; i < this->count; i++)
339 {
340 this->elements[i] = rhs.Begin()[i];
341 }
342 }
343 else
344 memcpy(this->elements, rhs.Begin(), this->count * sizeof(TYPE));
345 }
346 else
347 {
348 rhs.count = 0;
349 rhs.elements = nullptr;
350 }
351}
352
353//------------------------------------------------------------------------------
356template<class TYPE, bool StackAlloc>
357FixedArray<TYPE, StackAlloc>::FixedArray(std::initializer_list<TYPE> list) :
358 count(0),
359 elements(nullptr)
360{
361 this->Alloc((SizeT)list.size());
362 if constexpr (!std::is_trivially_copyable<TYPE>::value)
363 {
364 IndexT i;
365 for (i = 0; i < this->count; i++)
366 {
367 this->elements[i] = list.begin()[i];
368 }
369 }
370 else
371 memcpy(this->elements, list.begin(), this->count * sizeof(TYPE));
372}
373
374//------------------------------------------------------------------------------
377template<class TYPE, bool StackAlloc>
379 count(0),
380 elements(nullptr)
381{
382}
383
384//------------------------------------------------------------------------------
387template<class TYPE, bool StackAlloc>
392
393//------------------------------------------------------------------------------
396template<class TYPE, bool StackAlloc> void
398{
399 if (this != &rhs)
400 {
401 this->Delete();
402 this->Copy(rhs);
403 }
404}
405
406//------------------------------------------------------------------------------
409template<class TYPE, bool StackAlloc> void
411{
412 if (this != &rhs)
413 {
414 this->Delete();
415 this->elements = rhs.elements;
416 this->count = rhs.count;
417 rhs.elements = nullptr;
418 rhs.count = 0;
419 }
420}
421
422//------------------------------------------------------------------------------
425template<class TYPE, bool StackAlloc> TYPE&
427{
428 #if NEBULA_BOUNDSCHECKS
429 n_assert(this->elements && (index < this->count));
430 #endif
431 return this->elements[index];
432}
433
434//------------------------------------------------------------------------------
437template<class TYPE, bool StackAlloc> bool
439{
440 if (this->count != rhs.count)
441 {
442 return false;
443 }
444 else
445 {
446 #if NEBULA_BOUNDSCHECKS
447 n_assert(this->elements && rhs.elements);
448 #endif
449 IndexT i;
450 SizeT num = this->count;
451 for (i = 0; i < num; i++)
452 {
453 if (this->elements[i] != rhs.elements[i])
454 {
455 return false;
456 }
457 }
458 return true;
459 }
460}
461
462//------------------------------------------------------------------------------
465template<class TYPE, bool StackAlloc> bool
467{
468 return !(*this == rhs);
469}
470
471//------------------------------------------------------------------------------
474template<class TYPE, bool StackAlloc> void
476{
477 this->Delete();
478 this->Alloc(s);
479}
480
481//------------------------------------------------------------------------------
484template<class TYPE, bool StackAlloc> void
486{
487 // allocate new array and copy over old elements
488 if (newSize == this->count)
489 return;
490
491 TYPE* newElements = 0;
492 if (newSize > 0)
493 {
494 if constexpr (StackAlloc)
495 {
496 newElements = ArrayAllocStack<TYPE>(newSize);
497 }
498 else
499 {
500 newElements = ArrayAlloc<TYPE>(newSize);
501 }
502 SizeT numCopy = this->count;
503 if (numCopy > 0)
504 {
505 if (numCopy > newSize)
506 numCopy = newSize;
507 if constexpr (!std::is_trivially_move_assignable<TYPE>::value && std::is_move_assignable<TYPE>::value)
508 {
509 IndexT i;
510 for (i = 0; i < numCopy; i++)
511 {
512 newElements[i] = std::move(this->elements[i]);
513 }
514 }
515 else
516 {
517 Memory::MoveElements(this->elements, newElements, numCopy);
518 }
519 }
520 }
521
522 // delete old elements
523 this->Delete();
524
525 // set content to new elements
526 this->elements = newElements;
527 this->count = newSize;
528}
529
530//------------------------------------------------------------------------------
533template<class TYPE, bool StackAlloc> const SizeT
535{
536 return this->count;
537}
538
539//------------------------------------------------------------------------------
542template<class TYPE, bool StackAlloc> const SizeT
544{
545 return this->count * sizeof(TYPE);
546}
547
548//------------------------------------------------------------------------------
551template<class TYPE, bool StackAlloc> bool
553{
554 return 0 == this->count;
555}
556
557//------------------------------------------------------------------------------
560template<class TYPE, bool StackAlloc> void
565
566//------------------------------------------------------------------------------
569template<class TYPE, bool StackAlloc>
571{
572 if (this->count > 0)
573 {
574 if (std::is_trivially_destructible<TYPE>::value)
575 {
576 memset(this->elements, 0, this->count * sizeof(TYPE));
577 }
578 else
579 {
580 IndexT i;
581 for (i = 0; i < this->count; i++)
582 {
583 this->elements[i].~TYPE();
584 }
585 }
586 }
587 this->count = 0;
588}
589
590//------------------------------------------------------------------------------
593template<class TYPE, bool StackAlloc> void
595{
596 IndexT i;
597 for (i = 0; i < this->count; i++)
598 {
599 this->elements[i] = val;
600 }
601}
602
603//------------------------------------------------------------------------------
606template<class TYPE, bool StackAlloc> void
608{
609 #if NEBULA_BOUNDSCHECKS
610 n_assert((first + num) <= this->count);
611 n_assert(0 != this->elements);
612 #endif
613 IndexT i;
614 for (i = first; i < (first + num); i++)
615 {
616 this->elements[i] = val;
617 }
618}
619
620//------------------------------------------------------------------------------
623template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
625{
626 return this->elements;
627}
628
629//------------------------------------------------------------------------------
632template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
634{
635 return this->elements + this->count;
636}
637
638//------------------------------------------------------------------------------
641template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
643{
644 IndexT i;
645 for (i = 0; i < this->count; i++)
646 {
647 if (elm == this->elements[i])
648 {
649 return &(this->elements[i]);
650 }
651 }
652 return 0;
653}
654
655//------------------------------------------------------------------------------
658template<class TYPE, bool StackAlloc> IndexT
660{
661 IndexT i;
662 for (i = 0; i < this->count; i++)
663 {
664 if (elm == this->elements[i])
665 {
666 return i;
667 }
668 }
669 return InvalidIndex;
670}
671
672//------------------------------------------------------------------------------
675template<class TYPE, bool StackAlloc> void
677{
678 std::sort(this->Begin(), this->End());
679}
680
681//------------------------------------------------------------------------------
685template<class TYPE, bool StackAlloc> IndexT
687{
688 SizeT num = this->Size();
689 if (num > 0)
690 {
691 IndexT half;
692 IndexT lo = 0;
693 IndexT hi = num - 1;
694 IndexT mid;
695 while (lo <= hi)
696 {
697 if (0 != (half = num/2))
698 {
699 mid = lo + ((num & 1) ? half : (half - 1));
700 if (elm < this->elements[mid])
701 {
702 hi = mid - 1;
703 num = num & 1 ? half : half - 1;
704 }
705 else if (elm > this->elements[mid])
706 {
707 lo = mid + 1;
708 num = half;
709 }
710 else
711 {
712 return mid;
713 }
714 }
715 else if (num)
716 {
717 if (elm != this->elements[lo])
718 {
719 return InvalidIndex;
720 }
721 else
722 {
723 return lo;
724 }
725 }
726 else
727 {
728 break;
729 }
730 }
731 }
732 return InvalidIndex;
733}
734
735//------------------------------------------------------------------------------
738template<class TYPE, bool StackAlloc> Array<TYPE>
740{
741 Array<TYPE> result;
742 result.Reserve(this->count);
743 IndexT i;
744 for (i = 0; i < this->count; i++)
745 {
746 result.Append(this->elements[i]);
747 }
748 return result;
749}
750
751//------------------------------------------------------------------------------
754template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
756{
757 return this->elements;
758}
759
760//------------------------------------------------------------------------------
763template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
765{
766 return this->elements + this->count;
767}
768
769//------------------------------------------------------------------------------
772template<class TYPE, bool StackAlloc> void
774{
775 n_error("Trying to resize a fixed array");
776}
777
778//------------------------------------------------------------------------------
781template<class TYPE, bool StackAlloc> size_t
783{
784 return this->count;
785}
786
787} // namespace Util
788//------------------------------------------------------------------------------
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:128
void operator=(const FixedArray< TYPE, StackAlloc > &rhs)
assignment operator
Definition fixedarray.h:397
Iterator End() const
get iterator past last element
Definition fixedarray.h:633
IndexT BinarySearchIndex(const TYPE &val) const
do a binary search, requires a sorted array
Definition fixedarray.h:686
FixedArray(FixedArray< TYPE, StackAlloc > &&rhs)
move constructor
Definition fixedarray.h:328
TYPE & operator[](IndexT index) const
write [] operator
Definition fixedarray.h:426
Iterator Find(const TYPE &val) const
find identical element in unsorted array (slow)
Definition fixedarray.h:642
Array< TYPE > AsArray() const
return content as Array (slow!)
Definition fixedarray.h:739
void Fill(const TYPE &val)
fill the entire array with a value
Definition fixedarray.h:594
bool operator==(const FixedArray< TYPE, StackAlloc > &rhs) const
equality operator
Definition fixedarray.h:438
Iterator end() const
Definition fixedarray.h:764
FixedArray(const FixedArray< TYPE, false > &rhs)
copy constructor
Definition fixedarray.h:244
Iterator Begin() const
get iterator to first element
Definition fixedarray.h:624
FixedArray(const SizeT s)
constructor with size
Definition fixedarray.h:197
const SizeT ByteSize() const
get total byte size
Definition fixedarray.h:543
size_t size() const
Definition fixedarray.h:782
const SizeT Size() const
get number of elements
Definition fixedarray.h:534
void resize(size_t size)
Definition fixedarray.h:773
FixedArray(const FixedArray< TYPE, true > &rhs)
copy constructor
Definition fixedarray.h:220
IndexT FindIndex(const TYPE &val) const
find index of identical element in unsorted array (slow)
Definition fixedarray.h:659
void operator=(FixedArray< TYPE, StackAlloc > &&rhs) noexcept
move assignment operator
Definition fixedarray.h:410
bool operator!=(const FixedArray< TYPE, StackAlloc > &rhs) const
inequality operator
Definition fixedarray.h:466
void Clear()
clear the array, free elements
Definition fixedarray.h:561
ComponentId * Iterator
Definition fixedarray.h:23
FixedArray()
default constructor
Definition fixedarray.h:117
FixedArray(std::initializer_list< TYPE > list)
constructor from initializer list
Definition fixedarray.h:357
bool IsEmpty() const
return true if array if empty (has no elements)
Definition fixedarray.h:552
void Fill(IndexT first, SizeT num, const TYPE &val)
fill array range with element
Definition fixedarray.h:607
FixedArray(const Array< TYPE > &rhs)
construct from array
Definition fixedarray.h:268
void Resize(SizeT newSize)
resize array without deleting existing content
Definition fixedarray.h:485
void Reset()
Reset the size and destroy all elements.
Definition fixedarray.h:570
void SetSize(SizeT s)
set number of elements (clears existing content)
Definition fixedarray.h:475
~FixedArray()
destructor
Definition fixedarray.h:388
ComponentId * elements
Definition fixedarray.h:109
void Copy(const FixedArray< TYPE, StackAlloc > &src)
copy content
Definition fixedarray.h:175
friend class FixedArray
Definition fixedarray.h:99
void Alloc(SizeT s)
allocate array for given size
Definition fixedarray.h:151
FixedArray(const SizeT s, const TYPE &initialValue)
constructor with size and initial value
Definition fixedarray.h:208
FixedArray(std::nullptr_t)
construct an empty fixed array
Definition fixedarray.h:378
SizeT count
Definition fixedarray.h:108
FixedArray(Array< TYPE > &&rhs)
move from array
Definition fixedarray.h:292
Iterator begin() const
for range-based iteration (C++11)
Definition fixedarray.h:755
void Sort()
sort the array
Definition fixedarray.h:676
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:134
TYPE * ArrayAllocStack(size_t size)
Definition memory.h:87
void ArrayFree(size_t size, TYPE *buffer)
Definition memory.h:117
TYPE * ArrayAlloc(size_t size)
Definition memory.h:69
__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 pinned array is an array which manages its own virtual memory.
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