diff --git a/flecs.c b/flecs.c index cbcd3b37d..a1d21ca99 100644 --- a/flecs.c +++ b/flecs.c @@ -48336,6 +48336,29 @@ double ecs_meta_get_float( return flecs_meta_to_float(op->kind, ptr); } +/* Handler to get string from opaque (see ecs_meta_get_string below) */ +static int ecs_meta_get_string_value_from_opaque( + const struct ecs_serializer_t *ser, ecs_entity_t type, const void *value) +{ + if(type != ecs_id(ecs_string_t)) { + ecs_err("Expected value call for opaque type to be a string"); + return -1; + } + char*** ctx = (char ***) ser->ctx; + *ctx = ECS_CONST_CAST(char**, value); + return 0; +} + +/* Handler to get string from opaque (see ecs_meta_get_string below) */ +static int ecs_meta_get_string_member_from_opaque( + const struct ecs_serializer_t* ser, const char* name) +{ + (void)ser; // silence unused warning + (void)name; // silence unused warning + ecs_err("Unexpected member call when serializing string from opaque"); + return -1; +} + const char* ecs_meta_get_string( const ecs_meta_cursor_t *cursor) { @@ -48344,9 +48367,28 @@ const char* ecs_meta_get_string( void *ptr = flecs_meta_cursor_get_ptr(cursor->world, scope); switch(op->kind) { case EcsOpString: return *(const char**)ptr; + case EcsOpOpaque: { + /* If opaque type happens to map to a string, retrieve it. + Otherwise, fallback to default case (error). */ + const EcsOpaque *opaque = ecs_get(cursor->world, op->type, EcsOpaque); + if(opaque && opaque->as_type == ecs_id(ecs_string_t) && opaque->serialize) { + char** str = NULL; + ecs_serializer_t ser = { + .world = cursor->world, + .value = ecs_meta_get_string_value_from_opaque, + .member = ecs_meta_get_string_member_from_opaque, + .ctx = &str + }; + opaque->serialize(&ser, ptr); + if(str && *str) + return *str; + /* invalid string, so fall through */ + } + /* Not a compatible opaque type, so fall through */ + } + /* fall through */ case EcsOpArray: case EcsOpVector: - case EcsOpOpaque: case EcsOpPush: case EcsOpPop: case EcsOpScope: diff --git a/src/addons/meta/cursor.c b/src/addons/meta/cursor.c index 78c416149..17d6439dc 100644 --- a/src/addons/meta/cursor.c +++ b/src/addons/meta/cursor.c @@ -1961,6 +1961,29 @@ double ecs_meta_get_float( return flecs_meta_to_float(op->kind, ptr); } +/* Handler to get string from opaque (see ecs_meta_get_string below) */ +static int ecs_meta_get_string_value_from_opaque( + const struct ecs_serializer_t *ser, ecs_entity_t type, const void *value) +{ + if(type != ecs_id(ecs_string_t)) { + ecs_err("Expected value call for opaque type to be a string"); + return -1; + } + char*** ctx = (char ***) ser->ctx; + *ctx = ECS_CONST_CAST(char**, value); + return 0; +} + +/* Handler to get string from opaque (see ecs_meta_get_string below) */ +static int ecs_meta_get_string_member_from_opaque( + const struct ecs_serializer_t* ser, const char* name) +{ + (void)ser; // silence unused warning + (void)name; // silence unused warning + ecs_err("Unexpected member call when serializing string from opaque"); + return -1; +} + const char* ecs_meta_get_string( const ecs_meta_cursor_t *cursor) { @@ -1969,9 +1992,28 @@ const char* ecs_meta_get_string( void *ptr = flecs_meta_cursor_get_ptr(cursor->world, scope); switch(op->kind) { case EcsOpString: return *(const char**)ptr; + case EcsOpOpaque: { + /* If opaque type happens to map to a string, retrieve it. + Otherwise, fallback to default case (error). */ + const EcsOpaque *opaque = ecs_get(cursor->world, op->type, EcsOpaque); + if(opaque && opaque->as_type == ecs_id(ecs_string_t) && opaque->serialize) { + char** str = NULL; + ecs_serializer_t ser = { + .world = cursor->world, + .value = ecs_meta_get_string_value_from_opaque, + .member = ecs_meta_get_string_member_from_opaque, + .ctx = &str + }; + opaque->serialize(&ser, ptr); + if(str && *str) + return *str; + /* invalid string, so fall through */ + } + /* Not a compatible opaque type, so fall through */ + } + /* fall through */ case EcsOpArray: case EcsOpVector: - case EcsOpOpaque: case EcsOpPush: case EcsOpPop: case EcsOpScope: diff --git a/test/meta/project.json b/test/meta/project.json index 653936f06..04f86fb22 100644 --- a/test/meta/project.json +++ b/test/meta/project.json @@ -385,7 +385,7 @@ "opaque_set_int", "opaque_set_uint", "opaque_set_float", - "opaque_set_string", + "opaque_get_set_string", "opaque_set_entity", "opaque_set_id", "opaque_set_int_vec", diff --git a/test/meta/src/Cursor.c b/test/meta/src/Cursor.c index ac7f44c76..8f79b2332 100644 --- a/test/meta/src/Cursor.c +++ b/test/meta/src/Cursor.c @@ -2249,7 +2249,7 @@ void Cursor_struct_pop_after_dotmember(void) { } }); - T value = {{0}}; + T value = {{{0, 0},{0, 0}}, {{0, 0},{0, 0}}}; ecs_meta_cursor_t cur = ecs_meta_cursor(world, t, &value); test_ok( ecs_meta_push(&cur) ); @@ -2941,7 +2941,14 @@ void Cursor_opaque_set_float(void) { ecs_fini(world); } -void Cursor_opaque_set_string(void) { +static +int const_string_t_serialize(const ecs_serializer_t *ser, const void *ptr) { + char **data = ECS_CONST_CAST(char**, ptr); + ser->value(ser, ecs_id(ecs_string_t), data); + return 0; +} + +void Cursor_opaque_get_set_string(void) { ecs_world_t *world = ecs_init(); ECS_COMPONENT(world, Opaque_const_string_t); @@ -2949,7 +2956,8 @@ void Cursor_opaque_set_string(void) { ecs_opaque(world, { .entity = ecs_id(Opaque_const_string_t), .type.as_type = ecs_id(ecs_string_t), - .type.assign_string = const_string_t_set + .type.assign_string = const_string_t_set, + .type.serialize = const_string_t_serialize }); Opaque_const_string_t v = { 0 }; @@ -2958,6 +2966,9 @@ void Cursor_opaque_set_string(void) { test_int(0, ecs_meta_set_string(&cur, "Hello World")); test_str(v.value, "Hello World"); + const char* str = ecs_meta_get_string(&cur); + test_str(str, "Hello World"); + ecs_fini(world); } diff --git a/test/meta/src/main.c b/test/meta/src/main.c index e84906fce..06d65a4fa 100644 --- a/test/meta/src/main.c +++ b/test/meta/src/main.c @@ -362,7 +362,7 @@ void Cursor_opaque_set_char(void); void Cursor_opaque_set_int(void); void Cursor_opaque_set_uint(void); void Cursor_opaque_set_float(void); -void Cursor_opaque_set_string(void); +void Cursor_opaque_get_set_string(void); void Cursor_opaque_set_entity(void); void Cursor_opaque_set_id(void); void Cursor_opaque_set_int_vec(void); @@ -2310,8 +2310,8 @@ bake_test_case Cursor_testcases[] = { Cursor_opaque_set_float }, { - "opaque_set_string", - Cursor_opaque_set_string + "opaque_get_set_string", + Cursor_opaque_get_set_string }, { "opaque_set_entity",