HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
void_span.hpp
1// Copyright Take Vos 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 "byte_string.hpp"
9#include <span>
10#include <cstddef>
11#include <bit>
12#include <type_traits>
13#include <string_view>
14
15namespace hi::inline v1 {
16
17class void_span {
18public:
19 using size_type = std::size_t;
21 using pointer = void *;
22 using const_pointer = void const *;
23
24 static constexpr std::size_t extent = std::dynamic_extent;
25
26 constexpr ~void_span() = default;
27 constexpr void_span() noexcept = default;
28 constexpr void_span(void_span const&) noexcept = default;
29 constexpr void_span(void_span&&) noexcept = default;
30 constexpr void_span& operator=(void_span const&) noexcept = default;
31 constexpr void_span& operator=(void_span&&) noexcept = default;
32 constexpr void_span(void *pointer, size_t size) noexcept : _pointer(pointer), _size(size)
33 {
34 hi_assert(pointer != nullptr or size == 0);
35 }
36
37 template<typename T, std::size_t N>
38 constexpr void_span(std::array<T, N>& rhs) noexcept requires(not std::is_const_v<T>) : void_span(rhs.data(), rhs.size())
39 {
40 }
41
42 template<typename T, std::size_t N>
43 constexpr void_span(std::span<T, N>& rhs) noexcept requires(not std::is_const_v<T>) : void_span(rhs.data(), rhs.size())
44 {
45 }
46
47 [[nodiscard]] constexpr pointer data() const noexcept
48 {
49 return _pointer;
50 }
51
52 [[nodiscard]] constexpr size_type size() const noexcept
53 {
54 return _size;
55 }
56
57 [[nodiscard]] constexpr size_type size_bytes() const noexcept
58 {
59 return _size;
60 }
61
62 [[nodiscard]] constexpr bool empty() const noexcept
63 {
64 return _size == 0;
65 }
66
67 template<std::size_t N>
68 [[nodiscard]] constexpr void_span first() const noexcept
69 {
70 hi_axiom(N <= _size);
71 return {_pointer, N};
72 }
73
74 [[nodiscard]] constexpr void_span first(size_type n) const noexcept
75 {
76 hi_axiom(n <= _size);
77 return {_pointer, n};
78 }
79
80 template<std::size_t N>
81 [[nodiscard]] constexpr void_span last() const noexcept
82 {
83 hi_axiom(N <= _size);
84 return {advance_bytes(_pointer, _size - N), N};
85 }
86
87 [[nodiscard]] constexpr void_span last(size_type n) const noexcept
88 {
89 hi_axiom(n <= _size);
90 return {advance_bytes(_pointer, _size - n), n};
91 }
92
93 template<std::size_t Offset, std::size_t Count = std::dynamic_extent>
94 [[nodiscard]] constexpr void_span subspan() const noexcept
95 {
96 if constexpr (Count == std::dynamic_extent) {
97 hi_axiom(Offset <= _size);
98 return {advance_bytes(_pointer, Offset), _size - Offset};
99 } else {
100 hi_axiom((Offset + Count) <= _size);
101 return {advance_bytes(_pointer, Offset), Count};
102 }
103 }
104
105 [[nodiscard]] constexpr void_span subspan(size_type offset, size_type count = std::dynamic_extent) const noexcept
106 {
107 hi_axiom(offset <= _size);
108 if (count == std::dynamic_extent) {
109 count = _size - offset;
110 }
111
112 hi_axiom(offset + count <= _size);
113 return {advance_bytes(_pointer, _size - count), count};
114 }
115
116 template<typename T, size_t E = std::dynamic_extent>
117 [[nodiscard]] constexpr friend std::span<T, E> as_span(void_span const& rhs) noexcept
118 {
119 if constexpr (E == std::dynamic_extent) {
120 hi_axiom(std::bit_cast<std::uintptr_t>(rhs._pointer) % std::alignment_of_v<T> == 0);
121 hi_axiom((rhs._size / sizeof(T)) * sizeof(T) == rhs._size);
122 return {static_cast<T *>(rhs._pointer), rhs._size / sizeof(T)};
123
124 } else {
125 hi_axiom(std::bit_cast<std::uintptr_t>(rhs._pointer) % std::alignment_of_v<T> == 0);
126 hi_axiom(E * sizeof(T) <= rhs._size);
127 return {static_cast<T *>(rhs._pointer), E};
128 }
129 }
130
131 template<typename CharT, typename Traits = std::char_traits<CharT>>
132 [[nodiscard]] constexpr friend std::basic_string_view<CharT, Traits> as_basic_string_view(void_span const& rhs) noexcept
133 {
134 hi_axiom(std::bit_cast<std::uintptr_t>(rhs._pointer) % std::alignment_of_v<CharT> == 0);
135 hi_axiom((rhs._size / sizeof(CharT)) * sizeof(CharT) == rhs._size);
136 return {static_cast<CharT const *>(rhs._pointer), rhs._size / sizeof(CharT)};
137 }
138
139 [[nodiscard]] constexpr friend std::string_view as_string_view(void_span const& rhs) noexcept
140 {
141 return as_basic_string_view<char>(rhs);
142 }
143
144 [[nodiscard]] constexpr friend bstring_view as_bstring_view(void_span const& rhs) noexcept
145 {
146 return as_basic_string_view<std::byte, byte_char_traits>(rhs);
147 }
148
149private:
150 pointer _pointer = nullptr;
151 size_type _size = 0;
152};
153
155public:
156 using size_type = std::size_t;
158 using pointer = void const *;
159 using const_pointer = void const *;
160
161 static constexpr std::size_t extent = std::dynamic_extent;
162
163 constexpr ~const_void_span() = default;
164 constexpr const_void_span() noexcept = default;
165 constexpr const_void_span(const_void_span const&) noexcept = default;
166 constexpr const_void_span(const_void_span&&) noexcept = default;
167 constexpr const_void_span& operator=(const_void_span const&) noexcept = default;
168 constexpr const_void_span& operator=(const_void_span&&) noexcept = default;
169 constexpr const_void_span(void const *pointer, size_t size) noexcept : _pointer(pointer), _size(size)
170 {
171 hi_assert(pointer != nullptr or size == 0);
172 }
173
174 constexpr const_void_span(void_span const& rhs) noexcept : const_void_span(rhs.data(), rhs.size()) {}
175
176 template<typename T, std::size_t N>
177 constexpr const_void_span(std::array<T, N> const& rhs) noexcept : const_void_span(rhs.data(), rhs.size())
178 {
179 }
180
181 template<typename T, std::size_t N>
182 constexpr const_void_span(std::span<T, N> const& rhs) noexcept : const_void_span(rhs.data(), rhs.size())
183 {
184 }
185
186 [[nodiscard]] constexpr pointer data() const noexcept
187 {
188 return _pointer;
189 }
190
191 [[nodiscard]] constexpr size_type size() const noexcept
192 {
193 return _size;
194 }
195
196 [[nodiscard]] constexpr size_type size_bytes() const noexcept
197 {
198 return _size;
199 }
200
201 [[nodiscard]] constexpr bool empty() const noexcept
202 {
203 return _size == 0;
204 }
205
206 template<std::size_t N>
207 [[nodiscard]] constexpr const_void_span first() const noexcept
208 {
209 hi_axiom(N <= _size);
210 return {_pointer, N};
211 }
212
213 [[nodiscard]] constexpr const_void_span first(size_type n) const noexcept
214 {
215 hi_axiom(n <= _size);
216 return {_pointer, n};
217 }
218
219 template<std::size_t N>
220 [[nodiscard]] constexpr const_void_span last() const noexcept
221 {
222 hi_axiom(N <= _size);
223 return {advance_bytes(_pointer, _size - N), N};
224 }
225
226 [[nodiscard]] constexpr const_void_span last(size_type n) const noexcept
227 {
228 hi_axiom(n <= _size);
229 return {advance_bytes(_pointer, _size - n), n};
230 }
231
232 template<std::size_t Offset, std::size_t Count = std::dynamic_extent>
233 [[nodiscard]] constexpr const_void_span subspan() const noexcept
234 {
235 if constexpr (Count == std::dynamic_extent) {
236 hi_axiom(Offset <= _size);
237 return {advance_bytes(_pointer, Offset), _size - Offset};
238 } else {
239 hi_axiom((Offset + Count) <= _size);
240 return {advance_bytes(_pointer, Offset), Count};
241 }
242 }
243
244 [[nodiscard]] constexpr const_void_span subspan(size_type offset, size_type count = std::dynamic_extent) const noexcept
245 {
246 hi_axiom(offset <= _size);
247 if (count == std::dynamic_extent) {
248 count = _size - offset;
249 }
250
251 hi_axiom(offset + count <= _size);
252 return {advance_bytes(_pointer, _size - count), count};
253 }
254
255 template<typename T, size_t E = std::dynamic_extent>
256 [[nodiscard]] constexpr friend std::span<T, E> as_span(const_void_span const& rhs) noexcept requires(std::is_const_v<T>)
257 {
258 if constexpr (E == std::dynamic_extent) {
259 hi_axiom(std::bit_cast<std::uintptr_t>(rhs._pointer) % std::alignment_of_v<T> == 0);
260 hi_axiom((rhs._size / sizeof(T)) * sizeof(T) == rhs._size);
261 return {static_cast<T *>(rhs._pointer), rhs._size / sizeof(T)};
262
263 } else {
264 hi_axiom(std::bit_cast<std::uintptr_t>(rhs._pointer) % std::alignment_of_v<T> == 0);
265 hi_axiom(E * sizeof(T) <= rhs._size);
266 return {static_cast<T *>(rhs._pointer), E};
267 }
268 }
269
270 template<typename CharT, typename Traits = std::char_traits<CharT>>
271 [[nodiscard]] constexpr friend std::basic_string_view<CharT, Traits> as_basic_string_view(const_void_span const& rhs) noexcept
272 {
273 hi_axiom(std::bit_cast<std::uintptr_t>(rhs._pointer) % std::alignment_of_v<CharT> == 0);
274 hi_axiom((rhs._size / sizeof(CharT)) * sizeof(CharT) == rhs._size);
275 return {static_cast<CharT const *>(rhs._pointer), rhs._size / sizeof(CharT)};
276 }
277
278 [[nodiscard]] constexpr friend std::string_view as_string_view(const_void_span const& rhs) noexcept
279 {
280 return as_basic_string_view<char>(rhs);
281 }
282
283 [[nodiscard]] constexpr friend bstring_view as_bstring_view(const_void_span const& rhs) noexcept
284 {
285 return as_basic_string_view<std::byte, byte_char_traits>(rhs);
286 }
287
288private:
289 pointer _pointer = nullptr;
290 size_type _size = 0;
291};
292
293} // namespace hi::inline v1
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:199
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253
DOXYGEN BUG.
Definition algorithm.hpp:13
void * advance_bytes(void *ptr, std::ptrdiff_t distance) noexcept
Advance a pointer by a number of bytes.
Definition memory.hpp:191
Definition void_span.hpp:17
Definition void_span.hpp:154
Definition concepts.hpp:36
T data(T... args)
T size(T... args)