meta: cleanup, prep for hook point
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user