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