diff --git a/distr/flecs.c b/distr/flecs.c index 4405eb6af..fcf9ccf7b 100644 --- a/distr/flecs.c +++ b/distr/flecs.c @@ -25444,7 +25444,7 @@ int flecs_member_metric_init( id = desc->id; member_type = ecs_meta_get_type(&cur); - offset = (uintptr_t)ecs_meta_get_ptr(&cur); + offset = (uintptr_t)ecs_meta_get_write_ptr(&cur); member = ecs_meta_get_member_id(&cur); } else { const EcsMember *m = ecs_get(world, desc->member, EcsMember); @@ -48244,9 +48244,9 @@ int32_t get_elem_count( return op->count; } -/* Get pointer to current field/element */ +/* Get pointer to current field/element for writing */ static -ecs_meta_type_op_t* flecs_meta_cursor_get_ptr( +void* flecs_meta_cursor_get_write_ptr( const ecs_world_t *world, ecs_meta_scope_t *scope) { @@ -48290,6 +48290,52 @@ ecs_meta_type_op_t* flecs_meta_cursor_get_ptr( return ECS_OFFSET(scope->ptr, size * scope->elem_cur + op->offset); } +/* Get pointer to current field/element for reading */ +static +const void* flecs_meta_cursor_get_read_ptr( + const ecs_world_t *world, + ecs_meta_scope_t *scope) +{ + ecs_meta_type_op_t *op = flecs_meta_cursor_get_op(scope); + ecs_size_t size = get_size(world, scope); + const EcsOpaque *opaque = scope->opaque; + + if (scope->vector) { + if(ecs_vec_count(scope->vector) <= scope->elem_cur){ + return NULL; + } + scope->ptr = ecs_vec_first(scope->vector); + } else if (opaque) { + if (scope->is_collection) { + if (!opaque->get_element) { + char *str = ecs_get_path(world, scope->type); + ecs_err("missing get_element for opaque type %s", str); + ecs_os_free(str); + return NULL; + } + scope->is_empty_scope = false; + + const void *opaque_ptr = opaque->get_element( + scope->ptr, flecs_ito(size_t, scope->elem_cur)); + return opaque_ptr; + } else if (op->name) { + if (!opaque->get_member) { + char *str = ecs_get_path(world, scope->type); + ecs_err("missing get_member for opaque type %s", str); + ecs_os_free(str); + return NULL; + } + ecs_assert(scope->ptr != NULL, ECS_INTERNAL_ERROR, NULL); + return opaque->get_member(scope->ptr, op->name); + } else { + ecs_err("invalid operation for opaque type"); + return NULL; + } + } + + return ECS_OFFSET(scope->ptr, size * scope->elem_cur + op->offset); +} + static int flecs_meta_cursor_push_type( const ecs_world_t *world, @@ -48338,10 +48384,17 @@ ecs_meta_cursor_t ecs_meta_cursor( return (ecs_meta_cursor_t){ 0 }; } -void* ecs_meta_get_ptr( +void* ecs_meta_get_write_ptr( + ecs_meta_cursor_t *cursor) +{ + return flecs_meta_cursor_get_write_ptr(cursor->world, + flecs_meta_cursor_get_scope(cursor)); +} + +const void* ecs_meta_get_read_ptr( ecs_meta_cursor_t *cursor) { - return flecs_meta_cursor_get_ptr(cursor->world, + return flecs_meta_cursor_get_read_ptr(cursor->world, flecs_meta_cursor_get_scope(cursor)); } @@ -48528,7 +48581,7 @@ int ecs_meta_push( } } - void *ptr = flecs_meta_cursor_get_ptr(world, scope); + void *ptr = flecs_meta_cursor_get_write_ptr(world, scope); cursor->depth ++; ecs_check(cursor->depth < ECS_META_MAX_SCOPE_DEPTH, ECS_INVALID_PARAMETER, NULL); @@ -49015,7 +49068,7 @@ int ecs_meta_set_bool( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { cases_T_bool(ptr, value); @@ -49065,7 +49118,7 @@ int ecs_meta_set_char( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { cases_T_bool(ptr, value); @@ -49127,7 +49180,7 @@ int ecs_meta_set_int( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { cases_T_bool(ptr, value); @@ -49185,7 +49238,7 @@ int ecs_meta_set_uint( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { cases_T_bool(ptr, value); @@ -49242,7 +49295,7 @@ int ecs_meta_set_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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { case EcsOpBool: @@ -49348,7 +49401,7 @@ int ecs_meta_set_value( } else { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); if (op->type != value->type) { char *type_str = ecs_get_path(cursor->world, value->type); flecs_meta_conversion_error(cursor, op, type_str); @@ -49463,7 +49516,7 @@ int ecs_meta_set_string( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { case EcsOpI8: @@ -49651,7 +49704,7 @@ int ecs_meta_set_string_literal( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); if (!value) { return -1; @@ -49723,7 +49776,7 @@ int ecs_meta_set_entity( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { case EcsOpEntity: @@ -49788,7 +49841,7 @@ int ecs_meta_set_id( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { case EcsOpId: @@ -49850,7 +49903,7 @@ int ecs_meta_set_null( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch (op->kind) { case EcsOpString: ecs_os_free(*(char**)ptr); @@ -49906,31 +49959,43 @@ bool ecs_meta_get_bool( { 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); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { - case EcsOpBool: return *(ecs_bool_t*)ptr; - case EcsOpI8: return *(ecs_i8_t*)ptr != 0; - case EcsOpU8: return *(ecs_u8_t*)ptr != 0; - case EcsOpChar: return *(ecs_char_t*)ptr != 0; - case EcsOpByte: return *(ecs_u8_t*)ptr != 0; - case EcsOpI16: return *(ecs_i16_t*)ptr != 0; - case EcsOpU16: return *(ecs_u16_t*)ptr != 0; - case EcsOpI32: return *(ecs_i32_t*)ptr != 0; - case EcsOpU32: return *(ecs_u32_t*)ptr != 0; - case EcsOpI64: return *(ecs_i64_t*)ptr != 0; - case EcsOpU64: return *(ecs_u64_t*)ptr != 0; - case EcsOpIPtr: return *(ecs_iptr_t*)ptr != 0; - case EcsOpUPtr: return *(ecs_uptr_t*)ptr != 0; - case EcsOpF32: return ECS_NEQZERO(*(ecs_f32_t*)ptr); - case EcsOpF64: return ECS_NEQZERO(*(ecs_f64_t*)ptr); - case EcsOpString: return *(const char**)ptr != NULL; - case EcsOpEnum: return *(ecs_i32_t*)ptr != 0; - 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 EcsOpBool: return *(const ecs_bool_t*)ptr; + case EcsOpI8: return *(const ecs_i8_t*)ptr != 0; + case EcsOpU8: return *(const ecs_u8_t*)ptr != 0; + case EcsOpChar: return *(const ecs_char_t*)ptr != 0; + case EcsOpByte: return *(const ecs_u8_t*)ptr != 0; + case EcsOpI16: return *(const ecs_i16_t*)ptr != 0; + case EcsOpU16: return *(const ecs_u16_t*)ptr != 0; + case EcsOpI32: return *(const ecs_i32_t*)ptr != 0; + case EcsOpU32: return *(const ecs_u32_t*)ptr != 0; + case EcsOpI64: return *(const ecs_i64_t*)ptr != 0; + case EcsOpU64: return *(const ecs_u64_t*)ptr != 0; + case EcsOpIPtr: return *(const ecs_iptr_t*)ptr != 0; + case EcsOpUPtr: return *(const ecs_uptr_t*)ptr != 0; + case EcsOpF32: return ECS_NEQZERO(*(const ecs_f32_t*)ptr); + case EcsOpF64: return ECS_NEQZERO(*(const ecs_f64_t*)ptr); + case EcsOpString: return *(const char* const *)ptr != NULL; + case EcsOpEnum: return *(const ecs_i32_t*)ptr != 0; + case EcsOpBitmask: return *(const ecs_u32_t*)ptr != 0; + case EcsOpEntity: return *(const ecs_entity_t*)ptr != 0; + case EcsOpId: return *(const 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: @@ -49951,13 +50016,25 @@ char ecs_meta_get_char( { 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); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { case EcsOpChar: - return *(ecs_char_t*)ptr != 0; + return *(const ecs_char_t*)ptr; + 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: @@ -49994,7 +50071,10 @@ int64_t ecs_meta_get_int( { 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); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { case EcsOpBool: return *(const ecs_bool_t*)ptr; case EcsOpI8: return *(const ecs_i8_t*)ptr; @@ -50011,7 +50091,7 @@ int64_t ecs_meta_get_int( case EcsOpUPtr: return flecs_uto(int64_t, *(const ecs_uptr_t*)ptr); case EcsOpF32: return (int64_t)*(const ecs_f32_t*)ptr; case EcsOpF64: return (int64_t)*(const ecs_f64_t*)ptr; - case EcsOpString: return atoi(*(const char**)ptr); + case EcsOpString: return atoi(*(const char* const *)ptr); case EcsOpEnum: return *(const ecs_i32_t*)ptr; case EcsOpBitmask: return *(const ecs_u32_t*)ptr; case EcsOpEntity: @@ -50022,9 +50102,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: @@ -50044,31 +50133,43 @@ uint64_t ecs_meta_get_uint( { 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); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { - case EcsOpBool: return *(ecs_bool_t*)ptr; + case EcsOpBool: return *(const ecs_bool_t*)ptr; case EcsOpI8: return flecs_ito(uint64_t, *(const ecs_i8_t*)ptr); - case EcsOpU8: return *(ecs_u8_t*)ptr; + case EcsOpU8: return *(const ecs_u8_t*)ptr; case EcsOpChar: return flecs_ito(uint64_t, *(const ecs_char_t*)ptr); case EcsOpByte: return flecs_ito(uint64_t, *(const ecs_u8_t*)ptr); case EcsOpI16: return flecs_ito(uint64_t, *(const ecs_i16_t*)ptr); - case EcsOpU16: return *(ecs_u16_t*)ptr; + case EcsOpU16: return *(const ecs_u16_t*)ptr; case EcsOpI32: return flecs_ito(uint64_t, *(const ecs_i32_t*)ptr); - case EcsOpU32: return *(ecs_u32_t*)ptr; + case EcsOpU32: return *(const ecs_u32_t*)ptr; case EcsOpI64: return flecs_ito(uint64_t, *(const ecs_i64_t*)ptr); - case EcsOpU64: return *(ecs_u64_t*)ptr; + case EcsOpU64: return *(const ecs_u64_t*)ptr; case EcsOpIPtr: return flecs_ito(uint64_t, *(const ecs_i64_t*)ptr); - case EcsOpUPtr: return *(ecs_uptr_t*)ptr; + case EcsOpUPtr: return *(const ecs_uptr_t*)ptr; case EcsOpF32: return flecs_ito(uint64_t, *(const ecs_f32_t*)ptr); case EcsOpF64: return flecs_ito(uint64_t, *(const ecs_f64_t*)ptr); - case EcsOpString: return flecs_ito(uint64_t, atoi(*(const char**)ptr)); + case EcsOpString: return flecs_ito(uint64_t, atoi(*(const char* const *)ptr)); case EcsOpEnum: return flecs_ito(uint64_t, *(const ecs_i32_t*)ptr); 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: @@ -50125,7 +50226,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: @@ -50137,31 +50238,22 @@ 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; + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); } - 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; + 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; + } + return flecs_meta_to_float(op->kind, ptr); } const char* ecs_meta_get_string( @@ -50169,25 +50261,18 @@ const char* ecs_meta_get_string( { 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); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { - case EcsOpString: return *(const char**)ptr; + case EcsOpString: return *(const char* const*)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 */ } @@ -50230,12 +50315,24 @@ ecs_entity_t ecs_meta_get_entity( { 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); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { - case EcsOpEntity: return *(ecs_entity_t*)ptr; + case EcsOpEntity: return *(const 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: @@ -50266,18 +50363,30 @@ 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); ecs_meta_type_op_t *op = flecs_meta_cursor_get_op(scope); - void *ptr = flecs_meta_cursor_get_ptr(cursor->world, scope); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { - case EcsOpEntity: return *(ecs_id_t*)ptr; /* Entities are valid ids */ - case EcsOpId: return *(ecs_id_t*)ptr; + case EcsOpEntity: return *(const ecs_id_t*)ptr; /* Entities are valid ids */ + case EcsOpId: return *(const 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: @@ -50355,6 +50464,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( @@ -50394,7 +50508,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, } }); @@ -80572,7 +80687,7 @@ int flecs_expr_initializer_visit_type( } if (!is_opaque) { - elem->offset = (uintptr_t)ecs_meta_get_ptr(cur); + elem->offset = (uintptr_t)ecs_meta_get_write_ptr(cur); } } @@ -81119,7 +81234,7 @@ int flecs_expr_member_visit_type( const EcsMember *m = ecs_get(world, ecs_meta_get_member_id(cur), EcsMember); ecs_assert(m != NULL, ECS_INTERNAL_ERROR, NULL); #endif - node->offset = (uintptr_t)ecs_meta_get_ptr(cur); + node->offset = (uintptr_t)ecs_meta_get_write_ptr(cur); return 0; error: diff --git a/distr/flecs.h b/distr/flecs.h index 867de1c59..80abf538e 100644 --- a/distr/flecs.h +++ b/distr/flecs.h @@ -15932,6 +15932,53 @@ 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); + + /** get collection element */ + const void* (*get_element)( + const void *src, + size_t elem); + + /** get element */ + const void* (*get_member)( + const void *src, + const char *member); + } EcsOpaque; @@ -16086,13 +16133,22 @@ ecs_meta_cursor_t ecs_meta_cursor( ecs_entity_t type, void *ptr); -/** Get pointer to current field. +/** Get pointer to current field for writing. + * + * @param cursor The cursor. + * @return A pointer to the current field for writing. + */ +FLECS_API +void* ecs_meta_get_write_ptr( + ecs_meta_cursor_t *cursor); + +/** Get pointer to current field for reading. * * @param cursor The cursor. - * @return A pointer to the current field. + * @return A pointer to the current field. NULL if element does not exist. */ FLECS_API -void* ecs_meta_get_ptr( +const void* ecs_meta_get_read_ptr( ecs_meta_cursor_t *cursor); /** Move cursor to next field. @@ -16397,6 +16453,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); @@ -19300,9 +19357,14 @@ struct cursor { /** Get unit of value */ flecs::entity get_unit() const; - /** Get untyped pointer to value */ - void* get_ptr() { - return ecs_meta_get_ptr(&cursor_); + /** Get untyped pointer to value for writing */ + void* get_write_ptr() { + return ecs_meta_get_write_ptr(&cursor_); + } + + /** Get untyped pointer to value for reading */ + const void* get_read_ptr() { + return ecs_meta_get_read_ptr(&cursor_); } /** Set boolean value */ @@ -19564,6 +19626,88 @@ struct opaque { return *this; } + /* Getter interface */ + + /** Get bool value */ + opaque& get_bool(bool (*func)(const T *src)) { + this->desc.type.get_bool = + reinterpret_castdesc.type.get_bool)>(func); + return *this; + } + + /** Get char value */ + opaque& get_char(char (*func)(const T *src)) { + this->desc.type.get_char = + reinterpret_castdesc.type.get_char)>(func); + return *this; + } + + /** Get int value */ + opaque& get_int(int64_t (*func)(const T *src)) { + this->desc.type.get_int = + reinterpret_castdesc.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_castdesc.type.get_uint)>(func); + return *this; + } + + /** Get float value */ + opaque& get_float(double (*func)(const T *src)) { + this->desc.type.get_float = + reinterpret_castdesc.type.get_float)>(func); + return *this; + } + + /** Get string value */ + opaque& get_string(const char* (*func)(const T *src)) { + this->desc.type.get_string = + reinterpret_castdesc.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_castdesc.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_castdesc.type.get_id)>(func); + return *this; + } + + /** Get collection element */ + opaque& get_element(const void* (*func)(const T *src, size_t elem)) { + this->desc.type.get_element = + reinterpret_castdesc.type.get_element)>(func); + return *this; + } + + /** get element */ + opaque& get_member(const void* (*func)(const T *src, const char *member)) { + this->desc.type.get_member = + reinterpret_castdesc.type.get_member)>(func); + return *this; + } + ~opaque() { if (world) { ecs_opaque_init(world, &desc); diff --git a/include/flecs/addons/cpp/mixins/meta/cursor.hpp b/include/flecs/addons/cpp/mixins/meta/cursor.hpp index 868621c2d..3bceb9062 100644 --- a/include/flecs/addons/cpp/mixins/meta/cursor.hpp +++ b/include/flecs/addons/cpp/mixins/meta/cursor.hpp @@ -65,9 +65,14 @@ struct cursor { /** Get unit of value */ flecs::entity get_unit() const; - /** Get untyped pointer to value */ - void* get_ptr() { - return ecs_meta_get_ptr(&cursor_); + /** Get untyped pointer to value for writing */ + void* get_write_ptr() { + return ecs_meta_get_write_ptr(&cursor_); + } + + /** Get untyped pointer to value for reading */ + const void* get_read_ptr() { + return ecs_meta_get_read_ptr(&cursor_); } /** Set boolean value */ diff --git a/include/flecs/addons/cpp/mixins/meta/opaque.hpp b/include/flecs/addons/cpp/mixins/meta/opaque.hpp index d1f23803c..81955597d 100644 --- a/include/flecs/addons/cpp/mixins/meta/opaque.hpp +++ b/include/flecs/addons/cpp/mixins/meta/opaque.hpp @@ -166,6 +166,88 @@ struct opaque { return *this; } + /* Getter interface */ + + /** Get bool value */ + opaque& get_bool(bool (*func)(const T *src)) { + this->desc.type.get_bool = + reinterpret_castdesc.type.get_bool)>(func); + return *this; + } + + /** Get char value */ + opaque& get_char(char (*func)(const T *src)) { + this->desc.type.get_char = + reinterpret_castdesc.type.get_char)>(func); + return *this; + } + + /** Get int value */ + opaque& get_int(int64_t (*func)(const T *src)) { + this->desc.type.get_int = + reinterpret_castdesc.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_castdesc.type.get_uint)>(func); + return *this; + } + + /** Get float value */ + opaque& get_float(double (*func)(const T *src)) { + this->desc.type.get_float = + reinterpret_castdesc.type.get_float)>(func); + return *this; + } + + /** Get string value */ + opaque& get_string(const char* (*func)(const T *src)) { + this->desc.type.get_string = + reinterpret_castdesc.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_castdesc.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_castdesc.type.get_id)>(func); + return *this; + } + + /** Get collection element */ + opaque& get_element(const void* (*func)(const T *src, size_t elem)) { + this->desc.type.get_element = + reinterpret_castdesc.type.get_element)>(func); + return *this; + } + + /** get element */ + opaque& get_member(const void* (*func)(const T *src, const char *member)) { + this->desc.type.get_member = + reinterpret_castdesc.type.get_member)>(func); + return *this; + } + ~opaque() { if (world) { ecs_opaque_init(world, &desc); diff --git a/include/flecs/addons/meta.h b/include/flecs/addons/meta.h index e795406c9..04c86ca27 100644 --- a/include/flecs/addons/meta.h +++ b/include/flecs/addons/meta.h @@ -465,6 +465,53 @@ 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); + + /** get collection element */ + const void* (*get_element)( + const void *src, + size_t elem); + + /** get element */ + const void* (*get_member)( + const void *src, + const char *member); + } EcsOpaque; @@ -619,13 +666,22 @@ ecs_meta_cursor_t ecs_meta_cursor( ecs_entity_t type, void *ptr); -/** Get pointer to current field. +/** Get pointer to current field for writing. + * + * @param cursor The cursor. + * @return A pointer to the current field for writing. + */ +FLECS_API +void* ecs_meta_get_write_ptr( + ecs_meta_cursor_t *cursor); + +/** Get pointer to current field for reading. * * @param cursor The cursor. - * @return A pointer to the current field. + * @return A pointer to the current field. NULL if element does not exist. */ FLECS_API -void* ecs_meta_get_ptr( +const void* ecs_meta_get_read_ptr( ecs_meta_cursor_t *cursor); /** Move cursor to next field. @@ -930,6 +986,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); diff --git a/src/addons/meta/cursor.c b/src/addons/meta/cursor.c index cfc294c0c..358a136c1 100644 --- a/src/addons/meta/cursor.c +++ b/src/addons/meta/cursor.c @@ -124,9 +124,9 @@ int32_t get_elem_count( return op->count; } -/* Get pointer to current field/element */ +/* Get pointer to current field/element for writing */ static -ecs_meta_type_op_t* flecs_meta_cursor_get_ptr( +void* flecs_meta_cursor_get_write_ptr( const ecs_world_t *world, ecs_meta_scope_t *scope) { @@ -170,6 +170,52 @@ ecs_meta_type_op_t* flecs_meta_cursor_get_ptr( return ECS_OFFSET(scope->ptr, size * scope->elem_cur + op->offset); } +/* Get pointer to current field/element for reading */ +static +const void* flecs_meta_cursor_get_read_ptr( + const ecs_world_t *world, + ecs_meta_scope_t *scope) +{ + ecs_meta_type_op_t *op = flecs_meta_cursor_get_op(scope); + ecs_size_t size = get_size(world, scope); + const EcsOpaque *opaque = scope->opaque; + + if (scope->vector) { + if(ecs_vec_count(scope->vector) <= scope->elem_cur){ + return NULL; + } + scope->ptr = ecs_vec_first(scope->vector); + } else if (opaque) { + if (scope->is_collection) { + if (!opaque->get_element) { + char *str = ecs_get_path(world, scope->type); + ecs_err("missing get_element for opaque type %s", str); + ecs_os_free(str); + return NULL; + } + scope->is_empty_scope = false; + + const void *opaque_ptr = opaque->get_element( + scope->ptr, flecs_ito(size_t, scope->elem_cur)); + return opaque_ptr; + } else if (op->name) { + if (!opaque->get_member) { + char *str = ecs_get_path(world, scope->type); + ecs_err("missing get_member for opaque type %s", str); + ecs_os_free(str); + return NULL; + } + ecs_assert(scope->ptr != NULL, ECS_INTERNAL_ERROR, NULL); + return opaque->get_member(scope->ptr, op->name); + } else { + ecs_err("invalid operation for opaque type"); + return NULL; + } + } + + return ECS_OFFSET(scope->ptr, size * scope->elem_cur + op->offset); +} + static int flecs_meta_cursor_push_type( const ecs_world_t *world, @@ -218,10 +264,17 @@ ecs_meta_cursor_t ecs_meta_cursor( return (ecs_meta_cursor_t){ 0 }; } -void* ecs_meta_get_ptr( +void* ecs_meta_get_write_ptr( ecs_meta_cursor_t *cursor) { - return flecs_meta_cursor_get_ptr(cursor->world, + return flecs_meta_cursor_get_write_ptr(cursor->world, + flecs_meta_cursor_get_scope(cursor)); +} + +const void* ecs_meta_get_read_ptr( + ecs_meta_cursor_t *cursor) +{ + return flecs_meta_cursor_get_read_ptr(cursor->world, flecs_meta_cursor_get_scope(cursor)); } @@ -408,7 +461,7 @@ int ecs_meta_push( } } - void *ptr = flecs_meta_cursor_get_ptr(world, scope); + void *ptr = flecs_meta_cursor_get_write_ptr(world, scope); cursor->depth ++; ecs_check(cursor->depth < ECS_META_MAX_SCOPE_DEPTH, ECS_INVALID_PARAMETER, NULL); @@ -895,7 +948,7 @@ int ecs_meta_set_bool( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { cases_T_bool(ptr, value); @@ -945,7 +998,7 @@ int ecs_meta_set_char( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { cases_T_bool(ptr, value); @@ -1007,7 +1060,7 @@ int ecs_meta_set_int( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { cases_T_bool(ptr, value); @@ -1065,7 +1118,7 @@ int ecs_meta_set_uint( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { cases_T_bool(ptr, value); @@ -1122,7 +1175,7 @@ int ecs_meta_set_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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { case EcsOpBool: @@ -1228,7 +1281,7 @@ int ecs_meta_set_value( } else { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); if (op->type != value->type) { char *type_str = ecs_get_path(cursor->world, value->type); flecs_meta_conversion_error(cursor, op, type_str); @@ -1343,7 +1396,7 @@ int ecs_meta_set_string( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { case EcsOpI8: @@ -1531,7 +1584,7 @@ int ecs_meta_set_string_literal( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); if (!value) { return -1; @@ -1603,7 +1656,7 @@ int ecs_meta_set_entity( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { case EcsOpEntity: @@ -1668,7 +1721,7 @@ int ecs_meta_set_id( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch(op->kind) { case EcsOpId: @@ -1730,7 +1783,7 @@ int ecs_meta_set_null( { 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); + void *ptr = flecs_meta_cursor_get_write_ptr(cursor->world, scope); switch (op->kind) { case EcsOpString: ecs_os_free(*(char**)ptr); @@ -1786,31 +1839,43 @@ bool ecs_meta_get_bool( { 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); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { - case EcsOpBool: return *(ecs_bool_t*)ptr; - case EcsOpI8: return *(ecs_i8_t*)ptr != 0; - case EcsOpU8: return *(ecs_u8_t*)ptr != 0; - case EcsOpChar: return *(ecs_char_t*)ptr != 0; - case EcsOpByte: return *(ecs_u8_t*)ptr != 0; - case EcsOpI16: return *(ecs_i16_t*)ptr != 0; - case EcsOpU16: return *(ecs_u16_t*)ptr != 0; - case EcsOpI32: return *(ecs_i32_t*)ptr != 0; - case EcsOpU32: return *(ecs_u32_t*)ptr != 0; - case EcsOpI64: return *(ecs_i64_t*)ptr != 0; - case EcsOpU64: return *(ecs_u64_t*)ptr != 0; - case EcsOpIPtr: return *(ecs_iptr_t*)ptr != 0; - case EcsOpUPtr: return *(ecs_uptr_t*)ptr != 0; - case EcsOpF32: return ECS_NEQZERO(*(ecs_f32_t*)ptr); - case EcsOpF64: return ECS_NEQZERO(*(ecs_f64_t*)ptr); - case EcsOpString: return *(const char**)ptr != NULL; - case EcsOpEnum: return *(ecs_i32_t*)ptr != 0; - 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 EcsOpBool: return *(const ecs_bool_t*)ptr; + case EcsOpI8: return *(const ecs_i8_t*)ptr != 0; + case EcsOpU8: return *(const ecs_u8_t*)ptr != 0; + case EcsOpChar: return *(const ecs_char_t*)ptr != 0; + case EcsOpByte: return *(const ecs_u8_t*)ptr != 0; + case EcsOpI16: return *(const ecs_i16_t*)ptr != 0; + case EcsOpU16: return *(const ecs_u16_t*)ptr != 0; + case EcsOpI32: return *(const ecs_i32_t*)ptr != 0; + case EcsOpU32: return *(const ecs_u32_t*)ptr != 0; + case EcsOpI64: return *(const ecs_i64_t*)ptr != 0; + case EcsOpU64: return *(const ecs_u64_t*)ptr != 0; + case EcsOpIPtr: return *(const ecs_iptr_t*)ptr != 0; + case EcsOpUPtr: return *(const ecs_uptr_t*)ptr != 0; + case EcsOpF32: return ECS_NEQZERO(*(const ecs_f32_t*)ptr); + case EcsOpF64: return ECS_NEQZERO(*(const ecs_f64_t*)ptr); + case EcsOpString: return *(const char* const *)ptr != NULL; + case EcsOpEnum: return *(const ecs_i32_t*)ptr != 0; + case EcsOpBitmask: return *(const ecs_u32_t*)ptr != 0; + case EcsOpEntity: return *(const ecs_entity_t*)ptr != 0; + case EcsOpId: return *(const 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: @@ -1831,13 +1896,25 @@ char ecs_meta_get_char( { 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); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { case EcsOpChar: - return *(ecs_char_t*)ptr != 0; + return *(const ecs_char_t*)ptr; + 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: @@ -1874,7 +1951,10 @@ int64_t ecs_meta_get_int( { 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); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { case EcsOpBool: return *(const ecs_bool_t*)ptr; case EcsOpI8: return *(const ecs_i8_t*)ptr; @@ -1891,7 +1971,7 @@ int64_t ecs_meta_get_int( case EcsOpUPtr: return flecs_uto(int64_t, *(const ecs_uptr_t*)ptr); case EcsOpF32: return (int64_t)*(const ecs_f32_t*)ptr; case EcsOpF64: return (int64_t)*(const ecs_f64_t*)ptr; - case EcsOpString: return atoi(*(const char**)ptr); + case EcsOpString: return atoi(*(const char* const *)ptr); case EcsOpEnum: return *(const ecs_i32_t*)ptr; case EcsOpBitmask: return *(const ecs_u32_t*)ptr; case EcsOpEntity: @@ -1902,9 +1982,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: @@ -1924,31 +2013,43 @@ uint64_t ecs_meta_get_uint( { 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); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { - case EcsOpBool: return *(ecs_bool_t*)ptr; + case EcsOpBool: return *(const ecs_bool_t*)ptr; case EcsOpI8: return flecs_ito(uint64_t, *(const ecs_i8_t*)ptr); - case EcsOpU8: return *(ecs_u8_t*)ptr; + case EcsOpU8: return *(const ecs_u8_t*)ptr; case EcsOpChar: return flecs_ito(uint64_t, *(const ecs_char_t*)ptr); case EcsOpByte: return flecs_ito(uint64_t, *(const ecs_u8_t*)ptr); case EcsOpI16: return flecs_ito(uint64_t, *(const ecs_i16_t*)ptr); - case EcsOpU16: return *(ecs_u16_t*)ptr; + case EcsOpU16: return *(const ecs_u16_t*)ptr; case EcsOpI32: return flecs_ito(uint64_t, *(const ecs_i32_t*)ptr); - case EcsOpU32: return *(ecs_u32_t*)ptr; + case EcsOpU32: return *(const ecs_u32_t*)ptr; case EcsOpI64: return flecs_ito(uint64_t, *(const ecs_i64_t*)ptr); - case EcsOpU64: return *(ecs_u64_t*)ptr; + case EcsOpU64: return *(const ecs_u64_t*)ptr; case EcsOpIPtr: return flecs_ito(uint64_t, *(const ecs_i64_t*)ptr); - case EcsOpUPtr: return *(ecs_uptr_t*)ptr; + case EcsOpUPtr: return *(const ecs_uptr_t*)ptr; case EcsOpF32: return flecs_ito(uint64_t, *(const ecs_f32_t*)ptr); case EcsOpF64: return flecs_ito(uint64_t, *(const ecs_f64_t*)ptr); - case EcsOpString: return flecs_ito(uint64_t, atoi(*(const char**)ptr)); + case EcsOpString: return flecs_ito(uint64_t, atoi(*(const char* const *)ptr)); case EcsOpEnum: return flecs_ito(uint64_t, *(const ecs_i32_t*)ptr); 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: @@ -2005,7 +2106,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: @@ -2017,31 +2118,22 @@ 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; + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); } - 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; + 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; + } + return flecs_meta_to_float(op->kind, ptr); } const char* ecs_meta_get_string( @@ -2049,25 +2141,18 @@ const char* ecs_meta_get_string( { 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); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { - case EcsOpString: return *(const char**)ptr; + case EcsOpString: return *(const char* const*)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 */ } @@ -2110,12 +2195,24 @@ ecs_entity_t ecs_meta_get_entity( { 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); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { - case EcsOpEntity: return *(ecs_entity_t*)ptr; + case EcsOpEntity: return *(const 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: @@ -2146,18 +2243,30 @@ 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); ecs_meta_type_op_t *op = flecs_meta_cursor_get_op(scope); - void *ptr = flecs_meta_cursor_get_ptr(cursor->world, scope); + const void *ptr = flecs_meta_cursor_get_read_ptr(cursor->world, scope); + if(!ptr) { + ecs_throw(ECS_OUT_OF_RANGE, "cannot find element"); + } switch(op->kind) { - case EcsOpEntity: return *(ecs_id_t*)ptr; /* Entities are valid ids */ - case EcsOpId: return *(ecs_id_t*)ptr; + case EcsOpEntity: return *(const ecs_id_t*)ptr; /* Entities are valid ids */ + case EcsOpId: return *(const 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: diff --git a/src/addons/meta/definitions.c b/src/addons/meta/definitions.c index ce1101123..49a860264 100644 --- a/src/addons/meta/definitions.c +++ b/src/addons/meta/definitions.c @@ -37,6 +37,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( @@ -76,7 +81,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, } }); diff --git a/src/addons/metrics.c b/src/addons/metrics.c index ec66b59e7..599e1f988 100644 --- a/src/addons/metrics.c +++ b/src/addons/metrics.c @@ -484,7 +484,7 @@ int flecs_member_metric_init( id = desc->id; member_type = ecs_meta_get_type(&cur); - offset = (uintptr_t)ecs_meta_get_ptr(&cur); + offset = (uintptr_t)ecs_meta_get_write_ptr(&cur); member = ecs_meta_get_member_id(&cur); } else { const EcsMember *m = ecs_get(world, desc->member, EcsMember); diff --git a/src/addons/script/expr/visit_type.c b/src/addons/script/expr/visit_type.c index c45037be2..a2ff1dca1 100644 --- a/src/addons/script/expr/visit_type.c +++ b/src/addons/script/expr/visit_type.c @@ -882,7 +882,7 @@ int flecs_expr_initializer_visit_type( } if (!is_opaque) { - elem->offset = (uintptr_t)ecs_meta_get_ptr(cur); + elem->offset = (uintptr_t)ecs_meta_get_write_ptr(cur); } } @@ -1429,7 +1429,7 @@ int flecs_expr_member_visit_type( const EcsMember *m = ecs_get(world, ecs_meta_get_member_id(cur), EcsMember); ecs_assert(m != NULL, ECS_INTERNAL_ERROR, NULL); #endif - node->offset = (uintptr_t)ecs_meta_get_ptr(cur); + node->offset = (uintptr_t)ecs_meta_get_write_ptr(cur); return 0; error: diff --git a/test/meta/project.json b/test/meta/project.json index 834fca117..b30b9c486 100644 --- a/test/meta/project.json +++ b/test/meta/project.json @@ -449,14 +449,14 @@ "array_move_primitive", "array_move_struct", "array_move_out_of_range", - "opaque_set_bool", - "opaque_set_char", - "opaque_set_int", - "opaque_set_uint", - "opaque_set_float", + "opaque_get_set_bool", + "opaque_get_set_char", + "opaque_get_set_int", + "opaque_get_set_uint", + "opaque_get_set_float", "opaque_get_set_string", - "opaque_set_entity", - "opaque_set_id", + "opaque_get_set_entity", + "opaque_get_set_id", "opaque_set_int_vec", "opaque_set_int_vec_empty", "opaque_set_int_vec_resize_smaller", diff --git a/test/meta/src/Cursor.c b/test/meta/src/Cursor.c index 629efc341..5a3e6b39f 100644 --- a/test/meta/src/Cursor.c +++ b/test/meta/src/Cursor.c @@ -8,7 +8,9 @@ void Cursor_set_bool(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_bool_t), &value); test_ok( ecs_meta_set_bool(&cur, true) ); + test_bool(ecs_meta_get_bool(&cur), true); test_bool(value, true); + ecs_fini(world); } @@ -32,9 +34,10 @@ void Cursor_set_char(void) { ecs_char_t value = 10; ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_char_t), &value); - test_ok( ecs_meta_set_int(&cur, 20) ); + test_ok( ecs_meta_set_char(&cur, 'a') ); - test_int(value, 20); + test_int(ecs_meta_get_char(&cur), 'a'); + test_int(value, 'a'); ecs_fini(world); } @@ -47,6 +50,7 @@ void Cursor_set_i8(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_i8_t), &value); test_ok( ecs_meta_set_int(&cur, 20) ); + test_int(ecs_meta_get_int(&cur), 20); test_int(value, 20); ecs_fini(world); @@ -60,6 +64,7 @@ void Cursor_set_i16(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_i16_t), &value); test_ok( ecs_meta_set_int(&cur, 20) ); + test_int(ecs_meta_get_int(&cur), 20); test_int(value, 20); ecs_fini(world); @@ -73,6 +78,7 @@ void Cursor_set_i32(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_i32_t), &value); test_ok( ecs_meta_set_int(&cur, 20) ); + test_int(ecs_meta_get_int(&cur), 20); test_int(value, 20); ecs_fini(world); @@ -86,6 +92,7 @@ void Cursor_set_i64(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_i64_t), &value); test_ok( ecs_meta_set_int(&cur, 20) ); + test_int(ecs_meta_get_int(&cur), 20); test_int(value, 20); ecs_fini(world); @@ -99,6 +106,7 @@ void Cursor_set_iptr(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_iptr_t), &value); test_ok( ecs_meta_set_int(&cur, 20) ); + test_int(ecs_meta_get_int(&cur), 20); test_int(value, 20); ecs_fini(world); @@ -112,6 +120,7 @@ void Cursor_set_u8(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_u8_t), &value); test_ok( ecs_meta_set_uint(&cur, 20) ); + test_uint(ecs_meta_get_uint(&cur), 20); test_uint(value, 20); ecs_fini(world); @@ -125,6 +134,7 @@ void Cursor_set_u16(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_u8_t), &value); test_ok( ecs_meta_set_uint(&cur, 20) ); + test_uint(ecs_meta_get_uint(&cur), 20); test_uint(value, 20); ecs_fini(world); @@ -138,6 +148,7 @@ void Cursor_set_u32(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_u32_t), &value); test_ok( ecs_meta_set_uint(&cur, 20) ); + test_uint(ecs_meta_get_uint(&cur), 20); test_uint(value, 20); ecs_fini(world); @@ -150,6 +161,7 @@ void Cursor_set_u64(void) { ecs_u64_t value = 10; ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_u64_t), &value); test_ok( ecs_meta_set_uint(&cur, 20) ); + test_uint(ecs_meta_get_uint(&cur), 20); test_uint(value, 20); } @@ -157,6 +169,7 @@ void Cursor_set_u64(void) { ecs_u64_t value = 10; ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_u64_t), &value); test_ok( ecs_meta_set_uint(&cur, 2366700781656087864) ); + test_uint(ecs_meta_get_uint(&cur), 2366700781656087864); test_uint(value, 2366700781656087864); } @@ -170,7 +183,8 @@ void Cursor_set_uptr(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_uptr_t), &value); test_ok( ecs_meta_set_uint(&cur, 20) ); - + + test_uint(ecs_meta_get_uint(&cur), 20); test_uint(value, 20); ecs_fini(world); @@ -184,6 +198,7 @@ void Cursor_set_float(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_f32_t), &value); test_ok( ecs_meta_set_float(&cur, 20.5) ); + test_flt(ecs_meta_get_float(&cur), 20.5); test_flt(value, 20.5); ecs_fini(world); @@ -197,6 +212,7 @@ void Cursor_set_double(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_f64_t), &value); test_ok( ecs_meta_set_float(&cur, 20.5) ); + test_flt(ecs_meta_get_float(&cur), 20.5); test_flt(value, 20.5); ecs_fini(world); @@ -210,6 +226,7 @@ void Cursor_set_string(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_string_t), &value); test_ok( ecs_meta_set_string(&cur, "HelloWorld") ); + test_str(ecs_meta_get_string(&cur), "HelloWorld"); test_str(value, "HelloWorld"); ecs_os_free(value); @@ -238,6 +255,7 @@ void Cursor_set_string_to_null(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_string_t), &value); test_ok( ecs_meta_set_null(&cur) ); + test_str(ecs_meta_get_string(&cur), NULL); test_str(value, NULL); ecs_os_free(value); @@ -252,6 +270,7 @@ void Cursor_set_entity(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_entity_t), &value); test_ok( ecs_meta_set_entity(&cur, EcsFlecs) ); + test_uint(ecs_meta_get_entity(&cur), EcsFlecs); test_uint(value, EcsFlecs); ecs_fini(world); @@ -265,6 +284,7 @@ void Cursor_set_entity_to_number(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_entity_t), &value); test_ok( ecs_meta_set_uint(&cur, 500) ); + test_uint(ecs_meta_get_entity(&cur), 500); test_uint(value, 500); ecs_fini(world); @@ -278,6 +298,7 @@ void Cursor_set_entity_to_0(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_entity_t), &value); test_ok( ecs_meta_set_uint(&cur, 0) ); + test_uint(ecs_meta_get_entity(&cur), 0); test_uint(value, 0); ecs_fini(world); @@ -289,8 +310,9 @@ void Cursor_set_id(void) { ecs_id_t value = 0; ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_id_t), &value); - test_ok( ecs_meta_set_uint(&cur, 500) ); + test_ok( ecs_meta_set_id(&cur, 500) ); + test_uint(ecs_meta_get_id(&cur), 500); test_uint(value, 500); ecs_fini(world); @@ -304,6 +326,7 @@ void Cursor_set_id_to_number(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_id_t), &value); test_ok( ecs_meta_set_uint(&cur, 500) ); + test_uint(ecs_meta_get_id(&cur), 500); test_uint(value, 500); ecs_fini(world); @@ -317,6 +340,7 @@ void Cursor_set_id_to_0(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_id_t), &value); test_ok( ecs_meta_set_uint(&cur, 0) ); + test_uint(ecs_meta_get_id(&cur), 0); test_uint(value, 0); ecs_fini(world); @@ -342,6 +366,7 @@ void Cursor_set_enum(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, t, &value); test_ok( ecs_meta_set_int(&cur, Green) ); + test_uint(ecs_meta_get_int(&cur), Green); test_int(value, Green); ecs_fini(world); @@ -365,6 +390,7 @@ void Cursor_set_bitmask(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, t, &value); test_ok( ecs_meta_set_uint(&cur, Bacon | Lettuce) ); + test_int(ecs_meta_get_uint(&cur), Bacon | Lettuce); test_uint(value, Bacon | Lettuce); ecs_fini(world); @@ -378,6 +404,7 @@ void Cursor_set_signed_as_unsigned(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_i32_t), &value); test_ok( ecs_meta_set_uint(&cur, 10) ); + test_int(ecs_meta_get_int(&cur), 10); test_int(value, 10); ecs_fini(world); @@ -391,7 +418,8 @@ void Cursor_set_unsigned_as_signed(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_u32_t), &value); test_ok( ecs_meta_set_int(&cur, 10) ); - test_int(value, 10); + test_uint(ecs_meta_get_uint(&cur), 10); + test_uint(value, 10); ecs_fini(world); } @@ -405,6 +433,7 @@ void Cursor_set_signed_as_unsigned_out_of_range(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_i8_t), &value); test_fail( ecs_meta_set_uint(&cur, 128) ); + test_int(ecs_meta_get_int(&cur), 0); test_int(value, 0); ecs_fini(world); @@ -419,6 +448,7 @@ void Cursor_set_unsigned_as_signed_out_of_range(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_u32_t), &value); test_fail( ecs_meta_set_int(&cur, -10) ); + test_int(ecs_meta_get_int(&cur), 0); test_int(value, 0); ecs_fini(world); @@ -433,6 +463,7 @@ void Cursor_set_string_to_null_as_signed(void) { test_ok( ecs_meta_set_int(&cur, 0) ); test_str(value, "0"); + test_str(ecs_meta_get_string(&cur), "0"); ecs_os_free(value); ecs_fini(world); @@ -447,6 +478,7 @@ void Cursor_set_string_to_null_as_unsigned(void) { test_ok( ecs_meta_set_uint(&cur, 0) ); test_str(value, "0"); + test_str(ecs_meta_get_string(&cur), "0"); ecs_os_free(value); ecs_fini(world); @@ -641,6 +673,7 @@ void Cursor_set_entity_as_signed(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_entity_t), &value); test_ok( ecs_meta_set_int(&cur, (int64_t)e) ); + test_uint(ecs_meta_get_uint(&cur), e); test_uint(value, e); ecs_fini(world); @@ -655,6 +688,7 @@ void Cursor_set_entity_as_unsigned(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_entity_t), &value); test_ok( ecs_meta_set_uint(&cur, e) ); + test_uint(ecs_meta_get_uint(&cur), e); test_uint(value, e); ecs_fini(world); @@ -669,6 +703,7 @@ void Cursor_set_entity_as_signed_out_of_range(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_entity_t), &value); test_fail( ecs_meta_set_int(&cur, -10) ); + test_int(ecs_meta_get_uint(&cur), 0); test_uint(value, 0); ecs_fini(world); @@ -683,6 +718,7 @@ void Cursor_set_id_as_signed(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_id_t), &value); test_ok( ecs_meta_set_int(&cur, (int64_t)e) ); + test_uint(ecs_meta_get_id(&cur), e); test_uint(value, e); ecs_fini(world); @@ -697,6 +733,7 @@ void Cursor_set_id_as_unsigned(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_id_t), &value); test_ok( ecs_meta_set_uint(&cur, e) ); + test_uint(ecs_meta_get_id(&cur), e); test_uint(value, e); ecs_fini(world); @@ -711,6 +748,7 @@ void Cursor_set_id_as_signed_out_of_range(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_id_t), &value); test_fail( ecs_meta_set_int(&cur, -10) ); + test_uint(ecs_meta_get_id(&cur), 0); test_uint(value, 0); ecs_fini(world); @@ -729,6 +767,7 @@ void Cursor_set_str_to_bool(void) { cur = ecs_meta_cursor(world, ecs_id(ecs_bool_t), &value); test_ok( ecs_meta_set_string(&cur, "false") ); + test_bool(ecs_meta_get_bool(&cur), false); test_bool(value, false); ecs_fini(world); @@ -740,9 +779,9 @@ void Cursor_set_str_to_char(void) { ecs_char_t value = false; ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_char_t), &value); - test_ok( ecs_meta_set_string(&cur, "10") ); + test_ok( ecs_meta_set_string(&cur, "abc") ); - test_bool(value, 10); + test_int(value, 'a'); ecs_fini(world); } @@ -753,7 +792,7 @@ void Cursor_set_str_literal_to_char(void) { ecs_char_t value = false; ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_char_t), &value); - test_ok( ecs_meta_set_string_literal(&cur, "\"a\"") ); + test_ok( ecs_meta_set_string_literal(&cur, "\"abc\"") ); test_int(value, 'a'); @@ -768,6 +807,7 @@ void Cursor_set_str_to_i8(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_i8_t), &value); test_ok( ecs_meta_set_string(&cur, "20") ); + test_int(ecs_meta_get_int(&cur), 20); test_int(value, 20); ecs_fini(world); @@ -781,6 +821,7 @@ void Cursor_set_str_to_i16(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_i16_t), &value); test_ok( ecs_meta_set_string(&cur, "20") ); + test_int(ecs_meta_get_int(&cur), 20); test_int(value, 20); ecs_fini(world); @@ -794,6 +835,7 @@ void Cursor_set_str_to_i32(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_i32_t), &value); test_ok( ecs_meta_set_string(&cur, "20") ); + test_int(ecs_meta_get_int(&cur), 20); test_int(value, 20); ecs_fini(world); @@ -806,6 +848,7 @@ void Cursor_set_str_to_i64(void) { ecs_i64_t value = 10; ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_i64_t), &value); test_ok( ecs_meta_set_string(&cur, "20") ); + test_int(ecs_meta_get_int(&cur), 20); test_int(value, 20); } @@ -813,6 +856,7 @@ void Cursor_set_str_to_i64(void) { ecs_i64_t value = 10; ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_i64_t), &value); test_ok( ecs_meta_set_string(&cur, "2366700781656087864") ); + test_int(ecs_meta_get_int(&cur), 2366700781656087864); test_int(value, 2366700781656087864); } @@ -826,6 +870,7 @@ void Cursor_set_str_to_u64(void) { ecs_u64_t value = 10; ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_u64_t), &value); test_ok( ecs_meta_set_string(&cur, "20") ); + test_uint(ecs_meta_get_uint(&cur), 20); test_uint(value, 20); } @@ -833,6 +878,7 @@ void Cursor_set_str_to_u64(void) { ecs_u64_t value = 10; ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_u64_t), &value); test_ok( ecs_meta_set_string(&cur, "2366700781656087864") ); + test_uint(ecs_meta_get_uint(&cur), 2366700781656087864); test_uint(value, 2366700781656087864); } @@ -847,6 +893,7 @@ void Cursor_set_str_to_f32(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_f32_t), &value); test_ok( ecs_meta_set_string(&cur, "20.5") ); + test_flt(ecs_meta_get_float(&cur), 20.5); test_flt(value, 20.5); ecs_fini(world); @@ -860,6 +907,7 @@ void Cursor_set_str_to_f64(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_f64_t), &value); test_ok( ecs_meta_set_string(&cur, "20.5") ); + test_flt(ecs_meta_get_float(&cur), 20.5); test_flt(value, 20.5); ecs_fini(world); @@ -873,6 +921,7 @@ void Cursor_set_str_to_entity(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_entity_t), &value); test_ok( ecs_meta_set_string(&cur, "flecs.core") ); + test_uint(ecs_meta_get_entity(&cur), EcsFlecsCore); test_uint(value, EcsFlecsCore); ecs_fini(world); @@ -886,6 +935,7 @@ void Cursor_set_str_to_id(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_id_t), &value); test_ok( ecs_meta_set_string(&cur, "flecs.core") ); + test_uint(ecs_meta_get_id(&cur), EcsFlecsCore); test_uint(value, EcsFlecsCore); ecs_fini(world); @@ -901,6 +951,7 @@ void Cursor_set_str_to_invalid_bool(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_bool_t), &value); test_fail( ecs_meta_set_string(&cur, "foo") ); + test_bool(ecs_meta_get_bool(&cur), false); test_bool(value, false); ecs_fini(world); @@ -916,6 +967,7 @@ void Cursor_set_str_to_invalid_entity(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_entity_t), &value); test_fail( ecs_meta_set_string(&cur, "flops.core") ); + test_uint(ecs_meta_get_entity(&cur), 0); test_uint(value, 0); ecs_fini(world); @@ -931,6 +983,7 @@ void Cursor_set_str_to_invalid_id(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_id_t), &value); test_fail( ecs_meta_set_string(&cur, "flops.core") ); + test_uint(ecs_meta_get_id(&cur), 0); test_uint(value, 0); ecs_fini(world); @@ -958,6 +1011,7 @@ void Cursor_struct_set_i32(void) { test_ok( ecs_meta_push(&cur) ); test_ok( ecs_meta_set_int(&cur, 10) ); + test_int(ecs_meta_get_int(&cur), 10); test_int(value.x, 10); ecs_fini(world); @@ -2988,8 +3042,12 @@ typedef const char* const_string_t; \ static void t##_set(void *ptr, t value) { \ ((Opaque_##t*)ptr)->value = value; \ + } \ + static t t##_get(const void *ptr) { \ + return ((Opaque_##t*)ptr)->value; \ } + OpaqueType(bool) OpaqueType(char) OpaqueType(int64_t) @@ -3009,11 +3067,19 @@ static void Opaque_entity_set(void *ptr, ecs_world_t *world, ecs_entity_t value) ((Opaque_entity*)ptr)->value = value; } +static ecs_entity_t Opaque_entity_get(const void *ptr, const ecs_world_t *world) { + return ((Opaque_entity*)ptr)->value; +} + static void Opaque_id_set(void *ptr, ecs_world_t *world, ecs_id_t value) { ((Opaque_id*)ptr)->value = value; } -void Cursor_opaque_set_bool(void) { +static ecs_entity_t Opaque_id_get(const void *ptr, const ecs_world_t *world) { + return ((Opaque_id*)ptr)->value; +} + +void Cursor_opaque_get_set_bool(void) { ecs_world_t *world = ecs_init(); ECS_COMPONENT(world, Opaque_bool); @@ -3021,7 +3087,8 @@ void Cursor_opaque_set_bool(void) { ecs_opaque(world, { .entity = ecs_id(Opaque_bool), .type.as_type = ecs_id(ecs_bool_t), - .type.assign_bool = bool_set + .type.assign_bool = bool_set, + .type.get_bool = bool_get }); Opaque_bool v = { false }; @@ -3029,13 +3096,15 @@ void Cursor_opaque_set_bool(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(Opaque_bool), &v); test_int(0, ecs_meta_set_bool(&cur, true)); test_bool(v.value, true); + test_bool(ecs_meta_get_bool(&cur), true); test_int(0, ecs_meta_set_bool(&cur, false)); test_bool(v.value, false); + test_bool(ecs_meta_get_bool(&cur), false); ecs_fini(world); } -void Cursor_opaque_set_char(void) { +void Cursor_opaque_get_set_char(void) { ecs_world_t *world = ecs_init(); ECS_COMPONENT(world, Opaque_char); @@ -3043,7 +3112,8 @@ void Cursor_opaque_set_char(void) { ecs_opaque(world, { .entity = ecs_id(Opaque_char), .type.as_type = ecs_id(ecs_char_t), - .type.assign_char = char_set + .type.assign_char = char_set, + .type.get_char = char_get }); Opaque_char v = { 0 }; @@ -3051,13 +3121,15 @@ void Cursor_opaque_set_char(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(Opaque_char), &v); test_int(0, ecs_meta_set_char(&cur, 'a')); test_int(v.value, 'a'); + test_int(ecs_meta_get_char(&cur), 'a'); test_int(0, ecs_meta_set_char(&cur, 'A')); test_int(v.value, 'A'); + test_int(ecs_meta_get_char(&cur), 'A'); ecs_fini(world); } -void Cursor_opaque_set_int(void) { +void Cursor_opaque_get_set_int(void) { ecs_world_t *world = ecs_init(); ECS_COMPONENT(world, Opaque_int64_t); @@ -3065,7 +3137,8 @@ void Cursor_opaque_set_int(void) { ecs_opaque(world, { .entity = ecs_id(Opaque_int64_t), .type.as_type = ecs_id(ecs_i64_t), - .type.assign_int = int64_t_set + .type.assign_int = int64_t_set, + .type.get_int = int64_t_get }); Opaque_int64_t v = { 0 }; @@ -3073,13 +3146,15 @@ void Cursor_opaque_set_int(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(Opaque_int64_t), &v); test_int(0, ecs_meta_set_int(&cur, 10)); test_int(v.value, 10); + test_int(ecs_meta_get_int(&cur), 10); test_int(0, ecs_meta_set_int(&cur, -10)); test_int(v.value, -10); + test_int(ecs_meta_get_int(&cur), -10); ecs_fini(world); } -void Cursor_opaque_set_uint(void) { +void Cursor_opaque_get_set_uint(void) { ecs_world_t *world = ecs_init(); ECS_COMPONENT(world, Opaque_uint64_t); @@ -3087,7 +3162,8 @@ void Cursor_opaque_set_uint(void) { ecs_opaque(world, { .entity = ecs_id(Opaque_uint64_t), .type.as_type = ecs_id(ecs_i64_t), - .type.assign_uint = uint64_t_set + .type.assign_uint = uint64_t_set, + .type.get_uint = uint64_t_get }); Opaque_uint64_t v = { 0 }; @@ -3095,13 +3171,15 @@ void Cursor_opaque_set_uint(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(Opaque_uint64_t), &v); test_int(0, ecs_meta_set_uint(&cur, 10)); test_int(v.value, 10); + test_int(ecs_meta_get_uint(&cur), 10); test_int(0, ecs_meta_set_uint(&cur, 20)); test_int(v.value, 20); + test_int(ecs_meta_get_uint(&cur), 20); ecs_fini(world); } -void Cursor_opaque_set_float(void) { +void Cursor_opaque_get_set_float(void) { ecs_world_t *world = ecs_init(); ECS_COMPONENT(world, Opaque_double); @@ -3109,7 +3187,8 @@ void Cursor_opaque_set_float(void) { ecs_opaque(world, { .entity = ecs_id(Opaque_double), .type.as_type = ecs_id(ecs_f64_t), - .type.assign_float = double_set + .type.assign_float = double_set, + .type.get_float = double_get }); Opaque_double v = { 0 }; @@ -3117,19 +3196,14 @@ void Cursor_opaque_set_float(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(Opaque_double), &v); test_int(0, ecs_meta_set_float(&cur, 10.5)); test_flt(v.value, 10.5); + test_flt(ecs_meta_get_float(&cur), 10.5); test_int(0, ecs_meta_set_float(&cur, 20.5)); test_flt(v.value, 20.5); + test_flt(ecs_meta_get_float(&cur), 20.5); ecs_fini(world); } -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(); @@ -3139,7 +3213,7 @@ void Cursor_opaque_get_set_string(void) { .entity = ecs_id(Opaque_const_string_t), .type.as_type = ecs_id(ecs_string_t), .type.assign_string = const_string_t_set, - .type.serialize = const_string_t_serialize + .type.get_string = const_string_t_get }); Opaque_const_string_t v = { 0 }; @@ -3154,7 +3228,7 @@ void Cursor_opaque_get_set_string(void) { ecs_fini(world); } -void Cursor_opaque_set_entity(void) { +void Cursor_opaque_get_set_entity(void) { ecs_world_t *world = ecs_init(); ECS_COMPONENT(world, Opaque_entity); @@ -3162,7 +3236,8 @@ void Cursor_opaque_set_entity(void) { ecs_opaque(world, { .entity = ecs_id(Opaque_entity), .type.as_type = ecs_id(ecs_entity_t), - .type.assign_entity = Opaque_entity_set + .type.assign_entity = Opaque_entity_set, + .type.get_entity = Opaque_entity_get }); Opaque_entity v = { 0 }; @@ -3172,13 +3247,15 @@ void Cursor_opaque_set_entity(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(Opaque_entity), &v); test_int(0, ecs_meta_set_entity(&cur, e1)); test_uint(v.value, e1); + test_uint(ecs_meta_get_entity(&cur), e1); test_int(0, ecs_meta_set_entity(&cur, e2)); test_uint(v.value, e2); + test_uint(ecs_meta_get_entity(&cur), e2); ecs_fini(world); } -void Cursor_opaque_set_id(void) { +void Cursor_opaque_get_set_id(void) { ecs_world_t *world = ecs_init(); ECS_COMPONENT(world, Opaque_id); @@ -3186,7 +3263,8 @@ void Cursor_opaque_set_id(void) { ecs_opaque(world, { .entity = ecs_id(Opaque_id), .type.as_type = ecs_id(ecs_id_t), - .type.assign_id = Opaque_id_set + .type.assign_id = Opaque_id_set, + .type.get_id = Opaque_id_get }); Opaque_id v = { 0 }; @@ -3196,8 +3274,10 @@ void Cursor_opaque_set_id(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(Opaque_id), &v); test_int(0, ecs_meta_set_id(&cur, e1)); test_uint(v.value, e1); + test_uint(ecs_meta_get_id(&cur), e1); test_int(0, ecs_meta_set_id(&cur, e2)); test_uint(v.value, e2); + test_uint(ecs_meta_get_id(&cur), e2); ecs_fini(world); } @@ -3221,6 +3301,14 @@ static void* IntVec_ensure(void *ptr, size_t index) { return &data->array[index]; } +static const void* IntVec_get(const void *ptr, size_t index) { + const IntVec *data = ptr; + if (index >= data->count) { + return NULL; + } + return &data->array[index]; +} + static void IntVec_resize(void *ptr, size_t size) { IntVec *data = ptr; if (data->count != size) { @@ -3243,6 +3331,7 @@ void Cursor_opaque_set_int_vec(void) { .entity = ecs_id(IntVec), .type.as_type = ecs_vector(world, { .type = ecs_id(ecs_i32_t) }), .type.ensure_element = IntVec_ensure, + .type.get_element = IntVec_get, .type.count = IntVec_count, .type.resize = IntVec_resize }); @@ -3263,6 +3352,18 @@ void Cursor_opaque_set_int_vec(void) { test_int(v.array[1], 20); test_int(v.array[2], 30); + cur = ecs_meta_cursor(world, ecs_id(IntVec), &v); + test_int(0, ecs_meta_push(&cur)); + test_int(ecs_meta_get_int(&cur), 10); + test_int(0, ecs_meta_next(&cur)); + test_int(ecs_meta_get_int(&cur), 20); + test_int(0, ecs_meta_next(&cur)); + test_int(ecs_meta_get_int(&cur), 30); + test_assert(ecs_meta_get_read_ptr(&cur) != NULL); /* still points to a valid item */ + + test_int(0, ecs_meta_next(&cur)); + test_assert(ecs_meta_get_read_ptr(&cur) == NULL); /* now we are out of bounds */ + ecs_os_free(v.array); ecs_fini(world); @@ -3516,7 +3617,7 @@ typedef struct { int32_t y; } OpaqueStruct; -static void* OpaqueStruct_member(void *ptr, const char *member) { +static void* OpaqueStruct_ensure_member(void *ptr, const char *member) { OpaqueStruct *data = ptr; if (!strcmp(member, "x")) { return &data->x; @@ -3527,6 +3628,17 @@ static void* OpaqueStruct_member(void *ptr, const char *member) { } } +static const void* OpaqueStruct_get_member(const void *ptr, const char *member) { + const OpaqueStruct *data = ptr; + if (!strcmp(member, "x")) { + return &data->x; + } else if (!strcmp(member, "y")) { + return &data->y; + } else { + return NULL; + } +} + void Cursor_opaque_set_struct(void) { ecs_world_t *world = ecs_init(); @@ -3540,7 +3652,8 @@ void Cursor_opaque_set_struct(void) { {"y", .type = ecs_id(ecs_i32_t)} } }), - .type.ensure_member = OpaqueStruct_member + .type.ensure_member = OpaqueStruct_ensure_member, + .type.get_member = OpaqueStruct_get_member }); OpaqueStruct v = { 0 }; @@ -3548,8 +3661,10 @@ void Cursor_opaque_set_struct(void) { test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "x")); test_int(0, ecs_meta_set_int(&cur, 10)); + test_int(ecs_meta_get_int(&cur), 10); test_int(0, ecs_meta_member(&cur, "y")); test_int(0, ecs_meta_set_int(&cur, 20)); + test_int(ecs_meta_get_int(&cur), 20); test_int(0, ecs_meta_pop(&cur)); test_int(v.x, 10); test_int(v.y, 20); @@ -3558,8 +3673,10 @@ void Cursor_opaque_set_struct(void) { test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "y")); test_int(0, ecs_meta_set_int(&cur, 30)); + test_int(ecs_meta_get_int(&cur), 30); test_int(0, ecs_meta_member(&cur, "x")); test_int(0, ecs_meta_set_int(&cur, 40)); + test_int(ecs_meta_get_int(&cur), 40); test_int(0, ecs_meta_pop(&cur)); test_int(v.x, 40); test_int(v.y, 30); @@ -3574,7 +3691,7 @@ typedef struct { Position stop; } OpaqueNested; -static void* OpaqueNested_member(void *ptr, const char *member) { +static void* OpaqueNested_ensure_member(void *ptr, const char *member) { OpaqueNested *data = ptr; if (!strcmp(member, "start")) { return &data->start; @@ -3585,6 +3702,17 @@ static void* OpaqueNested_member(void *ptr, const char *member) { } } +static const void* OpaqueNested_get_member(const void *ptr, const char *member) { + const OpaqueNested *data = ptr; + if (!strcmp(member, "start")) { + return &data->start; + } else if (!strcmp(member, "stop")) { + return &data->stop; + } else { + return NULL; + } +} + void Cursor_opaque_set_nested_struct(void) { ecs_world_t *world = ecs_init(); @@ -3607,7 +3735,8 @@ void Cursor_opaque_set_nested_struct(void) { {"stop", .type = ecs_id(Position)} } }), - .type.ensure_member = OpaqueNested_member + .type.ensure_member = OpaqueNested_ensure_member, + .type.get_member = OpaqueNested_get_member, }); OpaqueNested v = { 0 }; @@ -3617,15 +3746,19 @@ void Cursor_opaque_set_nested_struct(void) { test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "x")); test_int(0, ecs_meta_set_int(&cur, 10)); + test_int(ecs_meta_get_int(&cur), 10); test_int(0, ecs_meta_member(&cur, "y")); test_int(0, ecs_meta_set_int(&cur, 20)); + test_int(ecs_meta_get_int(&cur), 20); test_int(0, ecs_meta_pop(&cur)); test_int(0, ecs_meta_member(&cur, "stop")); test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "x")); test_int(0, ecs_meta_set_int(&cur, 30)); + test_int(ecs_meta_get_int(&cur), 30); test_int(0, ecs_meta_member(&cur, "y")); test_int(0, ecs_meta_set_int(&cur, 40)); + test_int(ecs_meta_get_int(&cur), 40); test_int(0, ecs_meta_pop(&cur)); test_int(0, ecs_meta_pop(&cur)); @@ -3640,15 +3773,19 @@ void Cursor_opaque_set_nested_struct(void) { test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "y")); test_int(0, ecs_meta_set_int(&cur, 50)); + test_int(ecs_meta_get_int(&cur), 50); test_int(0, ecs_meta_member(&cur, "x")); test_int(0, ecs_meta_set_int(&cur, 60)); + test_int(ecs_meta_get_int(&cur), 60); test_int(0, ecs_meta_pop(&cur)); test_int(0, ecs_meta_member(&cur, "start")); test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "y")); test_int(0, ecs_meta_set_int(&cur, 70)); + test_int(ecs_meta_get_int(&cur), 70); test_int(0, ecs_meta_member(&cur, "x")); test_int(0, ecs_meta_set_int(&cur, 80)); + test_int(ecs_meta_get_int(&cur), 80); test_int(0, ecs_meta_pop(&cur)); test_int(0, ecs_meta_pop(&cur)); @@ -3667,7 +3804,7 @@ typedef struct { OpaqueStruct stop; } OpaqueNestedOpaque; -static void* OpaqueNestedOpaque_member(void *ptr, const char *member) { +static void* OpaqueNestedOpaque_ensure_member(void *ptr, const char *member) { OpaqueNestedOpaque *data = ptr; if (!strcmp(member, "start")) { return &data->start; @@ -3678,6 +3815,17 @@ static void* OpaqueNestedOpaque_member(void *ptr, const char *member) { } } +static const void* OpaqueNestedOpaque_get_member(const void *ptr, const char *member) { + const OpaqueNestedOpaque *data = ptr; + if (!strcmp(member, "start")) { + return &data->start; + } else if (!strcmp(member, "stop")) { + return &data->stop; + } else { + return NULL; + } +} + void Cursor_opaque_set_nested_opaque_struct(void) { ecs_world_t *world = ecs_init(); @@ -3692,7 +3840,8 @@ void Cursor_opaque_set_nested_opaque_struct(void) { {"y", .type = ecs_id(ecs_i32_t)} } }), - .type.ensure_member = OpaqueStruct_member + .type.ensure_member = OpaqueStruct_ensure_member, + .type.get_member = OpaqueStruct_get_member, }); ecs_opaque(world, { @@ -3703,7 +3852,8 @@ void Cursor_opaque_set_nested_opaque_struct(void) { {"stop", .type = ecs_id(OpaqueStruct)} } }), - .type.ensure_member = OpaqueNestedOpaque_member + .type.ensure_member = OpaqueNestedOpaque_ensure_member, + .type.get_member = OpaqueNestedOpaque_get_member }); OpaqueNestedOpaque v = { 0 }; @@ -3713,15 +3863,19 @@ void Cursor_opaque_set_nested_opaque_struct(void) { test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "x")); test_int(0, ecs_meta_set_int(&cur, 10)); + test_int(ecs_meta_get_int(&cur), 10); test_int(0, ecs_meta_member(&cur, "y")); test_int(0, ecs_meta_set_int(&cur, 20)); + test_int(ecs_meta_get_int(&cur), 20); test_int(0, ecs_meta_pop(&cur)); test_int(0, ecs_meta_member(&cur, "stop")); test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "x")); test_int(0, ecs_meta_set_int(&cur, 30)); + test_int(ecs_meta_get_int(&cur), 30); test_int(0, ecs_meta_member(&cur, "y")); test_int(0, ecs_meta_set_int(&cur, 40)); + test_int(ecs_meta_get_int(&cur), 40); test_int(0, ecs_meta_pop(&cur)); test_int(0, ecs_meta_pop(&cur)); @@ -3736,15 +3890,19 @@ void Cursor_opaque_set_nested_opaque_struct(void) { test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "y")); test_int(0, ecs_meta_set_int(&cur, 50)); + test_int(ecs_meta_get_int(&cur), 50); test_int(0, ecs_meta_member(&cur, "x")); test_int(0, ecs_meta_set_int(&cur, 60)); + test_int(ecs_meta_get_int(&cur), 60); test_int(0, ecs_meta_pop(&cur)); test_int(0, ecs_meta_member(&cur, "start")); test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "y")); test_int(0, ecs_meta_set_int(&cur, 70)); + test_int(ecs_meta_get_int(&cur), 70); test_int(0, ecs_meta_member(&cur, "x")); test_int(0, ecs_meta_set_int(&cur, 80)); + test_int(ecs_meta_get_int(&cur), 80); test_int(0, ecs_meta_pop(&cur)); test_int(0, ecs_meta_pop(&cur)); @@ -4145,7 +4303,8 @@ void Cursor_struct_w_2_opaque_structs(void) { {"y", .type = ecs_id(ecs_i32_t)} } }), - .type.ensure_member = OpaqueStruct_member + .type.ensure_member = OpaqueStruct_ensure_member, + .type.get_member = OpaqueStruct_get_member }); ecs_struct(world, { @@ -4326,7 +4485,8 @@ void Cursor_struct_w_3_opaque_structs(void) { {"y", .type = ecs_id(ecs_i32_t)} } }), - .type.ensure_member = OpaqueStruct_member + .type.ensure_member = OpaqueStruct_ensure_member, + .type.get_member = OpaqueStruct_get_member }); ecs_struct(world, { @@ -4527,7 +4687,7 @@ void Cursor_struct_w_3_opaque_arrays(void) { ecs_fini(world); } -static void* OpaqueStructIntVec_member(void *ptr, const char *member) { +static void* OpaqueStructIntVec_ensure_member(void *ptr, const char *member) { Struct_w_IntVec *data = ptr; if (!strcmp(member, "foo")) { return &data->foo; @@ -4538,6 +4698,17 @@ static void* OpaqueStructIntVec_member(void *ptr, const char *member) { } } +static const void* OpaqueStructIntVec_get_member(const void *ptr, const char *member) { + const Struct_w_IntVec *data = ptr; + if (!strcmp(member, "foo")) { + return &data->foo; + } else if (!strcmp(member, "bar")) { + return &data->bar; + } else { + return NULL; + } +} + void Cursor_opaque_struct_w_opaque_vec(void) { ecs_world_t *world = ecs_init(); @@ -4548,6 +4719,7 @@ void Cursor_opaque_struct_w_opaque_vec(void) { .entity = ecs_id(IntVec), .type.as_type = ecs_vector(world, { .type = ecs_id(ecs_i32_t) }), .type.ensure_element = IntVec_ensure, + .type.get_element = IntVec_get, .type.count = IntVec_count, .type.resize = IntVec_resize }); @@ -4562,7 +4734,8 @@ void Cursor_opaque_struct_w_opaque_vec(void) { ecs_opaque(world, { .entity = ecs_id(Struct_w_IntVec), .type.as_type = os, - .type.ensure_member = OpaqueStructIntVec_member, + .type.ensure_member = OpaqueStructIntVec_ensure_member, + .type.get_member = OpaqueStructIntVec_get_member }); Struct_w_IntVec v = {0}; @@ -4571,19 +4744,37 @@ void Cursor_opaque_struct_w_opaque_vec(void) { test_int(0, ecs_meta_member(&cur, "foo")); test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_set_int(&cur, 10)); + test_int(ecs_meta_get_int(&cur), 10); test_int(0, ecs_meta_next(&cur)); test_int(0, ecs_meta_set_int(&cur, 20)); + test_int(ecs_meta_get_int(&cur), 20); test_int(0, ecs_meta_next(&cur)); test_int(0, ecs_meta_set_int(&cur, 30)); + test_int(ecs_meta_get_int(&cur), 30); test_int(0, ecs_meta_pop(&cur)); + + const IntVec *vec = ecs_meta_get_read_ptr(&cur); + test_int(vec->array[0], 10); + test_int(vec->array[1], 20); + test_int(vec->array[2], 30); + test_int(0, ecs_meta_member(&cur, "bar")); test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_set_int(&cur, 40)); + test_int(ecs_meta_get_int(&cur), 40); test_int(0, ecs_meta_next(&cur)); test_int(0, ecs_meta_set_int(&cur, 50)); + test_int(ecs_meta_get_int(&cur), 50); test_int(0, ecs_meta_next(&cur)); test_int(0, ecs_meta_set_int(&cur, 60)); + test_int(ecs_meta_get_int(&cur), 60); test_int(0, ecs_meta_pop(&cur)); + + vec = ecs_meta_get_read_ptr(&cur); + test_int(vec->array[0], 40); + test_int(vec->array[1], 50); + test_int(vec->array[2], 60); + test_int(0, ecs_meta_pop(&cur)); test_int(v.foo.count, 3); @@ -4600,7 +4791,15 @@ void Cursor_opaque_struct_w_opaque_vec(void) { ecs_fini(world); } -static void* OpaqueStructElem_member(void *ptr, const char *member) { +static void* OpaqueStructElem_ensure_member(void *ptr, const char *member) { + if (!strcmp(member, "i")) { + return ptr; + } else { + return NULL; + } +} + +static const void* OpaqueStructElem_get_member(const void *ptr, const char *member) { if (!strcmp(member, "i")) { return ptr; } else { @@ -4626,13 +4825,15 @@ void Cursor_opaque_vec_w_opaque_elem(void) { .type.alignment = ECS_ALIGNOF(ecs_i32_t) }), .type.as_type = os, - .type.ensure_member = OpaqueStructElem_member, + .type.ensure_member = OpaqueStructElem_ensure_member, + .type.get_member = OpaqueStructElem_get_member, }); ecs_opaque(world, { .entity = ecs_id(IntVec), .type.as_type = ecs_vector(world, { .type = oelem }), .type.ensure_element = IntVec_ensure, + .type.get_element = IntVec_get, .type.count = IntVec_count, .type.resize = IntVec_resize }); @@ -4643,19 +4844,27 @@ void Cursor_opaque_vec_w_opaque_elem(void) { test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "i")); test_int(0, ecs_meta_set_int(&cur, 10)); + test_int(ecs_meta_get_int(&cur), 10); test_int(0, ecs_meta_pop(&cur)); test_int(0, ecs_meta_next(&cur)); test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "i")); test_int(0, ecs_meta_set_int(&cur, 20)); + test_int(ecs_meta_get_int(&cur), 20); test_int(0, ecs_meta_pop(&cur)); test_int(0, ecs_meta_next(&cur)); test_int(0, ecs_meta_push(&cur)); test_int(0, ecs_meta_member(&cur, "i")); test_int(0, ecs_meta_set_int(&cur, 30)); + test_int(ecs_meta_get_int(&cur), 30); test_int(0, ecs_meta_pop(&cur)); test_int(0, ecs_meta_pop(&cur)); + const IntVec *vec = ecs_meta_get_read_ptr(&cur); + test_int(vec->array[0], 10); + test_int(vec->array[1], 20); + test_int(vec->array[2], 30); + test_int(v.count, 3); test_int(v.array[0], 10); test_int(v.array[1], 20); diff --git a/test/meta/src/main.c b/test/meta/src/main.c index bde9d02b7..4353f52fb 100644 --- a/test/meta/src/main.c +++ b/test/meta/src/main.c @@ -424,14 +424,14 @@ void Cursor_array_struct_3(void); void Cursor_array_move_primitive(void); void Cursor_array_move_struct(void); void Cursor_array_move_out_of_range(void); -void Cursor_opaque_set_bool(void); -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_get_set_bool(void); +void Cursor_opaque_get_set_char(void); +void Cursor_opaque_get_set_int(void); +void Cursor_opaque_get_set_uint(void); +void Cursor_opaque_get_set_float(void); void Cursor_opaque_get_set_string(void); -void Cursor_opaque_set_entity(void); -void Cursor_opaque_set_id(void); +void Cursor_opaque_get_set_entity(void); +void Cursor_opaque_get_set_id(void); void Cursor_opaque_set_int_vec(void); void Cursor_opaque_set_int_vec_empty(void); void Cursor_opaque_set_int_vec_resize_smaller(void); @@ -2641,36 +2641,36 @@ bake_test_case Cursor_testcases[] = { Cursor_array_move_out_of_range }, { - "opaque_set_bool", - Cursor_opaque_set_bool + "opaque_get_set_bool", + Cursor_opaque_get_set_bool }, { - "opaque_set_char", - Cursor_opaque_set_char + "opaque_get_set_char", + Cursor_opaque_get_set_char }, { - "opaque_set_int", - Cursor_opaque_set_int + "opaque_get_set_int", + Cursor_opaque_get_set_int }, { - "opaque_set_uint", - Cursor_opaque_set_uint + "opaque_get_set_uint", + Cursor_opaque_get_set_uint }, { - "opaque_set_float", - Cursor_opaque_set_float + "opaque_get_set_float", + Cursor_opaque_get_set_float }, { "opaque_get_set_string", Cursor_opaque_get_set_string }, { - "opaque_set_entity", - Cursor_opaque_set_entity + "opaque_get_set_entity", + Cursor_opaque_get_set_entity }, { - "opaque_set_id", - Cursor_opaque_set_id + "opaque_get_set_id", + Cursor_opaque_get_set_id }, { "opaque_set_int_vec",