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