HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
placement.hpp
1// Copyright Take Vos 2019-2020.
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 "required.hpp"
8#include "type_traits.hpp"
9#include "cast.hpp"
10#include "exception.hpp"
11#include "check.hpp"
12#include <span>
13
14namespace tt {
15
16template<typename T>
17inline bool check_alignment(void const *ptr) {
18 return reinterpret_cast<ptrdiff_t>(ptr) % alignof(T) == 0;
19}
20
21
22template<typename T,typename Byte>
24 static_assert(
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"
30 );
31 static_assert(std::is_trivially_constructible_v<T>);
32 static_assert(!std::is_const_v<Byte> || std::is_trivially_destructible_v<T>);
33
34 using value_type = copy_cv_t<T,Byte>;
35 value_type *ptr;
36
37public:
38 placement_ptr(std::span<Byte> bytes, ssize_t &offset) {
39 Byte *_ptr = bytes.data() + offset;
40 offset += ssizeof(T);
41 ptr = new(const_cast<std::remove_cv_t<Byte> *>(_ptr)) T;
42 }
43
45 std::destroy_at(ptr);
46 }
47
48 value_type *operator->() const noexcept {
49 return ptr;
50 }
51
52 value_type &operator*() const noexcept {
53 return *ptr;
54 }
55};
56
57template<typename T,typename Byte>
58placement_ptr<T,Byte> unsafe_make_placement_ptr(std::span<Byte> bytes, ssize_t &offset)
59{
60 return placement_ptr<T,Byte>(bytes, offset);
61}
62
63template<typename T,typename Byte>
64placement_ptr<T,Byte> unsafe_make_placement_ptr(std::span<Byte> bytes, ssize_t &&offset = 0)
65{
66 ssize_t _offset = offset;
67 return unsafe_make_placement_ptr<T>(bytes, _offset);
68}
69
70template<typename T,typename Byte>
71bool check_placement_ptr(std::span<Byte> bytes, ssize_t offset = 0)
72{
73 return check_alignment<T>(bytes.data()) && (offset + sizeof(T) <= std::size(bytes));
74}
75
76template<typename T,typename Byte>
77placement_ptr<T,Byte> make_placement_ptr(std::span<Byte> bytes, ssize_t &offset)
78{
79 tt_parse_check(check_placement_ptr<T>(bytes, offset), "Parsing beyond end of buffer");
80 return placement_ptr<T,Byte>(bytes, offset);
81}
82
83template<typename T,typename Byte>
84placement_ptr<T,Byte> make_placement_ptr(std::span<Byte> bytes, ssize_t &&offset = 0)
85{
86 ssize_t _offset = offset;
87 return make_placement_ptr<T>(bytes, _offset);
88}
89
90template<typename T, typename Byte>
92 static_assert(
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"
98 );
99 static_assert(std::is_trivially_constructible_v<T>);
100 static_assert(!std::is_const_v<T> || std::is_trivially_destructible_v<T>);
101
102 using value_type = copy_cv_t<T,Byte>;
103
104 Byte *_begin;
105 Byte *_end;
106
107public:
108 placement_array(std::span<Byte> bytes, ssize_t &offset, ssize_t n) {
109 ttlet bytes_ = bytes.data();
110
111 _begin = bytes_ + offset,
112 offset += ssizeof(T) * n;
113 _end = bytes_ + offset;
114
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;
117 }
118 }
119
120 placement_array(placement_array const &) = delete;
121 placement_array(placement_array &&) = delete;
122 placement_array &operator=(placement_array const &) = delete;
123 placement_array &operator=(placement_array &&) = delete;
124
126 std::destroy(begin(), end());
127 }
128
129 size_t size() const noexcept {
130 return static_cast<size_t>(end() - begin());
131 }
132
133 bool contains(ssize_t index) const noexcept {
134 return index < std::ssize(*this);
135 }
136
137 value_type *begin() const noexcept {
138 return std::launder(reinterpret_cast<value_type *>(_begin));
139 }
140
141 value_type *end() const noexcept {
142 return std::launder(reinterpret_cast<value_type *>(_end));
143 }
144
145 value_type &operator[](ssize_t offset) const noexcept {
146 return *(begin() + offset);
147 }
148};
149
150template<typename T,typename Byte>
151placement_array<T,Byte> unsafe_make_placement_array(std::span<Byte> bytes, ssize_t &offset, ssize_t n)
152{
153 return placement_array<T,Byte>(bytes, offset, n);
154}
155
156template<typename T,typename Byte>
157placement_array<T,Byte> unsafe_make_placement_array(std::span<Byte> bytes, ssize_t &&offset, ssize_t n)
158{
159 ssize_t _offset = offset;
160 return unsafe_make_placement_array<T>(bytes, _offset, n);
161}
162
163template<typename T,typename Byte>
164placement_array<T,Byte> unsafe_make_placement_array(std::span<Byte> bytes, ssize_t &offset)
165{
166 ttlet n = std::size(bytes) / sizeof(T);
167 return unsafe_make_placement_array<T>(bytes, offset, n);
168}
169
170template<typename T,typename Byte>
171placement_array<T,Byte> unsafe_make_placement_array(std::span<Byte> bytes, ssize_t &&offset = 0)
172{
173 size_t _offset = offset;
174 return unsafe_make_placement_array<T>(bytes, _offset);
175}
176
177template<typename T,typename Byte>
178bool check_placement_array(std::span<Byte> bytes, ssize_t offset, ssize_t n)
179{
180 return check_alignment<T>(bytes.data()) && (offset + (n * ssizeof(T)) <= std::ssize(bytes));
181}
182
183template<typename T,typename Byte>
184bool check_placement_array(std::span<Byte> bytes, ssize_t offset)
185{
186 return check_alignment<T>(bytes.data());
187}
188
189template<typename T,typename Byte>
190placement_array<T,Byte> make_placement_array(std::span<Byte> bytes, ssize_t &offset, ssize_t n)
191{
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);
194}
195
196template<typename T,typename Byte>
197placement_array<T,Byte> make_placement_array(std::span<Byte> bytes, ssize_t &&offset, ssize_t n)
198{
199 ssize_t _offset = offset;
200 return make_placement_array<T>(bytes, _offset, n);
201}
202
203template<typename T,typename Byte>
204placement_array<T,Byte> make_placement_array(std::span<Byte> bytes, ssize_t &offset)
205{
206 ttlet n = std::ssize(bytes) / ssizeof(T);
207 return make_placement_array<T>(bytes, offset, n);
208}
209
210template<typename T,typename Byte>
211placement_array<T,Byte> make_placement_array(std::span<Byte> bytes, ssize_t &&offset = 0)
212{
213 ssize_t _offset = offset;
214 return make_placement_array<T>(bytes, _offset);
215}
216
217}
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