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}
588
589//------------------------------------------------------------------------------
592template<class TYPE, bool StackAlloc> void
594{
595 IndexT i;
596 for (i = 0; i < this->count; i++)
597 {
598 this->elements[i] = val;
599 }
600}
601
602//------------------------------------------------------------------------------
605template<class TYPE, bool StackAlloc> void
607{
608 #if NEBULA_BOUNDSCHECKS
609 n_assert((first + num) <= this->count);
610 n_assert(0 != this->elements);
611 #endif
612 IndexT i;
613 for (i = first; i < (first + num); i++)
614 {
615 this->elements[i] = val;
616 }
617}
618
619//------------------------------------------------------------------------------
622template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
624{
625 return this->elements;
626}
627
628//------------------------------------------------------------------------------
631template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
633{
634 return this->elements + this->count;
635}
636
637//------------------------------------------------------------------------------
640template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
642{
643 IndexT i;
644 for (i = 0; i < this->count; i++)
645 {
646 if (elm == this->elements[i])
647 {
648 return &(this->elements[i]);
649 }
650 }
651 return 0;
652}
653
654//------------------------------------------------------------------------------
657template<class TYPE, bool StackAlloc> IndexT
659{
660 IndexT i;
661 for (i = 0; i < this->count; i++)
662 {
663 if (elm == this->elements[i])
664 {
665 return i;
666 }
667 }
668 return InvalidIndex;
669}
670
671//------------------------------------------------------------------------------
674template<class TYPE, bool StackAlloc> void
676{
677 std::sort(this->Begin(), this->End());
678}
679
680//------------------------------------------------------------------------------
684template<class TYPE, bool StackAlloc> IndexT
686{
687 SizeT num = this->Size();
688 if (num > 0)
689 {
690 IndexT half;
691 IndexT lo = 0;
692 IndexT hi = num - 1;
693 IndexT mid;
694 while (lo <= hi)
695 {
696 if (0 != (half = num/2))
697 {
698 mid = lo + ((num & 1) ? half : (half - 1));
699 if (elm < this->elements[mid])
700 {
701 hi = mid - 1;
702 num = num & 1 ? half : half - 1;
703 }
704 else if (elm > this->elements[mid])
705 {
706 lo = mid + 1;
707 num = half;
708 }
709 else
710 {
711 return mid;
712 }
713 }
714 else if (num)
715 {
716 if (elm != this->elements[lo])
717 {
718 return InvalidIndex;
719 }
720 else
721 {
722 return lo;
723 }
724 }
725 else
726 {
727 break;
728 }
729 }
730 }
731 return InvalidIndex;
732}
733
734//------------------------------------------------------------------------------
737template<class TYPE, bool StackAlloc> Array<TYPE>
739{
740 Array<TYPE> result;
741 result.Reserve(this->count);
742 IndexT i;
743 for (i = 0; i < this->count; i++)
744 {
745 result.Append(this->elements[i]);
746 }
747 return result;
748}
749
750//------------------------------------------------------------------------------
753template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
755{
756 return this->elements;
757}
758
759//------------------------------------------------------------------------------
762template<class TYPE, bool StackAlloc> typename FixedArray<TYPE, StackAlloc>::Iterator
764{
765 return this->elements + this->count;
766}
767
768//------------------------------------------------------------------------------
771template<class TYPE, bool StackAlloc> void
773{
774 n_error("Trying to resize a fixed array");
775}
776
777//------------------------------------------------------------------------------
780template<class TYPE, bool StackAlloc> size_t
782{
783 return this->count;
784}
785
786} // namespace Util
787//------------------------------------------------------------------------------
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:632
IndexT BinarySearchIndex(const TYPE &val) const
do a binary search, requires a sorted array
Definition fixedarray.h:685
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:641
Array< TYPE > AsArray() const
return content as Array (slow!)
Definition fixedarray.h:738
void Fill(const TYPE &val)
fill the entire array with a value
Definition fixedarray.h:593
bool operator==(const FixedArray< TYPE, StackAlloc > &rhs) const
equality operator
Definition fixedarray.h:438
Iterator end() const
Definition fixedarray.h:763
FixedArray(const FixedArray< TYPE, false > &rhs)
copy constructor
Definition fixedarray.h:244
Iterator Begin() const
get iterator to first element
Definition fixedarray.h:623
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:781
const SizeT Size() const
get number of elements
Definition fixedarray.h:534
void resize(size_t size)
Definition fixedarray.h:772
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:658
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:606
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:754
void Sort()
sort the array
Definition fixedarray.h:675
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 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