HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
placement.hpp
1// Copyright Take Vos 2019, 2021-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 "../utility/utility.hpp"
8#include "../macros.hpp"
9#include <span>
10#include <bit>
11#include <stdexcept>
12#include <memory>
13#include <new>
14
15hi_export_module(hikogui.parser.placement);
16
17
18hi_warning_push();
19// C26492: Don't use const_cast to cast away const or volatile (type.3).
20// placement new requires non-const pointer, even if the non-constructor initializer doesn't
21// modify the memory.
22hi_warning_ignore_msvc(26492);
23// We are going to remove placement.hpp anyway.
24hi_warning_ignore_msvc(26403);
25hi_warning_ignore_msvc(26460);
26
27hi_export namespace hi::inline v1 {
28template<typename T>
29inline bool check_alignment(void const *ptr) noexcept
30{
31 return std::bit_cast<uintptr_t>(ptr) % alignof(T) == 0;
32}
33
34template<typename T>
36public:
37 static_assert(std::is_trivially_default_constructible_v<T>);
38 static_assert(std::is_trivially_destructible_v<T>);
39
40 using value_type = T;
41
42 template<byte_like Byte>
43 placement_ptr(std::span<Byte> bytes, std::size_t& offset)
44 {
45 if (offset + sizeof(value_type) > bytes.size()) {
46 throw std::bad_alloc();
47 }
48
49 auto ptr = bytes.data() + offset;
50 offset += sizeof(value_type);
51 std::uninitialized_default_construct_n(reinterpret_cast<value_type *>(ptr), 1);
52 _ptr = std::launder(reinterpret_cast<value_type *>(ptr));
53 }
54
56 {
57 std::destroy_at(_ptr);
58 }
59
60 placement_ptr() = delete;
61 placement_ptr(placement_ptr const&) = delete;
62 placement_ptr(placement_ptr&&) = delete;
63 placement_ptr& operator=(placement_ptr const&) = delete;
64 placement_ptr& operator=(placement_ptr&&) = delete;
65
66 value_type *operator->() const noexcept
67 {
68 return _ptr;
69 }
70
71 value_type& operator*() const noexcept
72 {
73 return *_ptr;
74 }
75
76private:
77 value_type *_ptr;
78};
79
80template<typename T, typename Byte>
81[[nodiscard]] auto make_placement_ptr(std::span<Byte> bytes, std::size_t& offset)
82{
83 return placement_ptr<copy_cv_t<T, Byte>>(bytes, offset);
84}
85
86template<typename T, typename Byte>
87[[nodiscard]] auto make_placement_ptr(std::span<Byte> bytes, std::size_t&& offset = 0)
88{
89 std::size_t _offset = offset;
90 return make_placement_ptr<T>(bytes, _offset);
91}
92
93template<typename T>
95public:
96 static_assert(std::is_trivially_default_constructible_v<T>);
97 static_assert(std::is_trivially_destructible_v<T>);
98
99 using value_type = T;
100 using container_type = std::span<value_type>;
101 using iterator = container_type::iterator;
102 using reference = container_type::reference;
103 using pointer = container_type::pointer;
104
105 template<byte_like Byte>
106 placement_array(std::span<Byte> bytes, std::size_t& offset, std::size_t n)
107 {
108 if (offset + n * sizeof(T) > bytes.size()) {
109 throw std::bad_alloc();
110 }
111
112 auto const ptr = bytes.data() + offset;
113 offset += sizeof(T) * n;
114
115 std::uninitialized_default_construct_n(reinterpret_cast<value_type *>(ptr), n);
116 _items = {std::launder(reinterpret_cast<value_type *>(ptr)), n};
117 }
118
119 placement_array(placement_array const&) = delete;
121 placement_array& operator=(placement_array const&) = delete;
122 placement_array& operator=(placement_array&&) = delete;
123
125 {
126 std::destroy(begin(), end());
127 }
128
129 operator std::span<value_type>() const noexcept
130 {
131 return _items;
132 }
133
134 std::size_t size() const noexcept
135 {
136 return std::distance(begin(), end());
137 }
138
139 iterator begin() const noexcept
140 {
141 return _items.begin();
142 }
143
144 iterator end() const noexcept
145 {
146 return _items.end();
147 }
148
149 reference operator[](ssize_t offset) const noexcept
150 {
151 return _items[offset];
152 }
153
154private:
155 std::span<value_type> _items;
156};
157
158template<typename T, byte_like Byte>
159[[nodiscard]] auto make_placement_array(std::span<Byte> bytes, std::size_t& offset, std::size_t n)
160{
161 return placement_array<copy_cv_t<T, Byte>>(bytes, offset, n);
162}
163
164template<typename T, byte_like Byte>
165[[nodiscard]] auto make_placement_array(std::span<Byte> bytes, std::size_t&& offset, std::size_t n)
166{
167 std::size_t _offset = offset;
168 return make_placement_array<T>(bytes, _offset, n);
169}
170
171template<typename T, byte_like Byte>
172[[nodiscard]] auto make_placement_array(std::span<Byte> bytes, std::size_t& offset)
173{
174 auto const n = bytes.size() / ssizeof(T);
175 return make_placement_array<T>(bytes, offset, n);
176}
177
178template<typename T, byte_like Byte>
179[[nodiscard]] auto make_placement_array(std::span<Byte> bytes, std::size_t&& offset = 0)
180{
181 std::size_t _offset = offset;
182 return make_placement_array<T>(bytes, _offset);
183}
184
185} // namespace hi::inline v1
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition placement.hpp:35
Definition placement.hpp:94
T distance(T... args)