Browse Source

meta: internal review to fully support re-registration

Michele Caini 5 years ago
parent
commit
03c7dac92f
4 changed files with 92 additions and 64 deletions
  1. 80 52
      src/entt/meta/factory.hpp
  2. 8 8
      src/entt/meta/meta.hpp
  3. 2 2
      src/entt/meta/node.hpp
  4. 2 2
      test/entt/meta/meta_type.cpp

+ 80 - 52
src/entt/meta/factory.hpp

@@ -19,6 +19,40 @@
 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));
+    }
+}
+
+
+}
+
+
+/**
+ * Internal details not to be documented.
+ * @endcond
+ */
+
+
 /**
  * @brief Meta factory to be used for reflection purposes.
  *
@@ -28,7 +62,7 @@ namespace entt {
  * there are no subtle errors at runtime.
  */
 template<typename...>
-class meta_factory;
+struct meta_factory;
 
 
 /**
@@ -37,11 +71,8 @@ class meta_factory;
  * @tparam Spec Property specialization pack used to disambiguate overloads.
  */
 template<typename Type, typename... Spec>
-class meta_factory<Type, Spec...>: public meta_factory<Type> {
-    [[nodiscard]] bool exists(const meta_any &key, const internal::meta_prop_node *node) ENTT_NOEXCEPT {
-        return node && (node->key() == key || exists(key, node->next));
-    }
-
+struct meta_factory<Type, Spec...>: public meta_factory<Type> {
+private:
     template<std::size_t Step = 0, std::size_t... Index, typename... Property, typename... Other>
     void unpack(std::index_sequence<Index...>, std::tuple<Property...> property, Other &&... other) {
         unroll<Step>(choice<3>, std::move(std::get<Index>(property))..., std::forward<Other>(other)...);
@@ -75,23 +106,23 @@ class meta_factory<Type, Spec...>: public meta_factory<Type> {
 
     template<std::size_t = 0, typename Key, typename... Value>
     void assign(Key &&key, Value &&... value) {
-        static const auto property{std::make_tuple(std::forward<Key>(key), std::forward<Value>(value)...)};
+        static meta_any property[1u + sizeof...(Value)]{};
 
         static internal::meta_prop_node node{
             nullptr,
-            []() -> meta_any {
-                return meta_any{std::in_place_type<const Key &>, std::get<0>(property)};
-            },
-            []() -> meta_any {
-                if constexpr(sizeof...(Value) == 0) {
-                    return {};
-                } else {
-                    return std::get<1>(property);
-                }
-            }
+            property,
+            sizeof...(Value) ? property + 1u : nullptr
         };
 
-        if(!exists(node.key(), *curr)) {
+        entt::meta_any instance{std::forward<Key>(key)};
+        ENTT_ASSERT(!internal::find_if_not(&instance, *curr, &node));
+        property[0u] = std::move(instance);
+
+        if constexpr(sizeof...(Value) > 0) {
+            property[1u] = (std::forward<Value>(value), ...);
+        }
+
+        if(!internal::find_if(&node, *curr)) {
             node.next = *curr;
             *curr = &node;
         }
@@ -154,18 +185,7 @@ private:
  * @tparam Type Reflected type for which the factory was created.
  */
 template<typename Type>
-class meta_factory<Type> {
-    template<typename Node>
-    bool exists(const Node *candidate, const Node *node) ENTT_NOEXCEPT {
-        return node && (node == candidate || exists(candidate, node->next));
-    }
-
-    template<typename Node>
-    Node * find(const id_type id, Node *node, const Node *owner) ENTT_NOEXCEPT {
-        return (!node || (node->id == id && node != owner)) ? node : find(id, node->next, owner);
-    }
-
-public:
+struct meta_factory<Type> {
     /**
      * @brief Makes a meta type _searchable_.
      * @param id Optional unique identifier.
@@ -174,9 +194,10 @@ public:
     auto type(const id_type id = type_hash<Type>::value()) {
         auto * const node = internal::meta_info<Type>::resolve();
 
-        if(!exists(node, *internal::meta_context::global())) {
-            ENTT_ASSERT(!find(id, *internal::meta_context::global(), node));
-            node->id = id;
+        ENTT_ASSERT(!internal::find_if_not(id, *internal::meta_context::global(), node));
+        node->id = id;
+
+        if(!internal::find_if(node, *internal::meta_context::global())) {
             node->next = *internal::meta_context::global();
             *internal::meta_context::global() = node;
         }
@@ -206,7 +227,7 @@ public:
             }
         };
 
-        if(!exists(&node, type->base)) {
+        if(!internal::find_if(&node, type->base)) {
             node.next = type->base;
             type->base = &node;
         }
@@ -237,7 +258,7 @@ public:
             }
         };
 
-        if(!exists(&node, type->conv)) {
+        if(!internal::find_if(&node, type->conv)) {
             node.next = type->conv;
             type->conv = &node;
         }
@@ -271,7 +292,7 @@ public:
             }
         };
 
-        if(!exists(&node, type->conv)) {
+        if(!internal::find_if(&node, type->conv)) {
             node.next = type->conv;
             type->conv = &node;
         }
@@ -311,7 +332,7 @@ public:
             }
         };
 
-        if(!exists(&node, type->ctor)) {
+        if(!internal::find_if(&node, type->ctor)) {
             node.next = type->ctor;
             type->ctor = &node;
         }
@@ -347,7 +368,7 @@ public:
             }
         };
 
-        if(!exists(&node, type->ctor)) {
+        if(!internal::find_if(&node, type->ctor)) {
             node.next = type->ctor;
             type->ctor = &node;
         }
@@ -418,9 +439,10 @@ public:
                 &meta_getter<Type, Data, Policy>
             };
 
-            if(!exists(&node, type->data)) {
-                ENTT_ASSERT(!find(id, type->data, &node));
-                node.id = id;
+            ENTT_ASSERT(!internal::find_if_not(id, type->data, &node));
+            node.id = id;
+
+            if(!internal::find_if(&node, type->data)) {
                 node.next = type->data;
                 type->data = &node;
             }
@@ -466,9 +488,10 @@ public:
             &meta_getter<Type, Getter, Policy>
         };
 
-        if(!exists(&node, type->data)) {
-            ENTT_ASSERT(!find(id, type->data, &node));
-            node.id = id;
+        ENTT_ASSERT(!internal::find_if_not(id, type->data, &node));
+        node.id = id;
+
+        if(!internal::find_if(&node, type->data)) {
             node.next = type->data;
             type->data = &node;
         }
@@ -511,16 +534,21 @@ public:
             }
         };
 
-        if(!exists(&node, type->func)) {
-            internal::meta_func_node **it = &type->func;
-            for(; *it && (*it)->id != id; it = &(*it)->next);
-            for(; *it && (*it)->id == id && (*it)->arity < node.arity; it = &(*it)->next);
-
-            node.id = id;
-            node.next = *it;
-            *it = &node;
+        for(auto *it = &type->func; *it; it = &(*it)->next) {
+            if(*it == &node) {
+                *it = node.next;
+                break;
+            }
         }
 
+        internal::meta_func_node **it = &type->func;
+        for(; *it && (*it)->id != id; it = &(*it)->next);
+        for(; *it && (*it)->id == id && (*it)->arity < node.arity; it = &(*it)->next);
+        
+        node.id = id;
+        node.next = *it;
+        *it = &node;
+
         return meta_factory<Type, std::integral_constant<decltype(Candidate), Candidate>>{&node.prop};
     }
 };

+ 8 - 8
src/entt/meta/meta.hpp

@@ -647,19 +647,19 @@ struct meta_prop {
     {}
 
     /**
-     * @brief Returns the stored key.
+     * @brief Returns the stored key as a const reference.
      * @return A meta any containing the key stored with the property.
      */
     [[nodiscard]] meta_any key() const {
-        return node->key();
+        return node->id->as_ref();
     }
 
     /**
-     * @brief Returns the stored value.
+     * @brief Returns the stored value by copy.
      * @return A meta any containing the value stored with the property.
      */
     [[nodiscard]] meta_any value() const {
-        return node->value();
+        return node->value ? *node->value : meta_any{};
     }
 
     /**
@@ -751,7 +751,7 @@ struct meta_ctor {
      * @return The property associated with the given key, if any.
      */
     [[nodiscard]] meta_prop prop(meta_any key) const {
-        return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->key() == key; }, node);
+        return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return *curr->id == key; }, node);
     }
 
     /**
@@ -847,7 +847,7 @@ struct meta_data {
      * @return The property associated with the given key, if any.
      */
     [[nodiscard]] meta_prop prop(meta_any key) const {
-        return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->key() == key; }, node);
+        return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return *curr->id == key; }, node);
     }
 
     /**
@@ -966,7 +966,7 @@ struct meta_func {
      * @return The property associated with the given key, if any.
      */
     [[nodiscard]] meta_prop prop(meta_any key) const {
-        return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->key() == key; }, node);
+        return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return *curr->id == key; }, node);
     }
 
     /**
@@ -1474,7 +1474,7 @@ public:
      * @return The property associated with the given key, if any.
      */
     [[nodiscard]] meta_prop prop(meta_any key) const {
-        return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return curr->key() == key; }, node);
+        return internal::meta_visit<&node_type::prop>([&key](const auto *curr) { return *curr->id == key; }, node);
     }
 
     /**

+ 2 - 2
src/entt/meta/node.hpp

@@ -41,8 +41,8 @@ struct meta_type_node;
 
 struct meta_prop_node {
     meta_prop_node * next;
-    meta_any(* const key)();
-    meta_any(* const value)();
+    const meta_any * const id;
+    meta_any * const value;
 };
 
 

+ 2 - 2
test/entt/meta/meta_type.cpp

@@ -651,8 +651,8 @@ TEST_F(MetaType, ResetAndReRegistrationAfterReset) {
     entt::meta<property_t>()
         .type("property"_hs)
         .data<property_t::random>("rand"_hs)
-        .prop(property_t::value, 42)
-        .prop(property_t::random, 3);
+            .prop(property_t::value, 42)
+            .prop(property_t::random, 3);
 
     ASSERT_TRUE(entt::resolve<property_t>().data("rand"_hs).prop(property_t::value));
     ASSERT_TRUE(entt::resolve<property_t>().data("rand"_hs).prop(property_t::random));