meta: cleanup, prep for hook point

This commit is contained in:
Michele Caini
2021-07-23 16:20:51 +02:00
parent 33ccb71526
commit 8566c58f2b

View File

@@ -2,6 +2,7 @@
#define ENTT_META_FACTORY_HPP
#include <algorithm>
#include <cstddef>
#include <tuple>
#include <type_traits>
@@ -13,70 +14,13 @@
#include "meta.hpp"
#include "node.hpp"
#include "policy.hpp"
#include "range.hpp"
#include "utility.hpp"
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
template<typename Node>
[[nodiscard]] bool find_if(const Node *candidate, const Node *node) ENTT_NOEXCEPT {
return node && (node == candidate || find_if(candidate, node->next));
}
template<typename Id, typename Node>
[[nodiscard]] bool find_if_not(const Id id, Node *node, const Node *owner) ENTT_NOEXCEPT {
if constexpr(std::is_pointer_v<Id>) {
return node && ((*node->id == *id && node != owner) || find_if_not(id, node->next, owner));
} else {
return node && ((node->id == id && node != owner) || find_if_not(id, node->next, owner));
}
}
template<auto... Member, typename Node>
void meta_reset(Node **curr) {
while(*curr) {
(meta_reset(&((*curr)->*Member)), ...);
*curr = std::exchange((*curr)->next, nullptr);
}
}
inline void meta_reset(internal::meta_type_node *node) ENTT_NOEXCEPT {
meta_reset(&node->prop);
meta_reset(&node->base);
meta_reset(&node->conv);
meta_reset<&internal::meta_ctor_node::prop>(&node->ctor);
meta_reset<&internal::meta_data_node::prop>(&node->data);
meta_reset<&internal::meta_func_node::prop>(&node->func);
node->id = {};
node->ctor = node->def_ctor;
node->dtor = nullptr;
node->next = nullptr;
}
}
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief Meta factory to be used for reflection purposes.
*
@@ -139,11 +83,11 @@ private:
};
entt::meta_any instance{std::forward<Key>(key)};
ENTT_ASSERT(!internal::find_if_not(&instance, *curr, &node), "Duplicate key");
property[0u] = std::move(instance);
property[1u] = std::move(value);
if(!internal::find_if(&node, *curr)) {
if(meta_range<internal::meta_prop_node *, internal::meta_prop_node> range{*curr}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [&instance](const auto *curr) { return curr->id == instance; }) == range.cend(), "Duplicate identifier");
node.next = *curr;
*curr = &node;
}
@@ -215,10 +159,10 @@ struct meta_factory<Type> {
auto type(const id_type id = type_hash<Type>::value()) {
auto * const node = internal::meta_info<Type>::resolve();
ENTT_ASSERT(!internal::find_if_not(id, *internal::meta_context::global(), node), "Duplicate identifier");
node->id = id;
if(!internal::find_if(node, *internal::meta_context::global())) {
if(meta_range<internal::meta_type_node *, internal::meta_type_node> range{*internal::meta_context::global()}; std::find(range.cbegin(), range.cend(), node) == range.cend()) {
ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id](const auto *curr) { return curr->id == id; }) == range.cend(), "Duplicate identifier");
node->next = *internal::meta_context::global();
*internal::meta_context::global() = node;
}
@@ -247,7 +191,7 @@ struct meta_factory<Type> {
}
};
if(!internal::find_if(&node, type->base)) {
if(meta_range<internal::meta_base_node *, internal::meta_base_node> range{type->base}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = type->base;
type->base = &node;
}
@@ -280,7 +224,7 @@ struct meta_factory<Type> {
}
};
if(!internal::find_if(&node, type->conv)) {
if(meta_range<internal::meta_conv_node *, internal::meta_conv_node> range{type->conv}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = type->conv;
type->conv = &node;
}
@@ -302,7 +246,7 @@ struct meta_factory<Type> {
}
};
if(!internal::find_if(&node, type->conv)) {
if(meta_range<internal::meta_conv_node *, internal::meta_conv_node> range{type->conv}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = type->conv;
type->conv = &node;
}
@@ -332,7 +276,7 @@ struct meta_factory<Type> {
}
};
if(!internal::find_if(&node, type->conv)) {
if(meta_range<internal::meta_conv_node *, internal::meta_conv_node> range{type->conv}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = type->conv;
type->conv = &node;
}
@@ -367,7 +311,7 @@ struct meta_factory<Type> {
&meta_construct<Type, Candidate, Policy>
};
if(!internal::find_if(&node, type->ctor)) {
if(meta_range<internal::meta_ctor_node *, internal::meta_ctor_node> range{type->ctor}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = type->ctor;
type->ctor = &node;
}
@@ -398,7 +342,7 @@ struct meta_factory<Type> {
&meta_construct<Type, Args...>
};
if(!internal::find_if(&node, type->ctor)) {
if(meta_range<internal::meta_ctor_node *, internal::meta_ctor_node> range{type->ctor}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = type->ctor;
type->ctor = &node;
}
@@ -466,10 +410,10 @@ struct meta_factory<Type> {
&meta_getter<Type, Data, Policy>
};
ENTT_ASSERT(!internal::find_if_not(id, type->data, &node), "Duplicate identifier");
node.id = id;
if(!internal::find_if(&node, type->data)) {
if(meta_range<internal::meta_data_node *, internal::meta_data_node> range{type->data}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id](const auto *curr) { return curr->id == id; }) == range.cend(), "Duplicate identifier");
node.next = type->data;
type->data = &node;
}
@@ -514,10 +458,10 @@ struct meta_factory<Type> {
&meta_getter<Type, Getter, Policy>
};
ENTT_ASSERT(!internal::find_if_not(id, type->data, &node), "Duplicate identifier");
node.id = id;
if(!internal::find_if(&node, type->data)) {
if(meta_range<internal::meta_data_node *, internal::meta_data_node> range{type->data}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id](const auto *curr) { return curr->id == id; }) == range.cend(), "Duplicate identifier");
node.next = type->data;
type->data = &node;
}
@@ -617,28 +561,43 @@ void meta_reset() ENTT_NOEXCEPT {
* @param id Unique identifier.
*/
inline void meta_reset(const id_type id) ENTT_NOEXCEPT {
auto clear_chain = [](auto **curr, auto... member) {
for(; *curr; *curr = std::exchange((*curr)->next, nullptr)) {
if constexpr(sizeof...(member) != 0u) {
static_assert(sizeof...(member) == 1u, "Assert in defense of the future me");
for(auto **it = (&((*curr)->*member), ...); *it; *it = std::exchange((*it)->next, nullptr));
}
}
};
for(auto** it = internal::meta_context::global(); *it; it = &(*it)->next) {
if((*it)->id == id) {
internal::meta_type_node *node = *it;
*it = (*it)->next;
internal::meta_reset(node);
if(auto *node = *it; node->id == id) {
clear_chain(&node->prop);
clear_chain(&node->base);
clear_chain(&node->conv);
clear_chain(&node->ctor, &internal::meta_ctor_node::prop);
clear_chain(&node->data, &internal::meta_data_node::prop);
clear_chain(&node->func, &internal::meta_func_node::prop);
node->id = {};
node->ctor = node->def_ctor;
node->dtor = nullptr;
*it = std::exchange(node->next, nullptr);
break;
}
}
}
/**
* @brief Resets all searchable types.
*
* @sa meta_reset
*/
inline void meta_reset() ENTT_NOEXCEPT {
for(auto** it = internal::meta_context::global(); *it; it = &(*it)->next) {
internal::meta_reset(*it);
while(*internal::meta_context::global()) {
meta_reset((*internal::meta_context::global())->id);
}
*internal::meta_context::global() = nullptr;
}