10#include "exception.hpp"
17inline bool check_alignment(
void const *ptr) {
18 return reinterpret_cast<ptrdiff_t
>(ptr) %
alignof(T) == 0;
22template<
typename T,
typename Byte>
25 std::is_same_v<std::remove_cv_t<Byte>,std::byte> ||
26 std::is_same_v<std::remove_cv_t<Byte>,
char> ||
27 std::is_same_v<std::remove_cv_t<Byte>,
unsigned char> ||
28 std::is_same_v<std::remove_cv_t<Byte>,
signed char>,
29 "Byte must be a byte type"
31 static_assert(std::is_trivially_constructible_v<T>);
32 static_assert(!std::is_const_v<Byte> || std::is_trivially_destructible_v<T>);
39 Byte *_ptr = bytes.data() + offset;
41 ptr =
new(
const_cast<std::remove_cv_t<Byte> *
>(_ptr)) T;
48 value_type *operator->()
const noexcept {
52 value_type &operator*()
const noexcept {
57template<
typename T,
typename Byte>
63template<
typename T,
typename Byte>
64placement_ptr<T,Byte> unsafe_make_placement_ptr(std::span<Byte> bytes, ssize_t &&offset = 0)
66 ssize_t _offset = offset;
67 return unsafe_make_placement_ptr<T>(bytes, _offset);
70template<
typename T,
typename Byte>
71bool check_placement_ptr(std::span<Byte> bytes, ssize_t offset = 0)
73 return check_alignment<T>(bytes.data()) && (offset +
sizeof(T) <= std::size(bytes));
76template<
typename T,
typename Byte>
77placement_ptr<T,Byte> make_placement_ptr(std::span<Byte> bytes, ssize_t &offset)
79 tt_parse_check(check_placement_ptr<T>(bytes, offset),
"Parsing beyond end of buffer");
80 return placement_ptr<T,Byte>(bytes, offset);
83template<
typename T,
typename Byte>
84placement_ptr<T,Byte> make_placement_ptr(std::span<Byte> bytes, ssize_t &&offset = 0)
86 ssize_t _offset = offset;
87 return make_placement_ptr<T>(bytes, _offset);
90template<
typename T,
typename Byte>
93 std::is_same_v<std::remove_cv_t<Byte>,std::byte> ||
94 std::is_same_v<std::remove_cv_t<Byte>,
char> ||
95 std::is_same_v<std::remove_cv_t<Byte>,
unsigned char> ||
96 std::is_same_v<std::remove_cv_t<Byte>,
signed char>,
97 "Byte must be a byte type"
99 static_assert(std::is_trivially_constructible_v<T>);
100 static_assert(!std::is_const_v<T> || std::is_trivially_destructible_v<T>);
109 ttlet bytes_ = bytes.data();
111 _begin = bytes_ + offset,
112 offset += ssizeof(T) * n;
113 _end = bytes_ + offset;
115 for (
ssize_t i = 0; i < n; i++) {
116 [[maybe_unused]]
auto *ptr =
new(
const_cast<std::remove_cv_t<Byte> *
>(_begin + i * ssizeof(T))) T;
126 std::destroy(begin(), end());
129 size_t size()
const noexcept {
130 return static_cast<size_t>(end() - begin());
133 bool contains(
ssize_t index)
const noexcept {
134 return index < std::ssize(*
this);
137 value_type *begin()
const noexcept {
138 return std::launder(
reinterpret_cast<value_type *
>(_begin));
141 value_type *end()
const noexcept {
142 return std::launder(
reinterpret_cast<value_type *
>(_end));
145 value_type &operator[](
ssize_t offset)
const noexcept {
146 return *(begin() + offset);
150template<
typename T,
typename Byte>
156template<
typename T,
typename Byte>
157placement_array<T,Byte> unsafe_make_placement_array(std::span<Byte> bytes, ssize_t &&offset, ssize_t n)
159 ssize_t _offset = offset;
160 return unsafe_make_placement_array<T>(bytes, _offset, n);
163template<
typename T,
typename Byte>
164placement_array<T,Byte> unsafe_make_placement_array(std::span<Byte> bytes, ssize_t &offset)
166 ttlet n = std::size(bytes) /
sizeof(T);
167 return unsafe_make_placement_array<T>(bytes, offset, n);
170template<
typename T,
typename Byte>
171placement_array<T,Byte> unsafe_make_placement_array(std::span<Byte> bytes, ssize_t &&offset = 0)
173 size_t _offset = offset;
174 return unsafe_make_placement_array<T>(bytes, _offset);
177template<
typename T,
typename Byte>
178bool check_placement_array(std::span<Byte> bytes, ssize_t offset, ssize_t n)
180 return check_alignment<T>(bytes.data()) && (offset + (n * ssizeof(T)) <= std::ssize(bytes));
183template<
typename T,
typename Byte>
184bool check_placement_array(std::span<Byte> bytes, ssize_t offset)
186 return check_alignment<T>(bytes.data());
189template<
typename T,
typename Byte>
190placement_array<T,Byte> make_placement_array(std::span<Byte> bytes, ssize_t &offset, ssize_t n)
192 tt_parse_check(check_placement_array<T>(bytes, offset, n),
"Parsing beyond end of buffer");
193 return placement_array<T,Byte>(bytes, offset, n);
196template<
typename T,
typename Byte>
197placement_array<T,Byte> make_placement_array(std::span<Byte> bytes, ssize_t &&offset, ssize_t n)
199 ssize_t _offset = offset;
200 return make_placement_array<T>(bytes, _offset, n);
203template<
typename T,
typename Byte>
204placement_array<T,Byte> make_placement_array(std::span<Byte> bytes, ssize_t &offset)
206 ttlet n = std::ssize(bytes) / ssizeof(T);
207 return make_placement_array<T>(bytes, offset, n);
210template<
typename T,
typename Byte>
211placement_array<T,Byte> make_placement_array(std::span<Byte> bytes, ssize_t &&offset = 0)
213 ssize_t _offset = offset;
214 return make_placement_array<T>(bytes, _offset);
typename copy_cv< To, From >::type copy_cv_t
Type-trait to copy const volatile qualifiers from one type to another.
Definition type_traits.hpp:269
Definition placement.hpp:23
Definition placement.hpp:91