Skip to content

Commit

Permalink
meta: support creating multiple types with different factories
Browse files Browse the repository at this point in the history
  • Loading branch information
skypjack committed Jul 26, 2024
1 parent 13284b7 commit 8b0ef2b
Showing 1 changed file with 55 additions and 35 deletions.
90 changes: 55 additions & 35 deletions src/entt/meta/factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,57 +28,62 @@ namespace entt {
namespace internal {

class basic_meta_factory {
using invoke_type = std::remove_pointer_t<decltype(meta_func_node::invoke)>;

auto *find_overload() {
auto *curr = &details->func[bucket];

while(curr->invoke != invoke) {
curr = curr->next.get();
}

return curr;
}

protected:
void type(const id_type id) noexcept {
auto &&elem = meta_context::from(*ctx).value[parent];
ENTT_ASSERT(elem.id == id || !resolve(*ctx, id), "Duplicate identifier");
bucket = &elem.details->prop;
user = &elem.custom;
mask = &elem.traits;
invoke = nullptr;
bucket = parent;
elem.id = id;
}

void base(const id_type id, meta_base_node node) {
details->base.insert_or_assign(id, node);
bucket = nullptr;
user = nullptr;
mask = nullptr;
invoke = nullptr;
bucket = parent;
}

void conv(const id_type id, meta_conv_node node) {
details->conv.insert_or_assign(id, node);
bucket = nullptr;
user = nullptr;
mask = nullptr;
invoke = nullptr;
bucket = parent;
}

void ctor(const id_type id, meta_ctor_node node) {
details->ctor.insert_or_assign(id, node);
bucket = nullptr;
user = nullptr;
mask = nullptr;
invoke = nullptr;
bucket = parent;
}

void dtor(meta_dtor_node node) {
meta_context::from(*ctx).value[parent].dtor = node;
bucket = nullptr;
user = nullptr;
mask = nullptr;
invoke = nullptr;
bucket = parent;
}

void data(const id_type id, meta_data_node node) {
auto &&it = details->data.insert_or_assign(id, std::move(node)).first;
bucket = &it->second.prop;
user = &it->second.custom;
mask = &it->second.traits;
details->data.insert_or_assign(id, std::move(node));
invoke = nullptr;
bucket = id;
}

void func(const id_type id, meta_func_node node) {
if(auto it = details->func.find(id); it == details->func.end()) {
auto &&elem = details->func.insert_or_assign(id, std::move(node)).first;
bucket = &elem->second.prop;
user = &elem->second.custom;
mask = &elem->second.traits;
invoke = elem->second.invoke;
bucket = id;
} else {
auto *curr = &it->second;

Expand All @@ -93,47 +98,62 @@ class basic_meta_factory {

node.next = std::move(curr->next);
*curr = std::move(node);
bucket = &curr->prop;
user = &curr->custom;
mask = &curr->traits;

invoke = curr->invoke;
bucket = id;
}
}

void prop(const id_type key, meta_prop_node value) {
(*bucket)[key] = std::move(value);
if(bucket == parent) {
details->prop[key] = std::move(value);
} else if(invoke == nullptr) {
details->data[bucket].prop[key] = std::move(value);
} else {
find_overload()->prop[key] = std::move(value);
}
}

void traits(const meta_traits value) {
*mask |= value;
if(bucket == parent) {
meta_context::from(*ctx).value[bucket].traits |= value;
} else if(invoke == nullptr) {
details->data[bucket].traits |= value;
} else {
find_overload()->traits |= value;
}
}

void custom(meta_custom_node node) {
*user = std::move(node);
if(bucket == parent) {
meta_context::from(*ctx).value[bucket].custom = std::move(node);
} else if(invoke == nullptr) {
details->data[bucket].custom = std::move(node);
} else {
find_overload()->custom = std::move(node);
}
}

public:
basic_meta_factory(const id_type id, meta_ctx &area)
: ctx{&area},
parent{id} {
parent{id},
bucket{id} {
auto &&elem = meta_context::from(*ctx).value[parent];

if(!elem.details) {
elem.details = std::make_shared<meta_type_descriptor>();
}

details = elem.details.get();
bucket = &details->prop;
user = &elem.custom;
mask = &elem.traits;
}

private:
meta_ctx *ctx{};
id_type parent{};
id_type bucket{};
invoke_type *invoke{};
meta_type_descriptor *details{};
dense_map<id_type, meta_prop_node, identity> *bucket{};
meta_custom_node *user{};
meta_traits *mask;
};

} // namespace internal
Expand Down

0 comments on commit 8b0ef2b

Please sign in to comment.