fennec
Loading...
Searching...
No Matches
dynarray.h
Go to the documentation of this file.
1// =====================================================================================================================
2// fennec, a free and open source game engine
3// Copyright © 2025 Medusa Slockbower
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17// =====================================================================================================================
18
30
31#ifndef FENNEC_CONTAINERS_DYNARRAY_H
32#define FENNEC_CONTAINERS_DYNARRAY_H
33
35#include <fennec/lang/utility.h>
37#include <fennec/memory/new.h>
38
39namespace fennec
40{
41
63template<class TypeT, class Alloc = allocator<TypeT>>
64struct dynarray {
65public:
66
67// Definitions =========================================================================================================
68
69 using value_t = TypeT;
70 using alloc_t = Alloc;
71
72
73// Constructors ========================================================================================================
74
77
80 constexpr dynarray()
81 : _alloc(8)
82 , _size(0) {
83 }
84
89 explicit constexpr dynarray(const alloc_t& alloc)
90 : _alloc(8, alloc)
91 , _size(0) {
92 }
93
98 explicit constexpr dynarray(alloc_t&& alloc) noexcept
99 : _alloc(8, alloc)
100 , _size(0) {
101 }
102
106 explicit constexpr dynarray(size_t n)
107 : _alloc(n)
108 , _size(n)
109 {
110 value_t* addr = _alloc.data();
111 for(; n > 0; --n, ++addr) {
112 fennec::construct(addr);
113 }
114 }
115
121 constexpr dynarray(size_t n, const alloc_t& alloc)
122 : _alloc(n, alloc)
123 , _size(n) {
124 value_t* addr = _alloc.data();
125 for(; n > 0; --n, ++addr) {
126 fennec::construct(addr);
127 }
128 }
129
135 constexpr dynarray(size_t n, alloc_t&& alloc)
136 : _alloc(n, alloc)
137 , _size(n) {
138 value_t* addr = _alloc.data();
139 for(; n > 0; --n, ++addr) {
140 fennec::construct(addr);
141 }
142 }
143
149 constexpr dynarray(size_t n, const TypeT& val)
150 : _alloc(n)
151 , _size(n) {
152 value_t* addr = _alloc.data();
153 for(; n > 0; --n, ++addr) {
154 fennec::construct(addr, val);
155 }
156 }
157
158 // This constructor should not be invokable since moving is a single object operation and will cause undefined
159 // behaviour when moving to multiple elements
160 constexpr dynarray(size_t n, TypeT&& val) = delete;
161
167 template<typename...ArgsT>
168 constexpr explicit dynarray(size_t n, ArgsT&&...args)
169 : _alloc(n)
170 , _size(n) {
171 for(; n > 0; --n) {
172 fennec::construct(&_alloc[n], fennec::forward<ArgsT>(args)...);
173 }
174 }
175
180 template<size_t N>
181 constexpr dynarray(const TypeT (&arr)[N])
182 : _alloc(N)
183 , _size(N) {
184 for (size_t i = 0; i < N; ++i) {
185 _alloc[i] = arr[i];
186 }
187 }
188
193 template<size_t N>
194 constexpr dynarray(TypeT (&&arr)[N])
195 : _alloc(N)
196 , _size(N) {
197 for (size_t i = 0; i < N; ++i) {
198 _alloc[i] = fennec::move(arr[i]);
199 }
200 }
201
207 template<typename OTypeT, class OAlloc>
208 constexpr dynarray(const dynarray<OTypeT, OAlloc>& conv)
209 : _alloc(conv.size())
210 , _size(conv.size()) {
211 size_t i = 0;
212 for (const auto& it : conv) {
213 fennec::construct(&_alloc[i++], it);
214 }
215 }
216
221 constexpr dynarray(initializer_list<value_t> l, const alloc_t& alloc = alloc_t())
222 : _alloc(l.size(), alloc)
223 , _size(l.size()) {
224 size_t i = 0;
225 for (auto& it : l) {
226 fennec::construct(&_alloc[i++], fennec::move(it));
227 }
228 }
229
233 constexpr dynarray(const dynarray& arr)
234 : _alloc(arr._size)
235 , _size(arr._size) {
236 for (size_t i = 0; i < _size; ++i) {
237 fennec::construct(&_alloc[i], arr[i]);
238 }
239 }
240
244 constexpr dynarray(dynarray&& arr) noexcept
245 : _alloc(fennec::move(arr._alloc))
246 , _size(arr._size) {
247 arr._size = 0;
248 }
249
252 constexpr ~dynarray() {
253 value_t* addr = _alloc.data();
254 if (addr == nullptr) return;
255 for(int n = _size; n > 0; --n, ++addr) {
256 fennec::destruct(addr);
257 }
258 }
259
261
262// Assignment ==========================================================================================================
263
266
271 constexpr dynarray& operator=(const dynarray& arr) {
272 this->clear();
273 _alloc.creallocate(_size = arr._size);
274 for (size_t i = 0; i < _size; ++i) {
275 fennec::construct(&_alloc[i], fennec::copy(arr[i]));
276 }
277 return *this;
278 }
279
284 constexpr dynarray& operator=(dynarray&& arr) noexcept {
285 this->clear();
286 _alloc = fennec::move(arr._alloc);
287 _size = arr._size;
288 arr._size = 0;
289 return *this;
290 }
291
297 template<size_t N>
298 constexpr dynarray& operator=(const TypeT (&arr)[N]) {
299 this->clear();
300 _alloc.creallocate(_size = N);
301 for (size_t i = 0; i < _size; ++i) {
302 fennec::construct(&_alloc[i], fennec::copy(arr[i]));
303 }
304 return *this;
305 }
306
312 template<size_t N>
313 constexpr dynarray& operator=(TypeT (&&arr)[N]) {
314 this->clear();
315 _alloc.creallocate(_size = N);
316 for (size_t i = 0; i < _size; ++i) {
317 fennec::construct(&_alloc[i], fennec::move(arr[i]));
318 }
319 return *this;
320 }
321
323
324// Properties ==========================================================================================================
325
328
331 constexpr size_t size() const {
332 return _size;
333 }
334
337 constexpr size_t capacity() const {
338 return _alloc.capacity();
339 }
340
343 constexpr bool empty() const {
344 return _size == 0;
345 }
346
348
349
350// Element Access ======================================================================================================
351
354
359 constexpr TypeT& operator[](size_t i) {
360 assertd(i < _size, "Array Out of Bounds");
361 return _alloc.data()[i];
362 }
363
368 constexpr const TypeT& operator[](size_t i) const {
369 assertd(i < _size, "Array Out of Bounds");
370 return _alloc.data()[i];
371 }
372
375 constexpr TypeT& front() {
376 return this->operator[](0);
377 }
378
381 constexpr const TypeT& front() const {
382 return this->operator[](0);
383 }
384
387 constexpr TypeT& back() {
388 return this->operator[](size() - 1);
389 }
390
393 constexpr const TypeT& back() const {
394 return this->operator[](size() - 1);
395 }
396
398
399
400// Modifiers ===========================================================================================================
401
404
409 constexpr void insert(size_t i, TypeT&& val) {
410
411 // Grow if the size has reached the capacity of the allocation
412 if(_size == capacity()) {
413 _grow();
414 }
415
416 // Move the data if we are not inserting at the end of the array
417 if((i = min(i, _size)) < _size) {
418 fennec::memmove(
419 (void*)(_alloc.data() + i + 1)
420 , (void*)(_alloc.data() + i)
421 , (_size - i) * sizeof(TypeT));
422 }
423
424 // Insert the element
425 fennec::construct(_alloc.data() + i, fennec::forward<TypeT>(val));
426 ++_size;
427 }
428
433 constexpr void insert(size_t i, const TypeT& val) {
434
435 // Grow if the size has reached the capacity of the allocation
436 if(_size == capacity()) {
437 _grow();
438 }
439
440 // Move the data if we are not inserting at the end of the array
441 if((i = min(i, _size)) < _size) {
442 fennec::memmove(
443 (void*)(_alloc.data() + i),
444 (void*)(_alloc.data() + i + 1),
445 (_size - i) * sizeof(TypeT)
446 );
447 }
448
449 // Insert the element
450 fennec::construct(_alloc.data() + i, val);
451 ++_size;
452 }
453
459 template<typename...ArgsT>
460 constexpr void emplace(size_t i, ArgsT&&...args) {
461
462 // Grow if the size has reached the capacity of the allocation
463 if(_size == capacity()) {
464 _grow();
465 }
466
467 // Move the data if we are not inserting at the end of the array
468 if((i = min(i, _size)) < _size) {
469 fennec::memmove(
470 (void*)(_alloc.data() + i)
471 , (void*)(_alloc.data() + i + 1)
472 , (_size - i) * sizeof(TypeT));
473 }
474
475 // Insert the element
476 fennec::construct(_alloc.data() + i, fennec::forward<ArgsT>(args)...);
477 ++_size;
478 }
479
483 constexpr void push_back(const TypeT& val) {
484 dynarray::insert(_size, val);
485 }
486
490 constexpr void push_back(TypeT&& val) {
491 dynarray::insert(_size, fennec::forward<TypeT>(val));
492 }
493
498 template<typename...ArgsT>
499 constexpr void emplace_back(ArgsT...args) {
500 dynarray::emplace(_size, fennec::forward<ArgsT>(args)...);
501 }
502
505 constexpr void pop_back() {
506 fennec::destruct(&_alloc[--_size]);
507 }
508
512 constexpr void resize(size_t n) {
513 _alloc.creallocate(n);
514
515 while (_size < n) {
516 emplace_back();
517 }
518 }
519
524 constexpr void resize(size_t n, const TypeT& val) {
525 _alloc.creallocate(n);
526
527 while (_size < n) {
528 emplace_back(val);
529 }
530 }
531
534 constexpr void clear() {
535 while (_size > 0) {
536 fennec::destruct(&_alloc[--_size]);
537 }
538 _alloc.deallocate();
539 }
540
542
543
544// Iteration ===========================================================================================================
545
548
552 constexpr TypeT* begin() { return _alloc.data(); }
553
557 constexpr TypeT* end() { return begin() + _size; }
558
562 constexpr const TypeT* begin() const { return _alloc; }
563
567 constexpr const TypeT* end() const { return begin() + _size; }
568
570
571private:
572 constexpr void _grow() {
573 _alloc.creallocate(_alloc.capacity() * 2);
574 }
575
576 allocation<value_t, alloc_t> _alloc;
577 size_t _size;
578};
579
580}
581
582#endif // FENNEC_CONTAINERS_DYNARRAY_H
This header contains structures and classes related to allocating blocks of memory.
constexpr genType min(genType x, genType y)
Returns if otherwise it returns .
Definition common.h:688
This header contains functions related to analyzing, modifying or copying buffers interpreted as byte...
constexpr value_t * data()
Getter for the real pointer to the allocated block of memory.
Definition allocator.h:624
constexpr size_t capacity() const
Getter for the number of elements n of type T that the allocation can hold.
Definition allocator.h:617
constexpr void deallocate() noexcept
Release the block of memory.
Definition allocator.h:505
constexpr void creallocate(size_t n, align_t align=zero< align_t >()) noexcept
Reallocate the block with a new size. Contents are copied to the new allocation.
Definition allocator.h:541
Wrapper for dynamically sized and allocated arrays.
Definition dynarray.h:64
constexpr void emplace_back(ArgsT...args)
Emplace Back.
Definition dynarray.h:499
constexpr dynarray & operator=(const TypeT(&arr)[N])
Array Copy Assignment Operator.
Definition dynarray.h:298
constexpr ~dynarray()
Default Destructor, destructs all elements and frees the underlying allocation.
Definition dynarray.h:252
constexpr TypeT * end()
"Iterator" End Function
Definition dynarray.h:557
constexpr dynarray(size_t n, alloc_t &&alloc)
Sized Allocation Alloc Move Constructor, initializes a dynarray with allocator alloc and n elements u...
Definition dynarray.h:135
constexpr const TypeT & back() const
Definition dynarray.h:393
constexpr TypeT & operator[](size_t i)
Array Access Operator.
Definition dynarray.h:359
constexpr dynarray & operator=(TypeT(&&arr)[N])
Array Copy Assignment Operator.
Definition dynarray.h:313
constexpr bool empty() const
Definition dynarray.h:343
constexpr void insert(size_t i, TypeT &&val)
Move Insertion.
Definition dynarray.h:409
constexpr dynarray(size_t n, const alloc_t &alloc)
Sized Allocation Alloc Constructor, initializes a dynarray with allocator alloc and n elements using ...
Definition dynarray.h:121
constexpr dynarray()
Default Constructor, initializes an empty allocation.
Definition dynarray.h:80
constexpr TypeT & front()
Definition dynarray.h:375
constexpr void clear()
Clears the contents of the dynarray, destructing all elements and releasing the allocation.
Definition dynarray.h:534
constexpr const TypeT * end() const
Const "Iterator" End Function.
Definition dynarray.h:567
constexpr dynarray(const dynarray< OTypeT, OAlloc > &conv)
Conversion Constructor, copies elements of conv as this value_t
Definition dynarray.h:208
constexpr dynarray(TypeT(&&arr)[N])
Array Move Constructor.
Definition dynarray.h:194
constexpr dynarray(size_t n)
Sized Allocation, initializes a dynarray with n elements using the default constructor.
Definition dynarray.h:106
constexpr void pop_back()
Erase last element.
Definition dynarray.h:505
constexpr void push_back(TypeT &&val)
Push Back Move.
Definition dynarray.h:490
constexpr dynarray & operator=(dynarray &&arr) noexcept
Move Assignment Operator.
Definition dynarray.h:284
constexpr dynarray(dynarray &&arr) noexcept
Move Constructor, takes ownership of the allocation.
Definition dynarray.h:244
constexpr dynarray(size_t n, ArgsT &&...args)
Emplace Constructor.
Definition dynarray.h:168
constexpr const TypeT & operator[](size_t i) const
Array Access Operator (const)
Definition dynarray.h:368
constexpr const TypeT & front() const
Definition dynarray.h:381
constexpr void push_back(const TypeT &val)
Push Back Copy.
Definition dynarray.h:483
constexpr size_t capacity() const
Definition dynarray.h:337
constexpr const TypeT * begin() const
Const "Iterator" Begin Function.
Definition dynarray.h:562
constexpr TypeT & back()
Definition dynarray.h:387
constexpr dynarray(const dynarray &arr)
Copy Constructor, uses the copy constructor to copy each element.
Definition dynarray.h:233
constexpr void insert(size_t i, const TypeT &val)
Copy Insertion.
Definition dynarray.h:433
constexpr void resize(size_t n, const TypeT &val)
Resize the dynarray, invoking the copy constructor for all new elements.
Definition dynarray.h:524
constexpr void emplace(size_t i, ArgsT &&...args)
Emplace Insertion.
Definition dynarray.h:460
constexpr dynarray(alloc_t &&alloc) noexcept
Alloc Move Constructor, initialize empty allocation with allocator instance.
Definition dynarray.h:98
Alloc alloc_t
Alias for the allocator type.
Definition dynarray.h:70
constexpr dynarray & operator=(const dynarray &arr)
Copy Assignment Operator.
Definition dynarray.h:271
constexpr dynarray(size_t n, const TypeT &val)
Sized Allocation Copy Constructor, Create an allocation of size n elements, with each element constru...
Definition dynarray.h:149
constexpr size_t size() const
Definition dynarray.h:331
TypeT value_t
Alias for the value type.
Definition dynarray.h:69
constexpr void resize(size_t n)
Resize the dynarray, invoking the default constructor for all new elements.
Definition dynarray.h:512
constexpr dynarray(initializer_list< value_t > l, const alloc_t &alloc=alloc_t())
Initializer List Constructor.
Definition dynarray.h:221
constexpr dynarray(const TypeT(&arr)[N])
Array Copy Constructor.
Definition dynarray.h:181
constexpr dynarray(const alloc_t &alloc)
Alloc Constructor, initialize empty allocation with allocator instance.
Definition dynarray.h:89
constexpr TypeT * begin()
"Iterator" Begin Function
Definition dynarray.h:552
Utility
constexpr const remove_reference_t< T > & copy(T &&x) noexcept
produces an r-value type to indicate x may be "copied"
Definition utility.h:104
constexpr remove_reference_t< T > && move(T &&x) noexcept
produces an x-value type to indicate x may be "moved"
Definition utility.h:92