Skip to content

Commit

Permalink
Have ecs_meta_get_string() work with opaques with .as_type = string
Browse files Browse the repository at this point in the history
  • Loading branch information
jpeletier authored and SanderMertens committed Aug 21, 2024
1 parent 5414ea5 commit 7934672
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 9 deletions.
44 changes: 43 additions & 1 deletion flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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:
Expand Down
44 changes: 43 additions & 1 deletion src/addons/meta/cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion test/meta/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
17 changes: 14 additions & 3 deletions test/meta/src/Cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) );
Expand Down Expand Up @@ -2941,15 +2941,23 @@ 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);

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 };
Expand All @@ -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);
}

Expand Down
6 changes: 3 additions & 3 deletions test/meta/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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",
Expand Down

0 comments on commit 7934672

Please sign in to comment.