Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[meta] Getter interface for primitive opaque types #1403

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 83 additions & 45 deletions distr/flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -49011,9 +49011,18 @@ bool ecs_meta_get_bool(
case EcsOpBitmask: return *(ecs_u32_t*)ptr != 0;
case EcsOpEntity: return *(ecs_entity_t*)ptr != 0;
case EcsOpId: return *(ecs_id_t*)ptr != 0;
case EcsOpOpaque: {
/* If opaque type knows how to convert to bool, retrieve it.
Otherwise, fallback to default case (error). */
const EcsOpaque *opaque = ecs_get(cursor->world, op->type, EcsOpaque);
if(opaque && opaque->get_bool) {
return opaque->get_bool(ptr);
}
/* Not a compatible opaque type, so fall through */
}
/* fall through */
case EcsOpArray:
case EcsOpVector:
case EcsOpOpaque:
case EcsOpPush:
case EcsOpPop:
case EcsOpScope:
Expand All @@ -49038,9 +49047,18 @@ char ecs_meta_get_char(
switch(op->kind) {
case EcsOpChar:
return *(ecs_char_t*)ptr != 0;
case EcsOpOpaque: {
/* If opaque type knows how to convert to char, retrieve it.
Otherwise, fallback to default case (error). */
const EcsOpaque *opaque = ecs_get(cursor->world, op->type, EcsOpaque);
if(opaque && opaque->get_char) {
return opaque->get_char(ptr);
}
/* Not a compatible opaque type, so fall through */
}
/* fall through */
case EcsOpArray:
case EcsOpVector:
case EcsOpOpaque:
case EcsOpPush:
case EcsOpPop:
case EcsOpScope:
Expand Down Expand Up @@ -49105,9 +49123,18 @@ int64_t ecs_meta_get_int(
ecs_throw(ECS_INVALID_PARAMETER,
"invalid conversion from id to int");
break;
case EcsOpOpaque: {
/* If opaque type knows how to convert to int, retrieve it.
Otherwise, fallback to default case (error). */
const EcsOpaque *opaque = ecs_get(cursor->world, op->type, EcsOpaque);
if(opaque && opaque->get_int) {
return opaque->get_int(ptr);
}
/* Not a compatible opaque type, so fall through */
}
/* fall through */
case EcsOpArray:
case EcsOpVector:
case EcsOpOpaque:
case EcsOpPush:
case EcsOpPop:
case EcsOpScope:
Expand Down Expand Up @@ -49149,9 +49176,18 @@ uint64_t ecs_meta_get_uint(
case EcsOpBitmask: return *(const ecs_u32_t*)ptr;
case EcsOpEntity: return *(const ecs_entity_t*)ptr;
case EcsOpId: return *(const ecs_id_t*)ptr;
case EcsOpOpaque: {
/* If opaque type knows how to convert to uint, retrieve it.
Otherwise, fallback to default case (error). */
const EcsOpaque *opaque = ecs_get(cursor->world, op->type, EcsOpaque);
if(opaque && opaque->get_uint) {
return opaque->get_uint(ptr);
}
/* Not a compatible opaque type, so fall through */
}
/* fall through */
case EcsOpArray:
case EcsOpVector:
case EcsOpOpaque:
case EcsOpPush:
case EcsOpPop:
case EcsOpScope:
Expand Down Expand Up @@ -49208,7 +49244,7 @@ double flecs_meta_to_float(
ecs_throw(ECS_INVALID_PARAMETER, "invalid element for float");
break;
default:
ecs_throw(ECS_INVALID_PARAMETER, "invalid operation");

break;
}
error:
Expand All @@ -49221,30 +49257,18 @@ double ecs_meta_get_float(
ecs_meta_scope_t *scope = flecs_meta_cursor_get_scope(cursor);
ecs_meta_type_op_t *op = flecs_meta_cursor_get_op(scope);
void *ptr = flecs_meta_cursor_get_ptr(cursor->world, scope);
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;
if(op->kind == EcsOpOpaque){
/* If opaque type knows how to convert to float, retrieve it.
Otherwise, fallback to default case (error). */
const EcsOpaque *opaque = ecs_get(cursor->world, op->type, EcsOpaque);
if(opaque && opaque->get_float) {
return opaque->get_float(ptr);
}
ecs_throw(ECS_INVALID_PARAMETER, "invalid operation");
error:
return 0;
}
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;
return flecs_meta_to_float(op->kind, ptr);
}

const char* ecs_meta_get_string(
Expand All @@ -49256,21 +49280,11 @@ const char* ecs_meta_get_string(
switch(op->kind) {
case EcsOpString: return *(const char**)ptr;
case EcsOpOpaque: {
/* If opaque type happens to map to a string, retrieve it.
/* If opaque type knows how to convert to 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 */
if(opaque && opaque->get_string) {
return opaque->get_string(ptr);
}
/* Not a compatible opaque type, so fall through */
}
Expand Down Expand Up @@ -49316,9 +49330,18 @@ ecs_entity_t ecs_meta_get_entity(
void *ptr = flecs_meta_cursor_get_ptr(cursor->world, scope);
switch(op->kind) {
case EcsOpEntity: return *(ecs_entity_t*)ptr;
case EcsOpOpaque: {
/* If opaque type knows how to convert to entity, retrieve it.
Otherwise, fallback to default case (error). */
const EcsOpaque *opaque = ecs_get(cursor->world, op->type, EcsOpaque);
if(opaque && opaque->get_entity) {
return opaque->get_entity(ptr, cursor->world);
}
/* Not a compatible opaque type, so fall through */
}
/* fall through */
case EcsOpArray:
case EcsOpVector:
case EcsOpOpaque:
case EcsOpPush:
case EcsOpPop:
case EcsOpScope:
Expand Down Expand Up @@ -49349,7 +49372,7 @@ ecs_entity_t ecs_meta_get_entity(
return 0;
}

ecs_entity_t ecs_meta_get_id(
ecs_id_t ecs_meta_get_id(
const ecs_meta_cursor_t *cursor)
{
ecs_meta_scope_t *scope = flecs_meta_cursor_get_scope(cursor);
Expand All @@ -49358,9 +49381,18 @@ ecs_entity_t ecs_meta_get_id(
switch(op->kind) {
case EcsOpEntity: return *(ecs_id_t*)ptr; /* Entities are valid ids */
case EcsOpId: return *(ecs_id_t*)ptr;
case EcsOpOpaque: {
/* If opaque type knows how to convert to id, retrieve it.
Otherwise, fallback to default case (error). */
const EcsOpaque *opaque = ecs_get(cursor->world, op->type, EcsOpaque);
if(opaque && opaque->get_id) {
return opaque->get_id(ptr, cursor->world);
}
/* Not a compatible opaque type, so fall through */
}
/* fall through */
case EcsOpArray:
case EcsOpVector:
case EcsOpOpaque:
case EcsOpPush:
case EcsOpPop:
case EcsOpScope:
Expand Down Expand Up @@ -49438,6 +49470,11 @@ int flecs_const_str_serialize(const ecs_serializer_t *ser, const void *ptr) {
return 0;
}

static
const char* flecs_const_get_string(const void *ptr) {
return *((const char *const *) ptr);
}

/* Initialize reflection data for core components */
static
void flecs_meta_import_core_definitions(
Expand Down Expand Up @@ -49477,7 +49514,8 @@ void flecs_meta_import_core_definitions(
}),
.type = {
.as_type = ecs_id(ecs_string_t),
.serialize = flecs_const_str_serialize,
.serialize = flecs_const_str_serialize,
.get_string = flecs_const_get_string,
}
});

Expand Down
104 changes: 104 additions & 0 deletions distr/flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -15411,6 +15411,43 @@ typedef struct EcsOpaque {
void (*resize)(
void *dst,
size_t count);

/* Getter interface */

/** Get bool value */
bool (*get_bool)(
const void *src);

/** Get char value */
char (*get_char)(
const void *src);

/** Get int value */
int64_t (*get_int)(
const void *src);

/** Get unsigned int value */
uint64_t (*get_uint)(
const void *src);

/** Get float value */
double (*get_float)(
const void *src);

/** Get string value */
const char* (*get_string)(
const void *src);

/** Get entity value */
ecs_entity_t (*get_entity)(
const void *src,
const ecs_world_t *world);

/** Get (component) id value */
ecs_id_t (*get_id)(
const void *src,
const ecs_world_t *world);

} EcsOpaque;


Expand Down Expand Up @@ -15876,6 +15913,7 @@ ecs_entity_t ecs_meta_get_entity(
* @param cursor The cursor.
* @return The value of the current field.
*/
FLECS_API
ecs_id_t ecs_meta_get_id(
const ecs_meta_cursor_t *cursor);

Expand Down Expand Up @@ -19045,6 +19083,72 @@ struct opaque {
return *this;
}

/* Getter interface */

/** Get bool value */
opaque& get_bool(bool (*func)(const T *src)) {
this->desc.type.get_bool =
reinterpret_cast<decltype(
this->desc.type.get_bool)>(func);
return *this;
}

/** Get char value */
opaque& get_char(char (*func)(const T *src)) {
this->desc.type.get_char =
reinterpret_cast<decltype(
this->desc.type.get_char)>(func);
return *this;
}

/** Get int value */
opaque& get_int(int64_t (*func)(const T *src)) {
this->desc.type.get_int =
reinterpret_cast<decltype(
this->desc.type.get_int)>(func);
return *this;
}

/** Get unsigned int value */
opaque& get_uint(uint64_t (*func)(const T *src)) {
this->desc.type.get_uint =
reinterpret_cast<decltype(
this->desc.type.get_uint)>(func);
return *this;
}

/** Get float value */
opaque& get_float(double (*func)(const T *src)) {
this->desc.type.get_float =
reinterpret_cast<decltype(
this->desc.type.get_float)>(func);
return *this;
}

/** Get string value */
opaque& get_string(const char* (*func)(const T *src)) {
this->desc.type.get_string =
reinterpret_cast<decltype(
this->desc.type.get_string)>(func);
return *this;
}

/** Get entity value */
opaque& get_entity(ecs_entity_t (*func)(const T *src, const flecs::world_t *world)) {
this->desc.type.get_entity =
reinterpret_cast<decltype(
this->desc.type.get_entity)>(func);
return *this;
}

/** Get (component) id value */
opaque& get_id(ecs_id_t (*func)(const T *src, const flecs::world_t *world)) {
this->desc.type.get_id =
reinterpret_cast<decltype(
this->desc.type.get_id)>(func);
return *this;
}

~opaque() {
if (world) {
ecs_opaque_init(world, &desc);
Expand Down
Loading