v4k-git-backup/engine/split/v4k_reflect.c

163 lines
5.6 KiB
C
Raw Normal View History

2023-10-11 19:01:06 +00:00
// C reflection: enums, functions, structs, members and anotations.
// - rlyeh, public domain
//
// @todo: nested structs? pointers in members?
// @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/)
2023-10-15 11:16:35 +00:00
static map(unsigned, reflect_t) reflects;
static map(unsigned, array(reflect_t)) members;
2023-10-11 19:01:06 +00:00
2023-10-16 15:15:59 +00:00
void reflect_init() {
if(!reflects) map_init_int(reflects);
2023-10-11 19:01:06 +00:00
}
2023-10-16 15:15:59 +00:00
AUTORUN {
reflect_init();
2023-10-11 19:01:06 +00:00
}
2023-10-20 17:55:43 +00:00
static
const char* symbol(const char *s) {
if( strbeg(s, "const ") ) s += 6;
if( strbeg(s, "union ") ) s += 6;
if( strbeg(s, "struct ") ) s += 7;
if(!strstr(s, " *") ) return s;
char *copy = va("%s", s);
do strswap(copy," *","*"); while( strstr(copy, " *") ); // char * -> char*
return (const char *)copy;
}
void type_inscribe(const char *TY,unsigned TYsz,const char *infos) {
2023-10-16 15:15:59 +00:00
reflect_init();
2023-10-20 17:55:43 +00:00
unsigned TYid = intern(TY = symbol(TY));
2023-10-15 11:16:35 +00:00
map_find_or_add(reflects, TYid, ((reflect_t){TYid, 0, TYsz, TY, infos}));
2023-10-11 19:01:06 +00:00
}
2023-10-20 17:55:43 +00:00
void enum_inscribe(const char *E,unsigned Eval,const char *infos) {
2023-10-16 15:15:59 +00:00
reflect_init();
2023-10-20 17:55:43 +00:00
unsigned Eid = intern(E = symbol(E));
2023-10-15 11:16:35 +00:00
map_find_or_add(reflects, Eid, ((reflect_t){Eid,0, Eval, E,infos}));
2023-10-11 19:01:06 +00:00
}
unsigned enum_find(const char *E) {
2023-10-16 15:15:59 +00:00
reflect_init();
2023-10-20 17:55:43 +00:00
E = symbol(E);
2023-10-11 19:01:06 +00:00
return map_find(reflects, intern(E))->sz;
}
2023-10-20 17:55:43 +00:00
void function_inscribe(const char *F,void *func,const char *infos) {
2023-10-16 15:15:59 +00:00
reflect_init();
2023-10-20 17:55:43 +00:00
unsigned Fid = intern(F = symbol(F));
2023-10-15 11:16:35 +00:00
map_find_or_add(reflects, Fid, ((reflect_t){Fid,0, 0, F,infos, func}));
reflect_t *found = map_find(reflects,Fid);
2023-10-11 19:01:06 +00:00
}
void *function_find(const char *F) {
2023-10-16 15:15:59 +00:00
reflect_init();
2023-10-20 17:55:43 +00:00
F = symbol(F);
2023-10-11 19:01:06 +00:00
return map_find(reflects, intern(F))->addr;
}
2023-10-20 17:55:43 +00:00
void struct_inscribe(const char *T,unsigned Tsz,unsigned OBJTYPEid, const char *infos) {
2023-10-16 15:15:59 +00:00
reflect_init();
2023-10-20 17:55:43 +00:00
unsigned Tid = intern(T = symbol(T));
2023-10-15 11:16:35 +00:00
map_find_or_add(reflects, Tid, ((reflect_t){Tid, OBJTYPEid, Tsz, T, infos}));
2023-10-11 19:01:06 +00:00
}
2023-10-20 17:55:43 +00:00
void member_inscribe(const char *T, const char *M,unsigned Msz, const char *infos, const char *type, unsigned bytes) {
2023-10-16 15:15:59 +00:00
reflect_init();
2023-10-20 17:55:43 +00:00
unsigned Tid = intern(T = symbol(T));
unsigned Mid = intern(M = symbol(M));
type = symbol(type);
2023-10-15 11:16:35 +00:00
map_find_or_add(reflects, (Mid<<16)|Tid, ((reflect_t){Mid, 0, Msz, M, infos, NULL, Tid, type }));
2023-10-11 19:01:06 +00:00
// add member separately as well
if(!members) map_init_int(members);
2023-10-15 11:16:35 +00:00
array(reflect_t) *found = map_find_or_add(members, Tid, 0);
2023-10-16 20:07:29 +00:00
array_push(*found, ((reflect_t){Mid, 0, Msz, M, infos, NULL, Tid, type, bytes }));
2023-10-11 19:01:06 +00:00
}
2023-10-15 11:16:35 +00:00
reflect_t member_find(const char *T, const char *M) {
2023-10-16 15:15:59 +00:00
reflect_init();
2023-10-20 17:55:43 +00:00
T = symbol(T);
M = symbol(M);
2023-10-11 19:01:06 +00:00
return *map_find(reflects, (intern(M)<<16)|intern(T));
}
void *member_findptr(void *obj, const char *T, const char *M) {
2023-10-16 15:15:59 +00:00
reflect_init();
2023-10-20 17:55:43 +00:00
T = symbol(T);
M = symbol(M);
2023-10-11 19:01:06 +00:00
return (char*)obj + member_find(T,M).sz;
}
2023-10-21 09:18:13 +00:00
array(reflect_t)* members_find(const char *T) {
2023-10-16 15:15:59 +00:00
reflect_init();
2023-10-20 17:55:43 +00:00
T = symbol(T);
2023-10-21 09:18:13 +00:00
return map_find(members, intern(T));
2023-10-11 19:01:06 +00:00
}
2023-10-16 15:15:59 +00:00
void reflect_dump(const char *mask) {
for each_map_ptr(reflects, unsigned, k, reflect_t, R) {
if( strmatchi(R->name, mask))
printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s\n",
R->name ? R->name : "", R->info ? R->info : "", R->id, R->objtype, R->sz, R->addr, R->parent, R->type ? R->type : "");
}
}
void reflect_print_(const reflect_t *R) {
static __thread int tabs = 0;
printf("%*.s", 4 * (tabs++), "");
unsigned symbol_q = intern(R->name);
{
array(reflect_t) *RR = map_find(members, symbol_q);
/**/ if( RR ) { printf("struct %s: %s%s\n", R->name, R->info ? "// ":"", R->info ? R->info : ""); for each_array_ptr(*RR, reflect_t, it) reflect_print_(it); }
else if( R->addr ) printf("func %s(); %s%s\n", R->name, R->info ? "// ":"", R->info ? R->info : "");
else if( !R->parent ) printf("enum %s = %d; %s%s\n", R->name, R->sz, R->info ? "// ":"", R->info ? R->info : "");
else printf("%s %s; %s%s\n", R->type, R->name, R->info ? "// ":"", R->info ? R->info : "");
/*
ifdef(debug,
printf("%.*sname:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s\n",
tabs, "", R->name ? R->name : "", R->info ? R->info : "", R->id, R->objtype, R->sz, R->addr, R->parent, R->type ? R->type : "");
);
*/
}
--tabs;
}
void reflect_print(const char *symbol) {
reflect_t *found = map_find(reflects, intern(symbol));
if( found ) reflect_print_(found);
}
2023-10-11 19:01:06 +00:00
// -- tests
2023-10-16 20:07:29 +00:00
// type0 is reserved (no type)
// type1 reserved for objs
// type2 reserved for entities
// @todo: type3 and 4 likely reserved for components and systems??
// enum { OBJTYPE_vec3 = 0x03 };
2023-10-11 19:01:06 +00:00
AUTOTEST {
2023-10-16 20:07:29 +00:00
// register structs, enums and functions. with and without comments+tags
2023-10-11 19:01:06 +00:00
2023-10-16 20:07:29 +00:00
STRUCT( vec3, float, x );
STRUCT( vec3, float, y );
STRUCT( vec3, float, z, "Up" );
2023-10-11 19:01:06 +00:00
2023-10-16 20:07:29 +00:00
ENUM( IMAGE_RGB );
ENUM( TEXTURE_RGB, "3-channel Red+Green+Blue texture flag" );
ENUM( TEXTURE_RGBA, "4-channel Red+Green+Blue+Alpha texture flag" );
2023-10-11 19:01:06 +00:00
2023-10-16 20:07:29 +00:00
FUNCTION( puts );
FUNCTION( printf, "function that prints formatted text to stdout" );
2023-10-11 19:01:06 +00:00
// verify some reflected infos
test( function_find("puts") == puts );
test( function_find("printf") == printf );
2023-10-16 20:07:29 +00:00
test( enum_find("TEXTURE_RGB") == TEXTURE_RGB );
test( enum_find("TEXTURE_RGBA") == TEXTURE_RGBA );
2023-10-11 19:01:06 +00:00
// iterate reflected struct
2023-10-16 20:07:29 +00:00
for each_member("vec3", R) {
//printf("+%s vec3.%s (+%x) // %s\n", R->type, R->name, R->member_offset, R->info);
2023-10-11 19:01:06 +00:00
}
2023-10-16 15:15:59 +00:00
// reflect_print("puts");
2023-10-16 20:07:29 +00:00
//reflect_print("TEXTURE_RGBA");
//reflect_print("vec3");
2023-10-16 15:15:59 +00:00
// reflect_dump("*");
2023-10-11 19:01:06 +00:00
}