node.hpp 7.7 KB

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