diff --git a/distr/flecs.c b/distr/flecs.c index 1db350726a..f94f303687 100644 --- a/distr/flecs.c +++ b/distr/flecs.c @@ -24507,7 +24507,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); @@ -47136,9 +47136,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) { @@ -47182,6 +47182,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, @@ -47230,10 +47276,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)); } @@ -47409,7 +47462,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); @@ -47892,7 +47945,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); @@ -47932,7 +47985,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); @@ -47989,7 +48042,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); @@ -48042,7 +48095,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); @@ -48094,7 +48147,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: @@ -48195,7 +48248,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); @@ -48310,7 +48363,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: @@ -48498,7 +48551,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); ecs_size_t len = ecs_os_strlen(value); if (value[0] != '\"' || value[len - 1] != '\"') { @@ -48566,7 +48619,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: @@ -48626,7 +48679,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: @@ -48683,7 +48736,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); @@ -48739,31 +48792,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: @@ -48784,13 +48849,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: @@ -48827,7 +48904,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; @@ -48844,7 +48924,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: @@ -48855,9 +48935,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: @@ -48877,31 +48966,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: @@ -48958,7 +49059,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: @@ -48970,31 +49071,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( @@ -49002,25 +49094,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 */ } @@ -49063,12 +49148,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: @@ -49099,18 +49196,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: @@ -49188,6 +49297,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( @@ -49227,7 +49341,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, } }); @@ -54541,7 +54656,7 @@ ecs_value_t flecs_dotresolve_var( } return (ecs_value_t){ - .ptr = ecs_meta_get_ptr(&cur), + .ptr = ecs_meta_get_write_ptr(&cur), .type = ecs_meta_get_type(&cur) }; } @@ -54557,7 +54672,7 @@ int flecs_meta_call( const char *function) { ecs_entity_t type = ecs_meta_get_type(cur); - void *value_ptr = ecs_meta_get_ptr(cur); + void *value_ptr = ecs_meta_get_write_ptr(cur); if (!ecs_os_strcmp(function, "parent")) { if (type != ecs_id(ecs_entity_t)) { @@ -55321,7 +55436,7 @@ const char* flecs_funccall_parse( } ecs_entity_t type = ecs_meta_get_type(cur); - value->ptr = ecs_meta_get_ptr(cur); + value->ptr = ecs_meta_get_write_ptr(cur); value->type = type; ptr += 2; @@ -55435,7 +55550,7 @@ const char* flecs_script_expr_run( out = &result; } else { temp_result.type = ecs_meta_get_type(&cur); - temp_result.ptr = ecs_meta_get_ptr(&cur); + temp_result.ptr = ecs_meta_get_write_ptr(&cur); out = &temp_result; } @@ -55691,7 +55806,7 @@ const char* flecs_script_expr_run( } result.type = ecs_meta_get_type(&member_cur); - result.ptr = ecs_meta_get_ptr(&member_cur); + result.ptr = ecs_meta_get_write_ptr(&member_cur); } } } @@ -55714,7 +55829,7 @@ const char* flecs_script_expr_run( out = &result; } else { ecs_entity_t cur_type = ecs_meta_get_type(&cur); - void *cur_ptr = ecs_meta_get_ptr(&cur); + void *cur_ptr = ecs_meta_get_write_ptr(&cur); rvalue.type = cur_type; rvalue.ptr = cur_ptr; temp_out.type = cur_type; @@ -55746,7 +55861,7 @@ const char* flecs_script_expr_run( * temporary storage, and initialize the result value * for the binary operation with the current cursor */ ecs_entity_t cur_type = ecs_meta_get_type(&cur); - void *cur_ptr = ecs_meta_get_ptr(&cur); + void *cur_ptr = ecs_meta_get_write_ptr(&cur); lvalue.type = cur_type; lvalue.ptr = flecs_expr_value_new(stack, cur_type); ecs_value_copy(world, cur_type, lvalue.ptr, cur_ptr); diff --git a/distr/flecs.h b/distr/flecs.h index 84b52260cc..7d5ae0ca0f 100644 --- a/distr/flecs.h +++ b/distr/flecs.h @@ -15400,6 +15400,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; @@ -15554,13 +15601,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. @@ -15865,6 +15921,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); @@ -18770,9 +18827,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 */ @@ -19034,6 +19096,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 868621c2db..3bceb90628 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 d1f23803cf..81955597d4 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 4981269215..f64bbc2b62 100644 --- a/include/flecs/addons/meta.h +++ b/include/flecs/addons/meta.h @@ -457,6 +457,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; @@ -611,13 +658,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. @@ -922,6 +978,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 17d6439dce..796ada2641 100644 --- a/src/addons/meta/cursor.c +++ b/src/addons/meta/cursor.c @@ -123,9 +123,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) { @@ -169,6 +169,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, @@ -217,10 +263,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)); } @@ -396,7 +449,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); @@ -879,7 +932,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); @@ -919,7 +972,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); @@ -976,7 +1029,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); @@ -1029,7 +1082,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); @@ -1081,7 +1134,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: @@ -1182,7 +1235,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); @@ -1297,7 +1350,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: @@ -1485,7 +1538,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); ecs_size_t len = ecs_os_strlen(value); if (value[0] != '\"' || value[len - 1] != '\"') { @@ -1553,7 +1606,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: @@ -1613,7 +1666,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: @@ -1670,7 +1723,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); @@ -1726,31 +1779,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: @@ -1771,13 +1836,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: @@ -1814,7 +1891,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; @@ -1831,7 +1911,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: @@ -1842,9 +1922,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: @@ -1864,31 +1953,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: @@ -1945,7 +2046,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: @@ -1957,31 +2058,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( @@ -1989,25 +2081,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 */ } @@ -2050,12 +2135,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: @@ -2086,18 +2183,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 f22a7ef98f..5556896481 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 1e31f55775..219ddf38e7 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.c b/src/addons/script/expr.c index 40f92ed563..4e66ecd9e5 100644 --- a/src/addons/script/expr.c +++ b/src/addons/script/expr.c @@ -462,7 +462,7 @@ ecs_value_t flecs_dotresolve_var( } return (ecs_value_t){ - .ptr = ecs_meta_get_ptr(&cur), + .ptr = ecs_meta_get_write_ptr(&cur), .type = ecs_meta_get_type(&cur) }; } @@ -478,7 +478,7 @@ int flecs_meta_call( const char *function) { ecs_entity_t type = ecs_meta_get_type(cur); - void *value_ptr = ecs_meta_get_ptr(cur); + void *value_ptr = ecs_meta_get_write_ptr(cur); if (!ecs_os_strcmp(function, "parent")) { if (type != ecs_id(ecs_entity_t)) { @@ -1242,7 +1242,7 @@ const char* flecs_funccall_parse( } ecs_entity_t type = ecs_meta_get_type(cur); - value->ptr = ecs_meta_get_ptr(cur); + value->ptr = ecs_meta_get_write_ptr(cur); value->type = type; ptr += 2; @@ -1356,7 +1356,7 @@ const char* flecs_script_expr_run( out = &result; } else { temp_result.type = ecs_meta_get_type(&cur); - temp_result.ptr = ecs_meta_get_ptr(&cur); + temp_result.ptr = ecs_meta_get_write_ptr(&cur); out = &temp_result; } @@ -1612,7 +1612,7 @@ const char* flecs_script_expr_run( } result.type = ecs_meta_get_type(&member_cur); - result.ptr = ecs_meta_get_ptr(&member_cur); + result.ptr = ecs_meta_get_write_ptr(&member_cur); } } } @@ -1635,7 +1635,7 @@ const char* flecs_script_expr_run( out = &result; } else { ecs_entity_t cur_type = ecs_meta_get_type(&cur); - void *cur_ptr = ecs_meta_get_ptr(&cur); + void *cur_ptr = ecs_meta_get_write_ptr(&cur); rvalue.type = cur_type; rvalue.ptr = cur_ptr; temp_out.type = cur_type; @@ -1667,7 +1667,7 @@ const char* flecs_script_expr_run( * temporary storage, and initialize the result value * for the binary operation with the current cursor */ ecs_entity_t cur_type = ecs_meta_get_type(&cur); - void *cur_ptr = ecs_meta_get_ptr(&cur); + void *cur_ptr = ecs_meta_get_write_ptr(&cur); lvalue.type = cur_type; lvalue.ptr = flecs_expr_value_new(stack, cur_type); ecs_value_copy(world, cur_type, lvalue.ptr, cur_ptr); diff --git a/test/meta/project.json b/test/meta/project.json index 47871f8079..494b1290fb 100644 --- a/test/meta/project.json +++ b/test/meta/project.json @@ -423,14 +423,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 8f79b2332b..6c4e0977a4 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); @@ -432,7 +462,8 @@ void Cursor_set_string_to_null_as_signed(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_string_t), &value); test_ok( ecs_meta_set_int(&cur, 0) ); - test_str(value, 0); + test_str(ecs_meta_get_string(&cur), NULL); + test_str(value, NULL); ecs_fini(world); } @@ -445,7 +476,8 @@ void Cursor_set_string_to_null_as_unsigned(void) { ecs_meta_cursor_t cur = ecs_meta_cursor(world, ecs_id(ecs_string_t), &value); test_ok( ecs_meta_set_uint(&cur, 0) ); - test_str(value, 0); + test_str(ecs_meta_get_string(&cur), NULL); + test_str(value, NULL); ecs_fini(world); } @@ -459,6 +491,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); @@ -473,6 +506,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); @@ -487,6 +521,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); @@ -501,6 +536,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); @@ -515,6 +551,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); @@ -529,6 +566,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); @@ -547,6 +585,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); @@ -558,9 +597,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); } @@ -571,7 +610,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'); @@ -586,6 +625,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); @@ -599,6 +639,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); @@ -612,6 +653,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); @@ -624,6 +666,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); } @@ -631,6 +674,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); } @@ -644,6 +688,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); } @@ -651,6 +696,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); } @@ -665,6 +711,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); @@ -678,6 +725,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); @@ -691,6 +739,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); @@ -704,6 +753,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); @@ -719,6 +769,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); @@ -734,6 +785,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); @@ -749,6 +801,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); @@ -776,6 +829,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); @@ -2806,8 +2860,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) @@ -2827,11 +2885,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); @@ -2839,7 +2905,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 }; @@ -2847,13 +2914,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); @@ -2861,7 +2930,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 }; @@ -2869,13 +2939,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); @@ -2883,7 +2955,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 }; @@ -2891,13 +2964,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); @@ -2905,7 +2980,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 }; @@ -2913,13 +2989,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); @@ -2927,7 +3005,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 }; @@ -2935,19 +3014,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(); @@ -2957,7 +3031,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 }; @@ -2972,7 +3046,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); @@ -2980,7 +3054,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 }; @@ -2990,13 +3065,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); @@ -3004,7 +3081,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 }; @@ -3014,8 +3092,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); } @@ -3039,6 +3119,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) { @@ -3061,6 +3149,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 }); @@ -3081,6 +3170,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); @@ -3334,7 +3435,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; @@ -3345,6 +3446,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(); @@ -3358,7 +3470,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 }; @@ -3366,8 +3479,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); @@ -3376,8 +3491,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); @@ -3392,7 +3509,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; @@ -3403,6 +3520,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(); @@ -3425,7 +3553,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 }; @@ -3435,15 +3564,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)); @@ -3458,15 +3591,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)); @@ -3485,7 +3622,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; @@ -3496,6 +3633,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(); @@ -3510,7 +3658,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, { @@ -3521,7 +3670,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 }; @@ -3531,15 +3681,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)); @@ -3554,15 +3708,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)); @@ -3963,7 +4121,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, { @@ -4144,7 +4303,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, { @@ -4345,7 +4505,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; @@ -4356,6 +4516,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(); @@ -4366,6 +4537,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 }); @@ -4380,7 +4552,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}; @@ -4389,19 +4562,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); @@ -4418,7 +4609,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 { @@ -4444,13 +4643,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 }); @@ -4461,19 +4662,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 b22d883cb8..29a38d5abe 100644 --- a/test/meta/src/main.c +++ b/test/meta/src/main.c @@ -398,14 +398,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); @@ -2495,36 +2495,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",