Stratax 0.4.0rc1
Loading...
Searching...
No Matches
Buffer.hpp
Go to the documentation of this file.
1
4#pragma once
5
6#include "Config.hpp"
7#include <algorithm>
8#include <cstddef>
9#include <initializer_list>
10#include <iterator>
11#include <limits>
12#include <memory>
13#include <new>
14#include <utility>
15
17
18namespace stratax::core {
19
52template<typename T, std::size_t Alignment = config::default_alignment>
53class Buffer
54{
55
56 static_assert(Alignment >= alignof(T));
57 static_assert((Alignment & (Alignment - 1)) == 0);
58
59public:
61 using value_type = T;
63 using size_type = std::size_t;
65 using difference_type = std::ptrdiff_t;
67 using reference = T&;
69 using const_reference = const T&;
71 using pointer = T*;
73 using const_pointer = const T*;
79 using reverse_iterator = std::reverse_iterator<iterator>;
81 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
82
91 [[nodiscard]] static constexpr size_type alignment() noexcept
92 {
93 return Alignment;
94 }
95
105 [[nodiscard]] static constexpr size_type max_size() noexcept
106 {
107 return std::numeric_limits<size_type>::max() / sizeof(value_type);
108 }
109
117 Buffer() noexcept: data_(nullptr), size_(0) {}
118
133 : data_(allocate(size)), size_(size)
134 {
135 try {
136 std::uninitialized_value_construct_n(data_, size_);
137 } catch (...) {
138 deallocate(data_);
139 throw;
140 }
141 }
142
157 : data_(allocate(size)), size_(size)
158 {
159 construct_fill(value);
160 }
161
175 Buffer(std::initializer_list<value_type> list)
176 : data_(allocate(list.size())), size_(list.size())
177 {
178 size_type i = 0;
179
180 try {
181 for (const_reference value : list) {
182 std::construct_at(data_ + i, value);
183 ++i;
184 }
185 } catch (...) {
186 std::destroy_n(data_, i);
187 deallocate(data_);
188 throw;
189 }
190 }
191
204 Buffer(const Buffer& other)
205 : data_(allocate(other.size_)),
206 size_(other.size_)
207 {
208 try {
209 std::uninitialized_copy_n(
210 other.data_,
211 size_,
212 data_
213 );
214 }
215 catch (...) {
216 deallocate(data_);
217 throw;
218 }
219 }
220
232 Buffer(Buffer&& other) noexcept
233 : data_(other.data_), size_(other.size_)
234 {
235 other.data_ = nullptr;
236 other.size_ = 0;
237 }
238
253 Buffer& operator=(const Buffer& other)
254 {
255 if (this == &other) {
256 return *this;
257 }
258
259 Buffer temp(other);
260 swap(temp);
261 return *this;
262 }
263
278 Buffer& operator=(Buffer&& other) noexcept
279 {
280 if (this == &other) {
281 return *this;
282 }
283
284 if (size_ != 0) {
285 std::destroy_n(data_, size_);
286 }
287
288 deallocate(data_);
289
290 data_ = other.data_;
291 size_ = other.size_;
292
293 other.data_ = nullptr;
294 other.size_ = 0;
295
296 return *this;
297 }
298
307 {
308 if (size_ != 0) {
309 std::destroy_n(data_, size_);
310 }
311
312 deallocate(data_);
313 }
314
324 {
325 return data_[index];
326 }
327
336 const_reference operator[](size_type index) const noexcept {return data_[index];}
337
346 {
347 return data_[0];
348 }
349
358 {
359 return data_[0];
360 }
361
370 {
371 return data_[size_ - 1];
372 }
373
382 {
383 return data_[size_ - 1];
384 }
385
397 [[nodiscard]] pointer data() noexcept {return data_;}
398
410 [[nodiscard]] const_pointer data() const noexcept
411 {
412 return data_;
413 }
414
420 iterator begin() noexcept {return data_;}
426 const_iterator begin() const noexcept {return data_;}
432 const_iterator cbegin() const noexcept {return data_;}
438 iterator end() noexcept {return empty() ? data_ : data_ + size_;}
444 const_iterator end() const noexcept {return empty() ? data_ : data_ + size_;}
450 const_iterator cend() const noexcept {return empty() ? data_ : data_ + size_;}
487
497 [[nodiscard]] size_type size() const noexcept {return size_;}
498
505 [[nodiscard]] bool empty() const noexcept {return size_ == 0;}
506
519 {
520 std::fill_n(data_, size_, value);
521 }
522
534 void swap(Buffer& other) noexcept
535 {
536 std::swap(data_, other.data_);
537 std::swap(size_, other.size_);
538 }
539
540private:
541 pointer data_;
542 size_type size_;
543
554 static pointer allocate(size_type space)
555 {
556 if (space == 0) {
557 return nullptr;
558 }
559
560 if (space > max_size()) {
561 throw std::bad_array_new_length();
562 }
563
564 return static_cast<pointer>(
565 ::operator new(
566 sizeof(value_type) * space,
567 std::align_val_t{Alignment}
568 )
569 );
570 }
571
578 static void deallocate(pointer ptr) noexcept
579 {
580 if (ptr == nullptr) {
581 return;
582 }
583
584 ::operator delete(
585 ptr,
586 std::align_val_t{Alignment}
587 );
588 }
589
601 void construct_fill(const_reference value)
602 {
603 try {
604 std::uninitialized_fill_n(data_, size_, value);
605 } catch (...) {
606 deallocate(data_);
607 throw;
608 }
609 }
610
611};
612
613}
Allocation alignment and reserved execution flags.
Stratax exception types derived from std::runtime_error.
Fixed-size owner of aligned, contiguous element storage.
Definition Buffer.hpp:54
const_pointer const_iterator
Read-only contiguous random-access iterator type.
Definition Buffer.hpp:77
std::reverse_iterator< iterator > reverse_iterator
Mutable iterator that traverses elements in reverse order.
Definition Buffer.hpp:79
Buffer(size_type size, const_reference value)
Constructs a buffer with all elements initialized to value.
Definition Buffer.hpp:156
Buffer & operator=(Buffer &&other) noexcept
Move-assigns from another buffer.
Definition Buffer.hpp:278
const_pointer data() const noexcept
Returns a const pointer to the underlying contiguous storage.
Definition Buffer.hpp:410
reverse_iterator rend() noexcept
Returns the past-the-end iterator for mutable reverse traversal.
Definition Buffer.hpp:474
void swap(Buffer &other) noexcept
Swaps storage and size with another buffer.
Definition Buffer.hpp:534
Buffer(const Buffer &other)
Copy-constructs a buffer with independent storage.
Definition Buffer.hpp:204
Buffer(size_type size)
Constructs a buffer with value-initialized elements.
Definition Buffer.hpp:132
T & reference
Mutable element reference type.
Definition Buffer.hpp:67
size_type size() const noexcept
Returns the number of stored elements.
Definition Buffer.hpp:497
~Buffer()
Destroys the buffer and releases owned storage.
Definition Buffer.hpp:306
static constexpr size_type alignment() noexcept
Returns the alignment, in bytes, used for buffer allocations.
Definition Buffer.hpp:91
const_reverse_iterator rbegin() const noexcept
Returns a const reverse iterator to the final element.
Definition Buffer.hpp:462
T * pointer
Mutable pointer to an element.
Definition Buffer.hpp:71
static constexpr size_type max_size() noexcept
Returns the largest element count that cannot overflow in bytes.
Definition Buffer.hpp:105
const_reverse_iterator crend() const noexcept
Returns the past-the-end iterator for const reverse traversal.
Definition Buffer.hpp:486
std::ptrdiff_t difference_type
Signed type used for distances between iterators.
Definition Buffer.hpp:65
reference front()
Returns a reference to the first element.
Definition Buffer.hpp:345
const_iterator cend() const noexcept
Returns a const iterator one past the final element.
Definition Buffer.hpp:450
pointer iterator
Mutable contiguous random-access iterator type.
Definition Buffer.hpp:75
bool empty() const noexcept
Returns whether the buffer has no elements.
Definition Buffer.hpp:505
reference operator[](size_type index) noexcept
Returns an unchecked reference to an element.
Definition Buffer.hpp:323
Buffer(std::initializer_list< value_type > list)
Constructs a buffer from an initializer list.
Definition Buffer.hpp:175
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the final element.
Definition Buffer.hpp:468
std::size_t size_type
Unsigned type used for element counts and indices.
Definition Buffer.hpp:63
reverse_iterator rbegin() noexcept
Returns a mutable reverse iterator to the final element.
Definition Buffer.hpp:456
void fill(const_reference value)
Assigns a value to every element in the buffer.
Definition Buffer.hpp:518
pointer data() noexcept
Returns a pointer to the underlying contiguous storage.
Definition Buffer.hpp:397
const_reference front() const
Returns a const reference to the first element.
Definition Buffer.hpp:357
iterator begin() noexcept
Returns a mutable iterator to the first element.
Definition Buffer.hpp:420
const_iterator cbegin() const noexcept
Returns a const iterator to the first element.
Definition Buffer.hpp:432
const_iterator end() const noexcept
Returns a const iterator one past the final element.
Definition Buffer.hpp:444
const_reference back() const
Returns a const reference to the last element.
Definition Buffer.hpp:381
Buffer(Buffer &&other) noexcept
Move-constructs a buffer by transferring ownership.
Definition Buffer.hpp:232
const T * const_pointer
Read-only pointer to an element.
Definition Buffer.hpp:73
reference back()
Returns a reference to the last element.
Definition Buffer.hpp:369
const_iterator begin() const noexcept
Returns a const iterator to the first element.
Definition Buffer.hpp:426
Buffer() noexcept
Constructs an empty buffer that owns no allocation.
Definition Buffer.hpp:117
std::reverse_iterator< const_iterator > const_reverse_iterator
Read-only iterator that traverses elements in reverse order.
Definition Buffer.hpp:81
Buffer & operator=(const Buffer &other)
Copy-assigns from another buffer.
Definition Buffer.hpp:253
const T & const_reference
Read-only element reference type.
Definition Buffer.hpp:69
iterator end() noexcept
Returns a mutable iterator one past the final element.
Definition Buffer.hpp:438
const_reverse_iterator rend() const noexcept
Returns the past-the-end iterator for const reverse traversal.
Definition Buffer.hpp:480
const_reference operator[](size_type index) const noexcept
Returns an unchecked const reference to an element.
Definition Buffer.hpp:336
T value_type
Type of each stored element.
Definition Buffer.hpp:61