EnTT  3.10.0
node.hpp
1 #ifndef ENTT_META_NODE_HPP
2 #define ENTT_META_NODE_HPP
3 
4 #include <cstddef>
5 #include <type_traits>
6 #include <utility>
7 #include "../config/config.h"
8 #include "../core/attribute.h"
9 #include "../core/enum.hpp"
10 #include "../core/fwd.hpp"
11 #include "../core/type_info.hpp"
12 #include "../core/type_traits.hpp"
13 #include "type_traits.hpp"
14 
15 namespace entt {
16 
17 class meta_any;
18 class meta_type;
19 struct meta_handle;
20 
26 namespace internal {
27 
28 enum class meta_traits : std::uint32_t {
29  is_none = 0x0000,
30  is_const = 0x0001,
31  is_static = 0x0002,
32  is_arithmetic = 0x0004,
33  is_array = 0x0008,
34  is_enum = 0x0010,
35  is_class = 0x0020,
36  is_pointer = 0x0040,
37  is_meta_pointer_like = 0x0080,
38  is_meta_sequence_container = 0x0100,
39  is_meta_associative_container = 0x0200,
40  _entt_enum_as_bitmask
41 };
42 
43 struct meta_type_node;
44 
45 struct meta_prop_node {
46  meta_prop_node *next;
47  const meta_any &id;
48  meta_any &value;
49 };
50 
51 struct meta_base_node {
52  meta_base_node *next;
53  meta_type_node *const type;
54  meta_any (*const cast)(meta_any) ENTT_NOEXCEPT;
55 };
56 
57 struct meta_conv_node {
58  meta_conv_node *next;
59  meta_type_node *const type;
60  meta_any (*const conv)(const meta_any &);
61 };
62 
63 struct meta_ctor_node {
64  using size_type = std::size_t;
65  meta_ctor_node *next;
66  const size_type arity;
67  meta_type (*const arg)(const size_type) ENTT_NOEXCEPT;
68  meta_any (*const invoke)(meta_any *const);
69 };
70 
71 struct meta_data_node {
72  using size_type = std::size_t;
73  id_type id;
74  const meta_traits traits;
75  meta_data_node *next;
76  meta_prop_node *prop;
77  const size_type arity;
78  meta_type_node *const type;
79  meta_type (*const arg)(const size_type) ENTT_NOEXCEPT;
80  bool (*const set)(meta_handle, meta_any);
81  meta_any (*const get)(meta_handle);
82 };
83 
84 struct meta_func_node {
85  using size_type = std::size_t;
86  id_type id;
87  const meta_traits traits;
88  meta_func_node *next;
89  meta_prop_node *prop;
90  const size_type arity;
91  meta_type_node *const ret;
92  meta_type (*const arg)(const size_type) ENTT_NOEXCEPT;
93  meta_any (*const invoke)(meta_handle, meta_any *const);
94 };
95 
96 struct meta_template_node {
97  using size_type = std::size_t;
98  const size_type arity;
99  meta_type_node *const type;
100  meta_type_node *(*const arg)(const size_type)ENTT_NOEXCEPT;
101 };
102 
103 struct meta_type_node {
104  using size_type = std::size_t;
105  const type_info *info;
106  id_type id;
107  const meta_traits traits;
108  meta_type_node *next;
109  meta_prop_node *prop;
110  const size_type size_of;
111  meta_any (*const default_constructor)();
112  double (*const conversion_helper)(void *, const void *);
113  const meta_template_node *const templ;
114  meta_ctor_node *ctor{nullptr};
115  meta_base_node *base{nullptr};
116  meta_conv_node *conv{nullptr};
117  meta_data_node *data{nullptr};
118  meta_func_node *func{nullptr};
119  void (*dtor)(void *){nullptr};
120 };
121 
122 template<typename... Args>
123 meta_type_node *meta_arg_node(type_list<Args...>, const std::size_t index) ENTT_NOEXCEPT;
124 
125 template<typename Type>
126 class ENTT_API meta_node {
127  static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Invalid type");
128 
129  [[nodiscard]] static auto *meta_default_constructor() ENTT_NOEXCEPT {
130  if constexpr(std::is_default_constructible_v<Type>) {
131  return +[]() { return meta_any{std::in_place_type<Type>}; };
132  } else {
133  return static_cast<std::decay_t<decltype(meta_type_node::default_constructor)>>(nullptr);
134  }
135  }
136 
137  [[nodiscard]] static auto *meta_conversion_helper() ENTT_NOEXCEPT {
138  if constexpr(std::is_arithmetic_v<Type>) {
139  return +[](void *bin, const void *value) {
140  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));
141  };
142  } else if constexpr(std::is_enum_v<Type>) {
143  return +[](void *bin, const void *value) {
144  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));
145  };
146  } else {
147  return static_cast<std::decay_t<decltype(meta_type_node::conversion_helper)>>(nullptr);
148  }
149  }
150 
151  [[nodiscard]] static meta_template_node *meta_template_info() ENTT_NOEXCEPT {
152  if constexpr(is_complete_v<meta_template_traits<Type>>) {
153  static meta_template_node node{
154  meta_template_traits<Type>::args_type::size,
155  meta_node<typename meta_template_traits<Type>::class_type>::resolve(),
156  [](const std::size_t index) ENTT_NOEXCEPT { return meta_arg_node(typename meta_template_traits<Type>::args_type{}, index); }
157  // tricks clang-format
158  };
159 
160  return &node;
161  } else {
162  return nullptr;
163  }
164  }
165 
166 public:
167  [[nodiscard]] static meta_type_node *resolve() ENTT_NOEXCEPT {
168  static meta_type_node node{
169  &type_id<Type>(),
170  {},
171  internal::meta_traits::is_none
172  | (std::is_arithmetic_v<Type> ? internal::meta_traits::is_arithmetic : internal::meta_traits::is_none)
173  | (std::is_array_v<Type> ? internal::meta_traits::is_array : internal::meta_traits::is_none)
174  | (std::is_enum_v<Type> ? internal::meta_traits::is_enum : internal::meta_traits::is_none)
175  | (std::is_class_v<Type> ? internal::meta_traits::is_class : internal::meta_traits::is_none)
176  | (std::is_pointer_v<Type> ? internal::meta_traits::is_pointer : internal::meta_traits::is_none)
177  | (is_meta_pointer_like_v<Type> ? internal::meta_traits::is_meta_pointer_like : internal::meta_traits::is_none)
178  | (is_complete_v<meta_sequence_container_traits<Type>> ? internal::meta_traits::is_meta_sequence_container : internal::meta_traits::is_none)
179  | (is_complete_v<meta_associative_container_traits<Type>> ? internal::meta_traits::is_meta_associative_container : internal::meta_traits::is_none),
180  nullptr,
181  nullptr,
182  size_of_v<Type>,
183  meta_default_constructor(),
184  meta_conversion_helper(),
185  meta_template_info()
186  // tricks clang-format
187  };
188 
189  return &node;
190  }
191 };
192 
193 template<typename... Args>
194 [[nodiscard]] meta_type_node *meta_arg_node(type_list<Args...>, const std::size_t index) ENTT_NOEXCEPT {
195  meta_type_node *args[sizeof...(Args) + 1u]{nullptr, internal::meta_node<std::remove_cv_t<std::remove_reference_t<Args>>>::resolve()...};
196  return args[index + 1u];
197 }
198 
199 template<auto Member, typename Type>
200 [[nodiscard]] static std::decay_t<decltype(std::declval<internal::meta_type_node>().*Member)> find_by(const Type &info_or_id, const internal::meta_type_node *node) ENTT_NOEXCEPT {
201  for(auto *curr = node->*Member; curr; curr = curr->next) {
202  if constexpr(std::is_same_v<Type, type_info>) {
203  if(*curr->type->info == info_or_id) {
204  return curr;
205  }
206  } else if constexpr(std::is_same_v<decltype(curr), meta_base_node *>) {
207  if(curr->type->id == info_or_id) {
208  return curr;
209  }
210  } else {
211  if(curr->id == info_or_id) {
212  return curr;
213  }
214  }
215  }
216 
217  for(auto *curr = node->base; curr; curr = curr->next) {
218  if(auto *ret = find_by<Member>(info_or_id, curr->type); ret) {
219  return ret;
220  }
221  }
222 
223  return nullptr;
224 }
225 
226 } // namespace internal
227 
233 } // namespace entt
234 
235 #endif
EnTT default namespace.
Definition: dense_map.hpp:22
meta_type resolve()
Returns the meta type associated with a given type.
Definition: resolve.hpp:19
std::uint32_t id_type
Alias declaration for type identifiers.
Definition: fwd.hpp:14
constexpr bool is_complete_v
Helper variable template.
constexpr get_t< Type... > get
Variable template for lists of observed components.
Definition: utility.hpp:34
void invoke(basic_registry< Entity > &reg, const Entity entt)
Helper to create a listener that directly invokes a member function.
Definition: helper.hpp:119