From f9b456a99fcdbd7ab71565eb05195c7d05296177 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Mon, 25 May 2026 17:26:08 +0100 Subject: [PATCH] fx.reflection: implement assembly registration and lookup --- fx.reflection/assembly.c | 380 ++++++++++++++++-- .../include/fx/reflection/assembly.h | 22 +- 2 files changed, 369 insertions(+), 33 deletions(-) diff --git a/fx.reflection/assembly.c b/fx.reflection/assembly.c index bd2c3e5..5b353b2 100644 --- a/fx.reflection/assembly.c +++ b/fx.reflection/assembly.c @@ -1,8 +1,24 @@ +#include "fx/namemap.h" + #include #include +#include #include #include #include +#include + +FX_API fx_type_id fx_assembly_iterator_get_type(); +FX_API fx_type_id fx_assembly_type_iterator_get_type(); + +FX_DECLARE_TYPE(fx_assembly_iterator); +FX_DECLARE_TYPE(fx_assembly_type_iterator); + +FX_TYPE_CLASS_DECLARATION_BEGIN(fx_assembly_iterator) +FX_TYPE_CLASS_DECLARATION_END(fx_assembly_iterator) + +FX_TYPE_CLASS_DECLARATION_BEGIN(fx_assembly_type_iterator) +FX_TYPE_CLASS_DECLARATION_END(fx_assembly_type_iterator) enum map_entry_type { MAP_ENTRY_NONE = 0, @@ -12,6 +28,7 @@ enum map_entry_type { struct map_entry { enum map_entry_type e_type; + struct map_bucket *e_bucket; uint64_t e_hash; union { fx_queue_entry e_entry; @@ -39,8 +56,10 @@ struct type { }; struct fx_assembly_p { + fx_assembly *a_self; const char *a_name; struct map a_types; + fx_namemap_entry a_entry; struct { long v_major; @@ -50,6 +69,14 @@ struct fx_assembly_p { } a_version; }; +struct fx_assembly_iterator_p { + fx_namemap_entry *it_cur; +}; + +struct fx_assembly_type_iterator_p { + struct type *it_item; +}; + /*** PRIVATE FUNCTIONS ********************************************************/ FX_BST_DEFINE_SIMPLE_GET( @@ -60,6 +87,8 @@ FX_BST_DEFINE_SIMPLE_GET( map_get_entry); FX_BST_DEFINE_SIMPLE_INSERT(struct map_entry, e_node, e_hash, map_put_entry); +static fx_namemap assembly_map = FX_NAMEMAP_INIT; + static struct map_bucket *map_item_convert_to_bucket( struct map *map, struct map_item *item) @@ -78,6 +107,28 @@ static struct map_bucket *map_item_convert_to_bucket( return bucket; } +static struct map_item *map_first_item(const struct map *map) +{ + fx_bst_node *first = fx_bst_first(&map->m_entries); + if (!first) { + return NULL; + } + + struct map_entry *entry = fx_unbox(struct map_entry, first, e_node); + if (entry->e_type == MAP_ENTRY_ITEM) { + return (struct map_item *)entry; + } + + struct map_bucket *bucket = (struct map_bucket *)entry; + fx_queue_entry *first_entry = fx_queue_first(&bucket->b_items); + if (!first_entry) { + return NULL; + } + + entry = fx_unbox(struct map_entry, first_entry, e_entry); + return (struct map_item *)entry; +} + static void map_put(struct map *map, const char *name, struct map_item *item) { uint64_t hash = fx_hash_cstr(name); @@ -109,34 +160,81 @@ static void map_put(struct map *map, const char *name, struct map_item *item) } } -static void assembly_set_name(struct fx_assembly_p *asm, const char *name) +static struct map_item *map_item_next(struct map_item *item) { - asm->a_name = name; + struct map_bucket *bucket = item->i_entry.e_bucket; + struct map_entry *next_item = NULL; + if (bucket) { + struct fx_queue_entry *q_item = fx_queue_next( + &item->i_entry.e_entry); + if (!q_item) { + struct fx_bst_node *node = fx_bst_next( + &bucket->b_entry.e_node); + next_item = fx_unbox(struct map_entry, node, e_node); + } else { + next_item = fx_unbox(struct map_entry, q_item, e_entry); + } + } else { + struct fx_bst_node *node = fx_bst_next(&item->i_entry.e_node); + next_item = fx_unbox(struct map_entry, node, e_node); + } + + if (!next_item) { + return NULL; + } + + if (next_item->e_type == MAP_ENTRY_BUCKET) { + bucket = (struct map_bucket *)next_item; + struct fx_queue_entry *q_item = fx_queue_first( + &bucket->b_items); + next_item = fx_unbox(struct map_entry, q_item, e_entry); + } + + return (struct map_item *)next_item; +} + +static fx_status assembly_register(struct fx_assembly_p *assembly) +{ + if (fx_namemap_get(&assembly_map, assembly->a_name)) { + return FX_ERR_NAME_EXISTS; + } + + fx_namemap_put(&assembly_map, assembly->a_name, &assembly->a_entry); + return FX_SUCCESS; +} + +static void assembly_set_name(struct fx_assembly_p *assembly, const char *name) +{ + assembly->a_name = name; } static void assembly_set_version( - struct fx_assembly_p *asm, + struct fx_assembly_p *assembly, long major, long minor, long build, long revision) { - asm->a_version.v_major = major; - asm->a_version.v_minor = minor; - asm->a_version.v_build = build; - asm->a_version.v_revision = revision; + assembly->a_version.v_major = major; + assembly->a_version.v_minor = minor; + assembly->a_version.v_build = build; + assembly->a_version.v_revision = revision; } #include static void assembly_add_type( - struct fx_assembly_p *asm, + struct fx_assembly_p *assembly, const char *full_name, fx_type_id type_id) { struct type *type = malloc(sizeof *type); memset(type, 0x0, sizeof *type); - map_put(&asm->a_types, full_name, &type->e_map_item); + type->e_type = type_id; + fx_type *ty = (fx_type *)fx_type_get_by_id(type_id); + fx_type_set_assembly(ty, assembly->a_self); + + map_put(&assembly->a_types, full_name, &type->e_map_item); } static void map_item_dump(struct map_item *item) @@ -145,20 +243,22 @@ static void map_item_dump(struct map_item *item) printf(" Type: %s\n", type->e_map_item.i_name); } -static void assembly_dump(struct fx_assembly_p *asm) +static void assembly_dump(struct fx_assembly_p *assembly) { printf("Loaded assembly:\n"); printf(" %s, Version=%ld.%ld.%ld.%ld\n", - asm->a_name, - asm->a_version.v_major, - asm->a_version.v_minor, - asm->a_version.v_build, - asm->a_version.v_revision); + assembly->a_name, + assembly->a_version.v_major, + assembly->a_version.v_minor, + assembly->a_version.v_build, + assembly->a_version.v_revision); - fx_bst_node *cur_node = fx_bst_first(&asm->a_types.m_entries); + fx_bst_node *cur_node = fx_bst_first(&assembly->a_types.m_entries); while (cur_node) { - struct map_entry *entry - = fx_unbox(struct map_entry, cur_node, e_node); + struct map_entry *entry = fx_unbox( + struct map_entry, + cur_node, + e_node); switch (entry->e_type) { case MAP_ENTRY_ITEM: { struct map_item *item = (struct map_item *)entry; @@ -168,8 +268,8 @@ static void assembly_dump(struct fx_assembly_p *asm) case MAP_ENTRY_BUCKET: { struct map_bucket *bucket = (struct map_bucket *)entry; - fx_queue_entry *cur_qentry - = fx_queue_first(&bucket->b_items); + fx_queue_entry *cur_qentry = fx_queue_first( + &bucket->b_items); while (cur_qentry) { struct map_item *item = fx_unbox( struct map_item, @@ -187,19 +287,110 @@ static void assembly_dump(struct fx_assembly_p *asm) } } +static fx_iterator *assembly_get_types(const struct fx_assembly_p *assembly) +{ + fx_assembly_type_iterator *it = fx_object_create( + fx_assembly_type_iterator_get_type()); + if (!it) { + return NULL; + } + + struct fx_assembly_type_iterator_p *it_p = fx_object_get_private( + it, + fx_assembly_type_iterator_get_type()); + struct map_item *item = map_first_item(&assembly->a_types); + if (item) { + it_p->it_item = fx_unbox(struct type, item, e_map_item); + } else { + fx_iterator_set_status(it, FX_ERR_NO_DATA); + } + + return it; +} + +static const char *assembly_get_name(const struct fx_assembly_p *assembly) +{ + return assembly->a_name; +} + +static void assembly_get_version( + const struct fx_assembly_p *assembly, + long *out_major, + long *out_minor, + long *out_build, + long *out_revision) +{ + if (out_major) { + *out_major = assembly->a_version.v_major; + } + + if (out_minor) { + *out_minor = assembly->a_version.v_minor; + } + + if (out_build) { + *out_build = assembly->a_version.v_build; + } + + if (out_revision) { + *out_revision = assembly->a_version.v_revision; + } +} + /*** PUBLIC FUNCTIONS *********************************************************/ -void fx_assembly_set_name(fx_assembly *asm, const char *name) +fx_iterator *fx_assembly_get_all(void) +{ + fx_assembly_iterator *it = fx_object_create( + fx_assembly_iterator_get_type()); + if (!it) { + return NULL; + } + + struct fx_assembly_iterator_p *it_p = fx_object_get_private( + it, + fx_assembly_iterator_get_type()); + it_p->it_cur = fx_namemap_first(&assembly_map); + if (!it_p->it_cur) { + fx_iterator_set_status(it, FX_ERR_NO_DATA); + } + + return it; +} + +const fx_assembly *fx_assembly_get_by_name(const char *name) +{ + const fx_namemap_entry *entry = fx_namemap_get(&assembly_map, name); + if (!entry) { + return NULL; + } + + struct fx_assembly_p *assembly = fx_unbox( + struct fx_assembly_p, + entry, + a_entry); + return assembly->a_self; +} + +fx_status fx_assembly_register(fx_assembly *assembly) +{ + FX_CLASS_DISPATCH_STATIC_0( + FX_REFLECTION_TYPE_ASSEMBLY, + assembly_register, + assembly); +} + +void fx_assembly_set_name(fx_assembly *assembly, const char *name) { FX_CLASS_DISPATCH_STATIC_V( FX_REFLECTION_TYPE_ASSEMBLY, assembly_set_name, - asm, + assembly, name); } void fx_assembly_set_version( - fx_assembly *asm, + fx_assembly *assembly, long major, long minor, long build, @@ -208,7 +399,7 @@ void fx_assembly_set_version( FX_CLASS_DISPATCH_STATIC_V( FX_REFLECTION_TYPE_ASSEMBLY, assembly_set_version, - asm, + assembly, major, minor, build, @@ -216,39 +407,131 @@ void fx_assembly_set_version( } void fx_assembly_add_type( - fx_assembly *asm, + fx_assembly *assembly, const char *full_name, fx_type_id type_id) { FX_CLASS_DISPATCH_STATIC_V( FX_REFLECTION_TYPE_ASSEMBLY, assembly_add_type, - asm, + assembly, full_name, type_id); } -void fx_assembly_dump(const fx_assembly *asm) +fx_iterator *fx_assembly_get_types(const fx_assembly *assembly) +{ + FX_CLASS_DISPATCH_STATIC_0( + FX_REFLECTION_TYPE_ASSEMBLY, + assembly_get_types, + assembly); +} + +const char *fx_assembly_get_name(const fx_assembly *assembly) +{ + FX_CLASS_DISPATCH_STATIC_0( + FX_REFLECTION_TYPE_ASSEMBLY, + assembly_get_name, + assembly); +} + +void fx_assembly_get_version( + const fx_assembly *assembly, + long *out_major, + long *out_minor, + long *out_build, + long *out_revision) +{ + FX_CLASS_DISPATCH_STATIC_V( + FX_REFLECTION_TYPE_ASSEMBLY, + assembly_get_version, + assembly, + out_major, + out_minor, + out_build, + out_revision); +} + +void fx_assembly_dump(const fx_assembly *assembly) { FX_CLASS_DISPATCH_STATIC_0( FX_REFLECTION_TYPE_ASSEMBLY, assembly_dump, - asm); + assembly); } /*** VIRTUAL FUNCTIONS ********************************************************/ static void assembly_init(fx_object *obj, void *priv) { + struct fx_assembly_p *assembly = priv; + assembly->a_self = obj; } static void assembly_fini(fx_object *obj, void *priv) { } +/*** ITERATOR DEFINITION ******************************************************/ + +static enum fx_status type_iterator_move_next(const fx_iterator *obj) +{ + struct fx_assembly_type_iterator_p *it = fx_object_get_private( + obj, + fx_assembly_type_iterator_get_type()); + if (!it->it_item) { + return FX_ERR_NO_DATA; + } + + struct map_item *next = map_item_next(&it->it_item->e_map_item); + it->it_item = fx_unbox(struct type, next, e_map_item); + return it->it_item ? FX_SUCCESS : FX_ERR_NO_DATA; +} + +static fx_value type_iterator_get_value(const fx_iterator *obj) +{ + struct fx_assembly_type_iterator_p *it = fx_object_get_private( + obj, + fx_assembly_type_iterator_get_type()); + if (!it->it_item) { + return FX_VALUE_EMPTY; + } + + const fx_type *ty = fx_type_get_by_id(it->it_item->e_type); + return FX_VALUE_OBJECT(ty); +} + +static enum fx_status assembly_iterator_move_next(const fx_iterator *obj) +{ + struct fx_assembly_iterator_p *it = fx_object_get_private( + obj, + fx_assembly_iterator_get_type()); + if (!it->it_cur) { + return FX_ERR_NO_DATA; + } + + it->it_cur = fx_namemap_next(&assembly_map, it->it_cur); + return it->it_cur ? FX_SUCCESS : FX_ERR_NO_DATA; +} + +static fx_value assembly_iterator_get_value(const fx_iterator *obj) +{ + struct fx_assembly_iterator_p *it = fx_object_get_private( + obj, + fx_assembly_iterator_get_type()); + if (!it->it_cur) { + return FX_VALUE_EMPTY; + } + + struct fx_assembly_p *assembly = fx_unbox( + struct fx_assembly_p, + it->it_cur, + a_entry); + return FX_VALUE_OBJECT(assembly->a_self); +} + /*** CLASS DEFINITION *********************************************************/ -// ---- fx_string DEFINITION FX_TYPE_CLASS_BEGIN(fx_assembly) FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT) FX_INTERFACE_ENTRY(to_string) = NULL; @@ -257,8 +540,47 @@ FX_TYPE_CLASS_END(fx_assembly) FX_TYPE_DEFINITION_BEGIN(fx_assembly) FX_TYPE_ID(0xf6690c30, 0x6642, 0x42f0, 0xb79f, 0xe2baf3684b1b); + FX_TYPE_NAME("fx.reflection.assembly"); FX_TYPE_CLASS(fx_assembly_class); FX_TYPE_INSTANCE_PRIVATE(struct fx_assembly_p); FX_TYPE_INSTANCE_INIT(assembly_init); FX_TYPE_INSTANCE_FINI(assembly_fini); FX_TYPE_DEFINITION_END(fx_assembly) + +FX_TYPE_CLASS_BEGIN(fx_assembly_type_iterator) + FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT) + FX_INTERFACE_ENTRY(to_string) = NULL; + FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT) + + FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_iterator, FX_TYPE_ITERATOR) + FX_INTERFACE_ENTRY(it_move_next) = type_iterator_move_next; + FX_INTERFACE_ENTRY(it_get_value) = type_iterator_get_value; + FX_TYPE_VTABLE_INTERFACE_END(fx_iterator, FX_TYPE_ITERATOR) +FX_TYPE_CLASS_END(fx_assembly_type_iterator) + +FX_TYPE_DEFINITION_BEGIN(fx_assembly_type_iterator) + FX_TYPE_ID(0x74ecb8df, 0x155d, 0x4e45, 0x96a6, 0x0f71e3ea0a1e); + FX_TYPE_NAME("fx.reflection.assembly.type_iterator"); + FX_TYPE_EXTENDS(FX_TYPE_ITERATOR); + FX_TYPE_CLASS(fx_assembly_type_iterator_class); + FX_TYPE_INSTANCE_PRIVATE(struct fx_assembly_type_iterator_p); +FX_TYPE_DEFINITION_END(fx_assembly_type_iterator) + +FX_TYPE_CLASS_BEGIN(fx_assembly_iterator) + FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT) + FX_INTERFACE_ENTRY(to_string) = NULL; + FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT) + + FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_iterator, FX_TYPE_ITERATOR) + FX_INTERFACE_ENTRY(it_move_next) = assembly_iterator_move_next; + FX_INTERFACE_ENTRY(it_get_value) = assembly_iterator_get_value; + FX_TYPE_VTABLE_INTERFACE_END(fx_iterator, FX_TYPE_ITERATOR) +FX_TYPE_CLASS_END(fx_assembly_iterator) + +FX_TYPE_DEFINITION_BEGIN(fx_assembly_iterator) + FX_TYPE_ID(0x391f8d65, 0x9baf, 0x4941, 0xbdbe, 0xe739226f8947); + FX_TYPE_NAME("fx.reflection.assembly.iterator"); + FX_TYPE_EXTENDS(FX_TYPE_ITERATOR); + FX_TYPE_CLASS(fx_assembly_iterator_class); + FX_TYPE_INSTANCE_PRIVATE(struct fx_assembly_iterator_p); +FX_TYPE_DEFINITION_END(fx_assembly_iterator) diff --git a/fx.reflection/include/fx/reflection/assembly.h b/fx.reflection/include/fx/reflection/assembly.h index 9f3522f..04e5fe5 100644 --- a/fx.reflection/include/fx/reflection/assembly.h +++ b/fx.reflection/include/fx/reflection/assembly.h @@ -1,6 +1,7 @@ #ifndef FX_REFLECTION_ASSEMBLY_H_ #define FX_REFLECTION_ASSEMBLY_H_ +#include #include FX_DECLS_BEGIN; @@ -16,20 +17,33 @@ FX_API fx_type_id fx_assembly_get_type(); FX_TYPE_DEFAULT_CONSTRUCTOR(fx_assembly, FX_REFLECTION_TYPE_ASSEMBLY); -FX_API void fx_assembly_set_name(fx_assembly *asm, const char *name); +FX_API fx_iterator *fx_assembly_get_all(void); +FX_API const fx_assembly *fx_assembly_get_by_name(const char *name); + +FX_API fx_status fx_assembly_register(fx_assembly *assembly); +FX_API void fx_assembly_set_name(fx_assembly *assembly, const char *name); FX_API void fx_assembly_set_version( - fx_assembly *asm, + fx_assembly *assembly, long major, long minor, long build, long revision); FX_API void fx_assembly_add_type( - fx_assembly *asm, + fx_assembly *assembly, const char *full_name, fx_type_id type_id); +FX_API fx_iterator *fx_assembly_get_types(const fx_assembly *assembly); -FX_API void fx_assembly_dump(const fx_assembly *asm); +FX_API const char *fx_assembly_get_name(const fx_assembly *assembly); +FX_API void fx_assembly_get_version( + const fx_assembly *assembly, + long *out_major, + long *out_minor, + long *out_build, + long *out_revision); + +FX_API void fx_assembly_dump(const fx_assembly *assembly); FX_DECLS_END;