HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
vector_span.hpp
1// Copyright Take Vos 2020-2022.
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 "utility/module.hpp"
8#include <span>
9#include <iterator>
10#include <memory>
11#include <new>
12
13namespace hi::inline v1 {
14
15template<typename T>
17public:
18 using value_type = T;
19 using difference_type = ssize_t;
20
21private:
22 value_type *ptr;
23
24public:
25 vector_span_iterator() noexcept : ptr(nullptr) {}
26 vector_span_iterator(vector_span_iterator const &other) noexcept = default;
27 vector_span_iterator(vector_span_iterator &&other) noexcept = default;
28 vector_span_iterator &operator=(vector_span_iterator const &other) noexcept = default;
29 vector_span_iterator &operator=(vector_span_iterator &&other) noexcept = default;
30 ~vector_span_iterator() = default;
31
32 vector_span_iterator(value_type *ptr) noexcept : ptr(ptr)
33 {
35 }
36
37 vector_span_iterator &operator=(value_type *ptr) noexcept
38 {
40 this->ptr = ptr;
41 return *this;
42 }
43
44 [[nodiscard]] value_type &operator*() noexcept
45 {
46 return *std::launder(ptr);
47 }
48 [[nodiscard]] value_type const &operator*() const noexcept
49 {
50 return *std::launder(ptr);
51 }
52 [[nodiscard]] value_type *operator->() noexcept
53 {
54 return std::launder(ptr);
55 }
56 [[nodiscard]] value_type const *operator->() const noexcept
57 {
58 return std::launder(ptr);
59 }
60 [[nodiscard]] value_type &operator[](std::size_t i) noexcept
61 {
62 return *std::launder(ptr + i);
63 }
64 [[nodiscard]] value_type const &operator[](std::size_t i) const noexcept
65 {
66 return *std::launder(ptr + i);
67 }
68
69 vector_span_iterator &operator++() noexcept
70 {
71 ++ptr;
72 return *this;
73 }
74 vector_span_iterator operator++(int) noexcept
75 {
76 auto tmp = *this;
77 ++ptr;
78 return tmp;
79 }
80 vector_span_iterator &operator--() noexcept
81 {
82 --ptr;
83 return *this;
84 }
85 vector_span_iterator operator--(int) noexcept
86 {
87 auto tmp = *this;
88 --ptr;
89 return tmp;
90 }
91
92 vector_span_iterator &operator+=(ssize_t rhs) noexcept
93 {
94 ptr += rhs;
95 return *this;
96 }
97 vector_span_iterator &operator-=(ssize_t rhs) noexcept
98 {
99 ptr -= rhs;
100 return *this;
101 }
102
103 [[nodiscard]] friend bool operator==(vector_span_iterator const &lhs, vector_span_iterator const &rhs) noexcept
104 {
105 return lhs.ptr == rhs.ptr;
106 }
107
108 [[nodiscard]] friend auto operator<=>(vector_span_iterator const &lhs, vector_span_iterator const &rhs) noexcept
109 {
110 return lhs.ptr <=> rhs.ptr;
111 }
112
113 [[nodiscard]] friend vector_span_iterator operator+(vector_span_iterator const &lhs, ssize_t rhs) noexcept
114 {
115 return vector_span_iterator{lhs.ptr + rhs};
116 }
117 [[nodiscard]] friend vector_span_iterator operator-(vector_span_iterator const &lhs, ssize_t rhs) noexcept
118 {
119 return vector_span_iterator{lhs.ptr - rhs};
120 }
121 [[nodiscard]] friend vector_span_iterator operator+(ssize_t lhs, vector_span_iterator const &rhs) noexcept
122 {
123 return vector_span_iterator{lhs + rhs.ptr};
124 }
125
126 [[nodiscard]] friend difference_type operator-(vector_span_iterator const &lhs, vector_span_iterator const &rhs) noexcept
127 {
128 return lhs.ptr - rhs.ptr;
129 }
130};
131
132template<typename T>
134public:
135 using value_type = T;
138
139private:
140 value_type *_begin;
141 value_type *_end;
142 value_type *_max;
143
144public:
145 vector_span() noexcept : _begin(nullptr), _end(nullptr), _max(nullptr) {}
146
147 vector_span(value_type *buffer, ssize_t nr_elements) noexcept : _begin(buffer), _end(buffer), _max(buffer + nr_elements)
148 {
149 hi_axiom(nr_elements >= 0);
150 }
151
152 vector_span(std::span<value_type> span) noexcept : _begin(span.data()), _end(span.data()), _max(span.data() + span.size()) {}
153
154 vector_span(vector_span const &other) = default;
155 vector_span(vector_span &&other) = default;
156 vector_span &operator=(vector_span const &other) = default;
157 vector_span &operator=(vector_span &&other) = default;
158 ~vector_span() = default;
159
160 [[nodiscard]] iterator begin() noexcept
161 {
162 return _begin;
163 }
164 [[nodiscard]] const_iterator begin() const noexcept
165 {
166 return _begin;
167 }
168 [[nodiscard]] const_iterator cbegin() const noexcept
169 {
170 return _begin;
171 }
172
173 [[nodiscard]] iterator end() noexcept
174 {
175 return _end;
176 }
177 [[nodiscard]] const_iterator end() const noexcept
178 {
179 return _end;
180 }
181 [[nodiscard]] const_iterator cend() const noexcept
182 {
183 return _end;
184 }
185
186 [[nodiscard]] std::size_t size() const noexcept
187 {
188 return std::distance(_begin, _end);
189 }
190
191 [[nodiscard]] value_type &operator[](std::size_t i) noexcept
192 {
193 hi_assert_bounds(i, *this);
194 return *std::launder(_begin + i);
195 }
196 [[nodiscard]] value_type const &operator[](std::size_t i) const noexcept
197 {
198 hi_assert_bounds(i, *this);
199 return *std::launder(_begin + i);
200 }
201
202 value_type &front() noexcept
203 {
204 hi_axiom(_end != _begin);
205 return *std::launder(_begin);
206 }
207 value_type const &front() const noexcept
208 {
209 hi_axiom(_end != _begin);
210 return *std::launder(_begin);
211 }
212 value_type &back() noexcept
213 {
214 hi_axiom(_end != _begin);
215 return *std::launder(_end - 1);
216 }
217 value_type const &back() const noexcept
218 {
219 hi_axiom(_end != _begin);
220 return *std::launder(_end - 1);
221 }
222
223 [[nodiscard]] bool empty() const noexcept
224 {
225 return _begin == _end;
226 }
227
228 [[nodiscard]] bool full() const noexcept
229 {
230 return _end == _max;
231 }
232
233 void clear() noexcept
234 {
235 for (auto i = _begin; i != _end; ++i) {
236 std::destroy_at(std::launder(i));
237 }
238 _end = _begin;
239 }
240
241 void push_back(value_type const &rhs) noexcept
242 {
243 hi_axiom(_end != _max);
244 // Since we throw away the pointer, we have to std::launder all access to this object.
245 [[maybe_unused]] value_type *ptr = new (_end) value_type(rhs);
246 ++_end;
247 }
248
249 void push_back(value_type &&rhs) noexcept
250 {
251 hi_axiom(_end != _max);
252 // Since we throw away the pointer, we have to std::launder all access to this object.
253 [[maybe_unused]] value_type *ptr = new (_end) value_type(std::move(rhs));
254 ++_end;
255 }
256
257 template<typename... Args>
258 void emplace_back(Args &&...args) noexcept
259 {
260 hi_axiom(_end != _max);
261 std::construct_at(_end++, std::forward<Args>(args)...);
262 }
263
264 void pop_back() noexcept
265 {
266 hi_axiom(_end != _begin);
267 --_end;
268 std::destroy_at(std::launder(_end));
269 }
270};
271
272} // 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 hi_assert_not_null(x,...)
Assert if an expression is not nullptr.
Definition assert.hpp:223
DOXYGEN BUG.
Definition algorithm.hpp:13
Definition vector_span.hpp:16
Definition vector_span.hpp:133
T distance(T... args)
T move(T... args)