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