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