10#include "exception.hpp"
18hi_warning_ignore_msvc(26492)
20namespace
hi::inline
v1 {
23inline bool check_alignment(
void const *ptr)
noexcept
25 return std::bit_cast<uintptr_t>(ptr) %
alignof(T) == 0;
28template<
typename T,
typename Byte>
31 std::is_same_v<std::remove_cv_t<Byte>, std::byte> || std::is_same_v<std::remove_cv_t<Byte>,
char> ||
32 std::is_same_v<std::remove_cv_t<Byte>,
unsigned char> || std::is_same_v<std::remove_cv_t<Byte>,
signed char>,
33 "Byte must be a byte type");
34 static_assert(std::is_trivially_constructible_v<T>);
35 static_assert(!std::is_const_v<Byte> || std::is_trivially_destructible_v<T>);
37 using value_type = copy_cv_t<T, Byte>;
41 placement_ptr(std::span<Byte> bytes,
std::size_t& offset)
43 Byte *_ptr = bytes.data() + offset;
45 ptr =
new (
const_cast<std::remove_const_t<Byte> *
>(_ptr)) T;
53 placement_ptr() =
delete;
54 placement_ptr(placement_ptr
const&) =
delete;
55 placement_ptr(placement_ptr&&) =
delete;
56 placement_ptr& operator=(placement_ptr
const&) =
delete;
57 placement_ptr& operator=(placement_ptr&&) =
delete;
59 value_type *operator->() const noexcept
64 value_type& operator*() const noexcept
70template<
typename T,
typename Byte>
71placement_ptr<T, Byte> unsafe_make_placement_ptr(std::span<Byte> bytes,
std::size_t& offset)
73 return placement_ptr<T, Byte>(bytes, offset);
76template<
typename T,
typename Byte>
77placement_ptr<T, Byte> unsafe_make_placement_ptr(std::span<Byte> bytes,
std::size_t&& offset = 0)
80 return unsafe_make_placement_ptr<T>(bytes, _offset);
83template<
typename T,
typename Byte>
84bool check_placement_ptr(std::span<Byte> bytes,
std::size_t offset = 0)
86 return check_alignment<T>(bytes.data()) && (offset +
sizeof(T) <= size(bytes));
89template<
typename T,
typename Byte>
90placement_ptr<T, Byte> make_placement_ptr(std::span<Byte> bytes,
std::size_t& offset)
92 hi_parse_check(check_placement_ptr<T>(bytes, offset),
"Parsing beyond end of buffer");
93 return placement_ptr<T, Byte>(bytes, offset);
96template<
typename T,
typename Byte>
97placement_ptr<T, Byte> make_placement_ptr(std::span<Byte> bytes,
std::size_t&& offset = 0)
100 return make_placement_ptr<T>(bytes, _offset);
103template<
typename T,
typename Byte>
104class placement_array {
106 std::is_same_v<std::remove_cv_t<Byte>, std::byte> || std::is_same_v<std::remove_cv_t<Byte>,
char> ||
107 std::is_same_v<std::remove_cv_t<Byte>,
unsigned char> || std::is_same_v<std::remove_cv_t<Byte>,
signed char>,
108 "Byte must be a byte type");
109 static_assert(std::is_trivially_constructible_v<T>);
110 static_assert(!std::is_const_v<T> || std::is_trivially_destructible_v<T>);
112 using value_type = copy_cv_t<T, Byte>;
120 hilet bytes_ = bytes.data();
122 _begin = bytes_ + offset;
123 offset +=
sizeof(T) * n;
124 _end = bytes_ + offset;
126 for (
auto i = 0_uz; i <
n; i++) {
127 [[maybe_unused]]
auto *ptr =
new (
const_cast<std::remove_cv_t<Byte> *
>(_begin + i *
sizeof(T))) T;
131 placement_array(placement_array
const&) =
delete;
132 placement_array(placement_array&&) =
delete;
133 placement_array& operator=(placement_array
const&) =
delete;
134 placement_array& operator=(placement_array&&) =
delete;
148 return index < size();
151 value_type *
begin() const noexcept
153 return std::launder(
reinterpret_cast<value_type *
>(_begin));
156 value_type *
end() const noexcept
158 return std::launder(
reinterpret_cast<value_type *
>(_end));
161 value_type& operator[](ssize_t offset)
const noexcept
163 return *(
begin() + offset);
167template<
typename T,
typename Byte>
168placement_array<T, Byte> unsafe_make_placement_array(std::span<Byte> bytes,
std::size_t& offset,
std::size_t n)
170 return placement_array<T, Byte>(bytes, offset, n);
173template<
typename T,
typename Byte>
174placement_array<T, Byte> unsafe_make_placement_array(std::span<Byte> bytes,
std::size_t&& offset,
std::size_t n)
177 return unsafe_make_placement_array<T>(bytes, _offset, n);
180template<
typename T,
typename Byte>
181placement_array<T, Byte> unsafe_make_placement_array(std::span<Byte> bytes,
std::size_t& offset)
183 hilet n = bytes.size() /
sizeof(T);
184 return unsafe_make_placement_array<T>(bytes, offset, n);
187template<
typename T,
typename Byte>
188placement_array<T, Byte> unsafe_make_placement_array(std::span<Byte> bytes,
std::size_t&& offset = 0)
191 return unsafe_make_placement_array<T>(bytes, _offset);
194template<
typename T,
typename Byte>
197 return check_alignment<T>(bytes.data()) && (offset + (
n *
sizeof(T)) <= bytes.size());
200template<
typename T,
typename Byte>
201bool check_placement_array(std::span<Byte> bytes,
std::size_t offset)
203 return check_alignment<T>(bytes.data());
206template<
typename T,
typename Byte>
209 hi_parse_check(check_placement_array<T>(bytes, offset, n),
"Parsing beyond end of buffer");
210 return placement_array<T, Byte>(bytes, offset, n);
213template<
typename T,
typename Byte>
217 return make_placement_array<T>(bytes, _offset, n);
220template<
typename T,
typename Byte>
221placement_array<T, Byte> make_placement_array(std::span<Byte> bytes,
std::size_t& offset)
223 hilet n = bytes.size() / ssizeof(T);
224 return make_placement_array<T>(bytes, offset, n);
227template<
typename T,
typename Byte>
228placement_array<T, Byte> make_placement_array(std::span<Byte> bytes,
std::size_t&& offset = 0)
231 return make_placement_array<T>(bytes, _offset);
Utilities used by the HikoGUI library itself.
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:15
geometry/margins.hpp
Definition assert.hpp:18