HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
stack.hpp
1// Copyright Take Vos 2020-2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include <type_traits>
8#include <memory>
9#include <initializer_list>
10#include "utility/module.hpp"
11
12namespace hi::inline v1 {
13
21template<typename T, std::size_t MaxSize>
22class stack {
23public:
24 using value_type = T;
25 using pointer_type = value_type *;
26 using const_pointer_type = value_type const *;
27 using reference_type = value_type &;
28 using const_reference_type = value_type const &;
29 using iterator_type = pointer_type;
30 using const_iterator_type = const_pointer_type;
31 using size_type = std::size_t;
32 using difference_type = ptrdiff_t;
33
36 stack() noexcept : _top(begin()) {}
37
41 stack(std::initializer_list<value_type> init) noexcept : _top(begin())
42 {
43 for (hilet &init_item : init) {
44 push_back(init_item);
45 }
46 }
47
48 ~stack() noexcept
49 {
50 clear();
51 }
52
56 [[nodiscard]] iterator_type begin() noexcept
57 {
58 return std::launder(reinterpret_cast<pointer_type>(&_buffer[0]));
59 }
60
64 [[nodiscard]] const_iterator_type begin() const noexcept
65 {
66 return std::launder(reinterpret_cast<const_pointer_type>(&_buffer[0]));
67 }
68
72 [[nodiscard]] const_iterator_type cbegin() const noexcept
73 {
74 return std::launder(reinterpret_cast<const_pointer_type>(&_buffer[0]));
75 }
76
80 [[nodiscard]] iterator_type end() noexcept
81 {
82 return _top;
83 }
84
88 [[nodiscard]] const_iterator_type end() const noexcept
89 {
90 return _top;
91 }
92
96 [[nodiscard]] const_iterator_type cend() const noexcept
97 {
98 return _top;
99 }
100
104 [[nodiscard]] constexpr size_type max_size() const noexcept
105 {
106 return MaxSize;
107 }
108
112 [[nodiscard]] size_type size() const noexcept
113 {
114 return narrow_cast<size_type>(end() - begin());
115 }
116
120 [[nodiscard]] bool full() const noexcept
121 {
122 return _top == (begin() + max_size());
123 }
124
128 [[nodiscard]] bool empty() const noexcept
129 {
130 return _top == begin();
131 }
132
137 [[nodiscard]] reference_type operator[](std::size_t index) noexcept
138 {
139 hi_assert_bounds(index, *this);
140 return *std::launder(reinterpret_cast<pointer_type>(&_buffer[index]));
141 }
142
147 [[nodiscard]] const_reference_type operator[](std::size_t index) const noexcept
148 {
149 hi_assert_bounds(index, *this);
150 return *std::launder(reinterpret_cast<pointer_type>(&_buffer[index]));
151 }
152
157 [[nodiscard]] reference_type at(std::size_t index) noexcept
158 {
159 if (index >= size()) {
160 throw std::out_of_range("stack::at");
161 }
162 return (*this)[index];
163 }
164
169 [[nodiscard]] const_reference_type at(std::size_t index) const noexcept
170 {
171 if (index >= size()) {
172 throw std::out_of_range("stack::at");
173 }
174 return (*this)[index];
175 }
176
180 [[nodiscard]] reference_type back() noexcept
181 {
182 hi_axiom(!empty());
183 return *std::launder(_top - 1);
184 }
185
189 [[nodiscard]] const_reference_type back() const noexcept
190 {
191 hi_axiom(!empty());
192 return *std::launder(_top - 1);
193 }
194
199 template<typename... Args>
200 void emplace_back(Args &&...args) noexcept
201 {
202 hi_axiom(!full());
203 new (end()) value_type(std::forward<Args>(args)...);
204 ++_top;
205 }
206
211 template<typename Arg>
212 requires(std::is_convertible_v<Arg, value_type>) void push_back(Arg &&arg) noexcept
213 {
214 emplace_back(std::forward<Arg>(arg));
215 }
216
220 void pop_back() noexcept
221 {
222 hi_axiom(!empty());
223 auto *old_item = std::launder(--_top);
224 std::destroy_at(old_item);
225 }
226
231 void pop_back(iterator_type new_end) noexcept
232 {
233 while (_top != new_end) {
234 pop_back();
235 }
236 }
237
240 void clear() noexcept
241 {
242 std::destroy(begin(), end());
243 _top = begin();
244 }
245
246private:
247 std::aligned_storage_t<sizeof(T), std::alignment_of_v<T>> _buffer[MaxSize];
248 pointer_type _top;
249};
250
251} // namespace hi::inline v1
#define hi_assert_bounds(x,...)
Assert if a value is within bounds.
Definition assert.hpp:210
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:238
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:13
A static sized stack.
Definition stack.hpp:22
void pop_back() noexcept
Remove the value at the top of the stack.
Definition stack.hpp:220
size_type size() const noexcept
The number of elements that fit on the stack.
Definition stack.hpp:112
reference_type operator[](std::size_t index) noexcept
Get a reference to an element on the stack at an index.
Definition stack.hpp:137
const_iterator_type cbegin() const noexcept
Get an iterator to the first element on the stack.
Definition stack.hpp:72
void push_back(Arg &&arg) noexcept
Push a new value to after the current top of the stack.
Definition stack.hpp:212
void clear() noexcept
Remove all elements from the stack.
Definition stack.hpp:240
const_reference_type at(std::size_t index) const noexcept
Get a reference to an element on the stack at an index.
Definition stack.hpp:169
void pop_back(iterator_type new_end) noexcept
Pop elements of the stack through the given iterator.
Definition stack.hpp:231
reference_type back() noexcept
Get a reference to the element at the top of the stack.
Definition stack.hpp:180
const_iterator_type begin() const noexcept
Get an iterator to the first element on the stack.
Definition stack.hpp:64
bool full() const noexcept
Check if the stack is full.
Definition stack.hpp:120
stack() noexcept
Construct an empty stack.
Definition stack.hpp:36
iterator_type begin() noexcept
Get an iterator to the first element on the stack.
Definition stack.hpp:56
reference_type at(std::size_t index) noexcept
Get a reference to an element on the stack at an index.
Definition stack.hpp:157
const_iterator_type end() const noexcept
Get an iterator to the last element on the stack.
Definition stack.hpp:88
void emplace_back(Args &&...args) noexcept
Construct an object after the current top of the stack.
Definition stack.hpp:200
const_reference_type back() const noexcept
Get a reference to the element at the top of the stack.
Definition stack.hpp:189
const_reference_type operator[](std::size_t index) const noexcept
Get a reference to an element on the stack at an index.
Definition stack.hpp:147
stack(std::initializer_list< value_type > init) noexcept
Construct a stack with the given data.
Definition stack.hpp:41
bool empty() const noexcept
Check if the stack is empty.
Definition stack.hpp:128
constexpr size_type max_size() const noexcept
The maximum number of elements that fit on the stack.
Definition stack.hpp:104
const_iterator_type cend() const noexcept
Get an iterator to the last element on the stack.
Definition stack.hpp:96
iterator_type end() noexcept
Get an iterator to the last element on the stack.
Definition stack.hpp:80