EnTT 3.12.0
Loading...
Searching...
No Matches
node.hpp
1#ifndef ENTT_META_NODE_HPP
2#define ENTT_META_NODE_HPP
3
4#include <cstddef>
5#include <memory>
6#include <type_traits>
7#include <utility>
8#include "../config/config.h"
9#include "../container/dense_map.hpp"
10#include "../core/attribute.h"
11#include "../core/enum.hpp"
12#include "../core/fwd.hpp"
13#include "../core/type_info.hpp"
14#include "../core/type_traits.hpp"
15#include "../core/utility.hpp"
16#include "context.hpp"
17#include "type_traits.hpp"
18
19namespace entt {
20
21class meta_any;
22class meta_type;
23struct meta_handle;
24
30namespace internal {
31
32enum class meta_traits : std::uint32_t {
33 is_none = 0x0000,
34 is_const = 0x0001,
35 is_static = 0x0002,
36 is_arithmetic = 0x0004,
37 is_integral = 0x0008,
38 is_signed = 0x0010,
39 is_array = 0x0020,
40 is_enum = 0x0040,
41 is_class = 0x0080,
42 is_meta_pointer_like = 0x0100,
43 is_meta_sequence_container = 0x0200,
44 is_meta_associative_container = 0x0400,
45 _entt_enum_as_bitmask
46};
47
48struct meta_type_node;
49
50struct meta_prop_node {
51 meta_type_node (*type)(const meta_context &) noexcept {};
52 std::shared_ptr<void> value{};
53};
54
55struct meta_base_node {
56 meta_type_node (*type)(const meta_context &) noexcept {};
57 const void *(*cast)(const void *) noexcept {};
58};
59
60struct meta_conv_node {
61 meta_any (*conv)(const meta_ctx &, const void *){};
62};
63
64struct meta_ctor_node {
65 using size_type = std::size_t;
66
67 size_type arity{0u};
68 meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
69 meta_any (*invoke)(const meta_ctx &, meta_any *const){};
70};
71
72struct meta_dtor_node {
73 void (*dtor)(void *){};
74};
75
76struct meta_data_node {
77 using size_type = std::size_t;
78
79 meta_traits traits{meta_traits::is_none};
80 size_type arity{0u};
81 meta_type_node (*type)(const meta_context &) noexcept {};
82 meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
83 bool (*set)(meta_handle, meta_any){};
84 meta_any (*get)(const meta_ctx &, meta_handle){};
85 dense_map<id_type, meta_prop_node, identity> prop{};
86};
87
88struct meta_func_node {
89 using size_type = std::size_t;
90
91 meta_traits traits{meta_traits::is_none};
92 size_type arity{0u};
93 meta_type_node (*ret)(const meta_context &) noexcept {};
94 meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
95 meta_any (*invoke)(const meta_ctx &, meta_handle, meta_any *const){};
96 std::shared_ptr<meta_func_node> next{};
97 dense_map<id_type, meta_prop_node, identity> prop{};
98};
99
100struct meta_template_node {
101 using size_type = std::size_t;
102
103 size_type arity{0u};
104 meta_type_node (*type)(const meta_context &) noexcept {};
105 meta_type_node (*arg)(const meta_context &, const size_type) noexcept {};
106};
107
108struct meta_type_descriptor {
109 dense_map<id_type, meta_ctor_node, identity> ctor{};
110 dense_map<id_type, meta_base_node, identity> base{};
111 dense_map<id_type, meta_conv_node, identity> conv{};
112 dense_map<id_type, meta_data_node, identity> data{};
113 dense_map<id_type, meta_func_node, identity> func{};
114 dense_map<id_type, meta_prop_node, identity> prop{};
115};
116
117struct meta_type_node {
118 using size_type = std::size_t;
119
120 const type_info *info{};
121 id_type id{};
122 meta_traits traits{meta_traits::is_none};
123 size_type size_of{0u};
124 meta_type_node (*resolve)(const meta_context &) noexcept {};
125 meta_type_node (*remove_pointer)(const meta_context &) noexcept {};
126 meta_any (*default_constructor)(const meta_ctx &){};
127 double (*conversion_helper)(void *, const void *){};
128 meta_any (*from_void)(const meta_ctx &, void *, const void *){};
129 meta_template_node templ{};
130 meta_dtor_node dtor{};
131 std::shared_ptr<meta_type_descriptor> details{};
132};
133
134template<typename Type>
135meta_type_node resolve(const meta_context &) noexcept;
136
137template<typename... Args>
138[[nodiscard]] auto meta_arg_node(const meta_context &context, type_list<Args...>, [[maybe_unused]] const std::size_t index) noexcept {
139 [[maybe_unused]] std::size_t pos{};
140 meta_type_node (*value)(const meta_context &) noexcept = nullptr;
141 ((value = (pos++ == index ? &resolve<std::remove_cv_t<std::remove_reference_t<Args>>> : value)), ...);
142 ENTT_ASSERT(value != nullptr, "Out of bounds");
143 return value(context);
144}
145
146[[nodiscard]] inline const void *try_cast(const meta_context &context, const meta_type_node &from, const meta_type_node &to, const void *instance) noexcept {
147 if(from.info && to.info && *from.info == *to.info) {
148 return instance;
149 }
150
151 if(from.details) {
152 for(auto &&curr: from.details->base) {
153 if(const void *elem = try_cast(context, curr.second.type(context), to, curr.second.cast(instance)); elem) {
154 return elem;
155 }
156 }
157 }
158
159 return nullptr;
160}
161
162[[nodiscard]] inline const meta_type_node *try_resolve(const meta_context &context, const type_info &info) noexcept {
163 const auto it = context.value.find(info.hash());
164 return it != context.value.end() ? &it->second : nullptr;
165}
166
167template<typename Type>
168[[nodiscard]] meta_type_node resolve(const meta_context &context) noexcept {
169 static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");
170
171 if(auto *elem = try_resolve(context, type_id<Type>()); elem) {
172 return *elem;
173 }
174
175 meta_type_node node{
176 &type_id<Type>(),
177 type_id<Type>().hash(),
178 (std::is_arithmetic_v<Type> ? meta_traits::is_arithmetic : meta_traits::is_none)
179 | (std::is_integral_v<Type> ? meta_traits::is_integral : meta_traits::is_none)
180 | (std::is_signed_v<Type> ? meta_traits::is_signed : meta_traits::is_none)
181 | (std::is_array_v<Type> ? meta_traits::is_array : meta_traits::is_none)
182 | (std::is_enum_v<Type> ? meta_traits::is_enum : meta_traits::is_none)
183 | (std::is_class_v<Type> ? meta_traits::is_class : meta_traits::is_none)
184 | (is_meta_pointer_like_v<Type> ? meta_traits::is_meta_pointer_like : meta_traits::is_none)
185 | (is_complete_v<meta_sequence_container_traits<Type>> ? meta_traits::is_meta_sequence_container : meta_traits::is_none)
186 | (is_complete_v<meta_associative_container_traits<Type>> ? meta_traits::is_meta_associative_container : meta_traits::is_none),
187 size_of_v<Type>,
188 &resolve<Type>,
189 &resolve<std::remove_cv_t<std::remove_pointer_t<Type>>>};
190
191 if constexpr(std::is_default_constructible_v<Type>) {
192 node.default_constructor = +[](const meta_ctx &ctx) {
193 return meta_any{ctx, std::in_place_type<Type>};
194 };
195 }
196
197 if constexpr(std::is_arithmetic_v<Type>) {
198 node.conversion_helper = +[](void *bin, const void *value) {
199 return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(*static_cast<const double *>(value))) : static_cast<double>(*static_cast<const Type *>(value));
200 };
201 } else if constexpr(std::is_enum_v<Type>) {
202 node.conversion_helper = +[](void *bin, const void *value) {
203 return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(static_cast<std::underlying_type_t<Type>>(*static_cast<const double *>(value)))) : static_cast<double>(*static_cast<const Type *>(value));
204 };
205 }
206
207 if constexpr(!std::is_same_v<Type, void> && !std::is_function_v<Type>) {
208 node.from_void = +[](const meta_ctx &ctx, void *element, const void *as_const) {
209 if(element) {
210 return meta_any{ctx, std::in_place_type<std::decay_t<Type> &>, *static_cast<std::decay_t<Type> *>(element)};
211 }
212
213 return meta_any{ctx, std::in_place_type<const std::decay_t<Type> &>, *static_cast<const std::decay_t<Type> *>(as_const)};
214 };
215 }
216
217 if constexpr(is_complete_v<meta_template_traits<Type>>) {
218 node.templ = meta_template_node{
219 meta_template_traits<Type>::args_type::size,
220 &resolve<typename meta_template_traits<Type>::class_type>,
221 +[](const meta_context &area, const std::size_t index) noexcept { return meta_arg_node(area, typename meta_template_traits<Type>::args_type{}, index); }};
222 }
223
224 return node;
225}
226
227} // namespace internal
228
234} // namespace entt
235
236#endif
EnTT default namespace.
Definition: dense_map.hpp:21
std::uint32_t id_type
Alias declaration for type identifiers.
Definition: fwd.hpp:13
meta_type resolve(const meta_ctx &ctx) noexcept
Returns the meta type associated with a given type.
Definition: resolve.hpp:21