From c00dcd31d6672e78878689b99f47f6d07d79bbff Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Tue, 9 Jun 2020 16:36:10 +0200 Subject: [PATCH] meta: small review --- src/entt/entt.hpp | 2 + src/entt/meta/ctx.hpp | 78 +++++++++++ src/entt/meta/factory.hpp | 1 + src/entt/meta/internal.hpp | 237 +++++++++++++++++++++++++++++++++ src/entt/meta/meta.hpp | 265 +------------------------------------ 5 files changed, 320 insertions(+), 263 deletions(-) create mode 100644 src/entt/meta/ctx.hpp create mode 100644 src/entt/meta/internal.hpp diff --git a/src/entt/entt.hpp b/src/entt/entt.hpp index c95e4642c..8e0eca81f 100644 --- a/src/entt/entt.hpp +++ b/src/entt/entt.hpp @@ -20,7 +20,9 @@ #include "entity/utility.hpp" #include "entity/view.hpp" #include "locator/locator.hpp" +#include "meta/ctx.hpp" #include "meta/factory.hpp" +#include "meta/internal.hpp" #include "meta/meta.hpp" #include "meta/resolve.hpp" #include "meta/policy.hpp" diff --git a/src/entt/meta/ctx.hpp b/src/entt/meta/ctx.hpp new file mode 100644 index 000000000..a7be52aee --- /dev/null +++ b/src/entt/meta/ctx.hpp @@ -0,0 +1,78 @@ +#ifndef ENTT_META_CTX_HPP +#define ENTT_META_CTX_HPP + + +#include "../core/attribute.h" +#include "../config/config.h" +#include "internal.hpp" + + +namespace entt { + + +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + + +namespace internal { + + +struct ENTT_API meta_context { + // we could use the lines below but VS2017 returns with an ICE if combined with ENTT_API despite the code being valid C++ + // inline static meta_type_node *local = nullptr; + // inline static meta_type_node **global = &local; + + [[nodiscard]] static meta_type_node * & local() ENTT_NOEXCEPT { + static meta_type_node *chain = nullptr; + return chain; + } + + [[nodiscard]] static meta_type_node ** & global() ENTT_NOEXCEPT { + static meta_type_node **chain = &local(); + return chain; + } + + static void detach(const meta_type_node *node) ENTT_NOEXCEPT { + auto **it = global(); + + while(*it && *it != node) { + it = &(*it)->next; + } + + if(*it) { + *it = (*it)->next; + } + } +}; + + +} + + +/** + * Internal details not to be documented. + * @endcond TURN_OFF_DOXYGEN + */ + + +/*! @brief Opaque container for a meta context. */ +struct meta_ctx { + /** + * @brief Binds the meta system to a given context. + * @param other A valid context to which to bind. + */ + static void bind(meta_ctx other) ENTT_NOEXCEPT { + internal::meta_context::global() = other.ctx; + } + +private: + internal::meta_type_node **ctx{&internal::meta_context::local()}; +}; + + +} + + +#endif diff --git a/src/entt/meta/factory.hpp b/src/entt/meta/factory.hpp index 67db70a96..9dab23d00 100644 --- a/src/entt/meta/factory.hpp +++ b/src/entt/meta/factory.hpp @@ -13,6 +13,7 @@ #include "../core/type_info.hpp" #include "../core/type_traits.hpp" #include "../core/utility.hpp" +#include "internal.hpp" #include "meta.hpp" #include "policy.hpp" diff --git a/src/entt/meta/internal.hpp b/src/entt/meta/internal.hpp new file mode 100644 index 000000000..f1122353a --- /dev/null +++ b/src/entt/meta/internal.hpp @@ -0,0 +1,237 @@ +#ifndef ENTT_META_INTERNAL_HPP +#define ENTT_META_INTERNAL_HPP + + +#include +#include +#include "../core/attribute.h" +#include "../config/config.h" +#include "../core/fwd.hpp" +#include "../core/type_info.hpp" +#include "../core/type_traits.hpp" + + +namespace entt { + + +class meta_any; + + +/** + * @cond TURN_OFF_DOXYGEN + * Internal details not to be documented. + */ + + +namespace internal { + + +struct meta_type_node; + + +struct meta_prop_node { + meta_prop_node * next; + meta_any(* const key)(); + meta_any(* const value)(); +}; + + +struct meta_base_node { + meta_type_node * const parent; + meta_base_node * next; + meta_type_node *(* const type)() ENTT_NOEXCEPT; + void *(* const cast)(void *) ENTT_NOEXCEPT; +}; + + +struct meta_conv_node { + meta_type_node * const parent; + meta_conv_node * next; + meta_type_node *(* const type)() ENTT_NOEXCEPT; + meta_any(* const conv)(const void *); +}; + + +struct meta_ctor_node { + using size_type = std::size_t; + meta_type_node * const parent; + meta_ctor_node * next; + meta_prop_node * prop; + const size_type size; + meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT; + meta_any(* const invoke)(meta_any * const); +}; + + +struct meta_dtor_node { + meta_type_node * const parent; + void(* const invoke)(void *); +}; + + +struct meta_data_node { + id_type id; + meta_type_node * const parent; + meta_data_node * next; + meta_prop_node * prop; + const bool is_static; + meta_type_node *(* const type)() ENTT_NOEXCEPT; + bool(* const set)(meta_any, meta_any, meta_any); + meta_any(* const get)(meta_any, meta_any); +}; + + +struct meta_func_node { + using size_type = std::size_t; + id_type id; + meta_type_node * const parent; + meta_func_node * next; + meta_prop_node * prop; + const size_type size; + const bool is_const; + const bool is_static; + meta_type_node *(* const ret)() ENTT_NOEXCEPT; + meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT; + meta_any(* const invoke)(meta_any, meta_any *); +}; + + +struct meta_type_node { + using size_type = std::size_t; + const id_type type_id; + id_type id; + meta_type_node * next; + meta_prop_node * prop; + const bool is_void; + const bool is_integral; + const bool is_floating_point; + const bool is_array; + const bool is_enum; + const bool is_union; + const bool is_class; + const bool is_pointer; + const bool is_function_pointer; + const bool is_member_object_pointer; + const bool is_member_function_pointer; + const size_type extent; + bool(* const compare)(const void *, const void *); + meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT; + meta_type_node *(* const remove_extent)() ENTT_NOEXCEPT; + meta_base_node *base{nullptr}; + meta_conv_node *conv{nullptr}; + meta_ctor_node *ctor{nullptr}; + meta_dtor_node *dtor{nullptr}; + meta_data_node *data{nullptr}; + meta_func_node *func{nullptr}; +}; + + +template +void visit(Op &op, Node *node) { + while(node) { + op(Type{node}); + node = node->next; + } +} + + +template +void visit(Op &op, const internal::meta_type_node *node) { + if(node) { + internal::visit(op, node->*Member); + auto *next = node->base; + + while(next) { + visit(op, next->type()); + next = next->next; + } + } +} + + +template +auto find_if(const Op &op, Node *node) { + while(node && !op(node)) { + node = node->next; + } + + return node; +} + + +template +auto find_if(const Op &op, const meta_type_node *node) +-> decltype(find_if(op, node->*Member)) { + decltype(find_if(op, node->*Member)) ret = nullptr; + + if(node) { + ret = find_if(op, node->*Member); + auto *next = node->base; + + while(next && !ret) { + ret = find_if(op, next->type()); + next = next->next; + } + } + + return ret; +} + + +template +struct ENTT_API meta_node { + static_assert(std::is_same_v>>, "Invalid type"); + + [[nodiscard]] static bool compare(const void *lhs, const void *rhs) { + if constexpr(!std::is_function_v && is_equality_comparable_v) { + return *static_cast(lhs) == *static_cast(rhs); + } else { + return lhs == rhs; + } + } + + [[nodiscard]] static meta_type_node * resolve() ENTT_NOEXCEPT { + static meta_type_node node{ + type_info::id(), + {}, + nullptr, + nullptr, + std::is_void_v, + std::is_integral_v, + std::is_floating_point_v, + std::is_array_v, + std::is_enum_v, + std::is_union_v, + std::is_class_v, + std::is_pointer_v, + std::is_pointer_v && std::is_function_v>, + std::is_member_object_pointer_v, + std::is_member_function_pointer_v, + std::extent_v, + &compare, // workaround for an issue with VS2017 + &meta_node>>::resolve, + &meta_node>>::resolve + }; + + return &node; + } +}; + + +template +struct meta_info: meta_node>...> {}; + + +} + + +/** + * Internal details not to be documented. + * @endcond TURN_OFF_DOXYGEN + */ + + +} + + +#endif diff --git a/src/entt/meta/meta.hpp b/src/entt/meta/meta.hpp index 3aa3ea197..cead29e2e 100644 --- a/src/entt/meta/meta.hpp +++ b/src/entt/meta/meta.hpp @@ -8,277 +8,16 @@ #include #include "../config/config.h" #include "../core/fwd.hpp" -#include "../core/type_info.hpp" -#include "../core/type_traits.hpp" +#include "ctx.hpp" +#include "internal.hpp" namespace entt { -class meta_any; class meta_type; -/** - * @cond TURN_OFF_DOXYGEN - * Internal details not to be documented. - */ - - -namespace internal { - - -struct meta_type_node; - - -struct meta_prop_node { - meta_prop_node * next; - meta_any(* const key)(); - meta_any(* const value)(); -}; - - -struct meta_base_node { - meta_type_node * const parent; - meta_base_node * next; - meta_type_node *(* const type)() ENTT_NOEXCEPT; - void *(* const cast)(void *) ENTT_NOEXCEPT; -}; - - -struct meta_conv_node { - meta_type_node * const parent; - meta_conv_node * next; - meta_type_node *(* const type)() ENTT_NOEXCEPT; - meta_any(* const conv)(const void *); -}; - - -struct meta_ctor_node { - using size_type = std::size_t; - meta_type_node * const parent; - meta_ctor_node * next; - meta_prop_node * prop; - const size_type size; - meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT; - meta_any(* const invoke)(meta_any * const); -}; - - -struct meta_dtor_node { - meta_type_node * const parent; - void(* const invoke)(void *); -}; - - -struct meta_data_node { - id_type id; - meta_type_node * const parent; - meta_data_node * next; - meta_prop_node * prop; - const bool is_static; - meta_type_node *(* const type)() ENTT_NOEXCEPT; - bool(* const set)(meta_any, meta_any, meta_any); - meta_any(* const get)(meta_any, meta_any); -}; - - -struct meta_func_node { - using size_type = std::size_t; - id_type id; - meta_type_node * const parent; - meta_func_node * next; - meta_prop_node * prop; - const size_type size; - const bool is_const; - const bool is_static; - meta_type_node *(* const ret)() ENTT_NOEXCEPT; - meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT; - meta_any(* const invoke)(meta_any, meta_any *); -}; - - -struct meta_type_node { - using size_type = std::size_t; - const id_type type_id; - id_type id; - meta_type_node * next; - meta_prop_node * prop; - const bool is_void; - const bool is_integral; - const bool is_floating_point; - const bool is_array; - const bool is_enum; - const bool is_union; - const bool is_class; - const bool is_pointer; - const bool is_function_pointer; - const bool is_member_object_pointer; - const bool is_member_function_pointer; - const size_type extent; - bool(* const compare)(const void *, const void *); - meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT; - meta_type_node *(* const remove_extent)() ENTT_NOEXCEPT; - meta_base_node *base{nullptr}; - meta_conv_node *conv{nullptr}; - meta_ctor_node *ctor{nullptr}; - meta_dtor_node *dtor{nullptr}; - meta_data_node *data{nullptr}; - meta_func_node *func{nullptr}; -}; - - -template -void visit(Op &op, Node *node) { - while(node) { - op(Type{node}); - node = node->next; - } -} - - -template -void visit(Op &op, const internal::meta_type_node *node) { - if(node) { - internal::visit(op, node->*Member); - auto *next = node->base; - - while(next) { - visit(op, next->type()); - next = next->next; - } - } -} - - -template -auto find_if(const Op &op, Node *node) { - while(node && !op(node)) { - node = node->next; - } - - return node; -} - - -template -auto find_if(const Op &op, const meta_type_node *node) --> decltype(find_if(op, node->*Member)) { - decltype(find_if(op, node->*Member)) ret = nullptr; - - if(node) { - ret = find_if(op, node->*Member); - auto *next = node->base; - - while(next && !ret) { - ret = find_if(op, next->type()); - next = next->next; - } - } - - return ret; -} - - -template -[[nodiscard]] bool compare(const void *lhs, const void *rhs) { - if constexpr(!std::is_function_v && is_equality_comparable_v) { - return *static_cast(lhs) == *static_cast(rhs); - } else { - return lhs == rhs; - } -} - - -struct ENTT_API meta_context { - // we could use the lines below but VS2017 returns with an ICE if combined with ENTT_API despite the code being valid C++ - // inline static meta_type_node *local = nullptr; - // inline static meta_type_node **global = &local; - - [[nodiscard]] static meta_type_node * & local() ENTT_NOEXCEPT { - static meta_type_node *chain = nullptr; - return chain; - } - - [[nodiscard]] static meta_type_node ** & global() ENTT_NOEXCEPT { - static meta_type_node **chain = &local(); - return chain; - } - - static void detach(const meta_type_node *node) ENTT_NOEXCEPT { - auto **it = global(); - - while(*it && *it != node) { - it = &(*it)->next; - } - - if(*it) { - *it = (*it)->next; - } - } -}; - - -template -struct ENTT_API meta_node { - static_assert(std::is_same_v>>, "Invalid type"); - - [[nodiscard]] static meta_type_node * resolve() ENTT_NOEXCEPT { - static meta_type_node node{ - type_info::id(), - {}, - nullptr, - nullptr, - std::is_void_v, - std::is_integral_v, - std::is_floating_point_v, - std::is_array_v, - std::is_enum_v, - std::is_union_v, - std::is_class_v, - std::is_pointer_v, - std::is_pointer_v && std::is_function_v>, - std::is_member_object_pointer_v, - std::is_member_function_pointer_v, - std::extent_v, - &compare, // workaround for an issue with VS2017 - &meta_node>>::resolve, - &meta_node>>::resolve - }; - - return &node; - } -}; - - -template -struct meta_info: meta_node>...> {}; - - -} - - -/** - * Internal details not to be documented. - * @endcond TURN_OFF_DOXYGEN - */ - - -/*! @brief Opaque container for a meta context. */ -struct meta_ctx { - /** - * @brief Binds the meta system to a given context. - * @param other A valid context to which to bind. - */ - static void bind(meta_ctx other) ENTT_NOEXCEPT { - internal::meta_context::global() = other.ctx; - } - -private: - internal::meta_type_node **ctx{&internal::meta_context::local()}; -}; - - /** * @brief Opaque container for values of any type. *