Skip to content

Commit

Permalink
Fix inconsistencies between C/C++ API in enum constant registration
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed May 3, 2023
1 parent 1d1ec0c commit 2c0ab43
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 25 deletions.
54 changes: 43 additions & 11 deletions flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -19098,9 +19098,11 @@ void ecs_cpp_enum_init(
{
ecs_suspend_readonly_state_t readonly_state;
world = flecs_suspend_readonly(world, &readonly_state);
ecs_add_id(world, id, EcsExclusive);
ecs_add_id(world, id, EcsOneOf);
ecs_add_id(world, id, EcsTag);

#ifdef FLECS_META
ecs_set(world, id, EcsEnum, {0});
#endif

flecs_resume_readonly(world, &readonly_state);
}

Expand Down Expand Up @@ -19138,7 +19140,10 @@ ecs_entity_t ecs_cpp_enum_constant_register(
"enum component must have 32bit size");
#endif

ecs_set_id(world, id, parent, sizeof(int), &value);
#ifdef FLECS_META
ecs_set_id(world, id, ecs_pair(EcsConstant, ecs_id(ecs_i32_t)),
sizeof(ecs_i32_t), &value);
#endif

flecs_resume_readonly(world, &readonly_state);

Expand Down Expand Up @@ -23894,9 +23899,24 @@ static ECS_MOVE(EcsUnitPrefix, dst, src, {

static ECS_DTOR(EcsUnitPrefix, ptr, { dtor_unit_prefix(ptr); })


/* Type initialization */

static
const char* flecs_type_kind_str(
ecs_type_kind_t kind)
{
switch(kind) {
case EcsPrimitiveType: return "Primitive";
case EcsBitmaskType: return "Bitmask";
case EcsEnumType: return "Enum";
case EcsStructType: return "Struct";
case EcsArrayType: return "Array";
case EcsVectorType: return "Vector";
case EcsOpaqueType: return "Opaque";
default: return "unknown";
}
}

static
int flecs_init_type(
ecs_world_t *world,
Expand All @@ -23920,8 +23940,10 @@ int flecs_init_type(
}
} else {
if (meta_type->kind != kind) {
ecs_err("type '%s' reregistered with different kind",
ecs_get_name(world, type));
ecs_err("type '%s' reregistered as '%s' (was '%s')",
ecs_get_name(world, type),
flecs_type_kind_str(kind),
flecs_type_kind_str(meta_type->kind));
return -1;
}
}
Expand Down Expand Up @@ -24239,6 +24261,9 @@ int flecs_add_constant_to_enum(
ecs_assert(cptr != NULL, ECS_INTERNAL_ERROR, NULL);
cptr[0] = value;

cptr = ecs_get_mut_id(world, e, type);
cptr[0] = value;

return 0;
}

Expand Down Expand Up @@ -24305,6 +24330,9 @@ int flecs_add_constant_to_bitmask(
ecs_assert(cptr != NULL, ECS_INTERNAL_ERROR, NULL);
cptr[0] = value;

cptr = ecs_get_mut_id(world, e, type);
cptr[0] = value;

return 0;
}

Expand Down Expand Up @@ -24687,10 +24715,14 @@ void ecs_meta_type_init_default_ctor(ecs_iter_t *it) {
* contain uninitialized memory, which could cause serializers to crash
* when for example inspecting string fields. */
if (!type->existing) {
ecs_set_hooks_id(world, it->entities[i],
&(ecs_type_hooks_t){
.ctor = ecs_default_ctor
});
ecs_entity_t e = it->entities[i];
const ecs_type_info_t *ti = ecs_get_type_info(world, e);
if (!ti || !ti->hooks.ctor) {
ecs_set_hooks_id(world, e,
&(ecs_type_hooks_t){
.ctor = ecs_default_ctor
});
}
}
}
}
Expand Down
13 changes: 9 additions & 4 deletions src/addons/flecs_cpp.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,11 @@ void ecs_cpp_enum_init(
{
ecs_suspend_readonly_state_t readonly_state;
world = flecs_suspend_readonly(world, &readonly_state);
ecs_add_id(world, id, EcsExclusive);
ecs_add_id(world, id, EcsOneOf);
ecs_add_id(world, id, EcsTag);

#ifdef FLECS_META
ecs_set(world, id, EcsEnum, {0});
#endif

flecs_resume_readonly(world, &readonly_state);
}

Expand Down Expand Up @@ -467,7 +469,10 @@ ecs_entity_t ecs_cpp_enum_constant_register(
"enum component must have 32bit size");
#endif

ecs_set_id(world, id, parent, sizeof(int), &value);
#ifdef FLECS_META
ecs_set_id(world, id, ecs_pair(EcsConstant, ecs_id(ecs_i32_t)),
sizeof(ecs_i32_t), &value);
#endif

flecs_resume_readonly(world, &readonly_state);

Expand Down
41 changes: 34 additions & 7 deletions src/addons/meta/meta.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,24 @@ static ECS_MOVE(EcsUnitPrefix, dst, src, {

static ECS_DTOR(EcsUnitPrefix, ptr, { dtor_unit_prefix(ptr); })


/* Type initialization */

static
const char* flecs_type_kind_str(
ecs_type_kind_t kind)
{
switch(kind) {
case EcsPrimitiveType: return "Primitive";
case EcsBitmaskType: return "Bitmask";
case EcsEnumType: return "Enum";
case EcsStructType: return "Struct";
case EcsArrayType: return "Array";
case EcsVectorType: return "Vector";
case EcsOpaqueType: return "Opaque";
default: return "unknown";
}
}

static
int flecs_init_type(
ecs_world_t *world,
Expand All @@ -254,8 +269,10 @@ int flecs_init_type(
}
} else {
if (meta_type->kind != kind) {
ecs_err("type '%s' reregistered with different kind",
ecs_get_name(world, type));
ecs_err("type '%s' reregistered as '%s' (was '%s')",
ecs_get_name(world, type),
flecs_type_kind_str(kind),
flecs_type_kind_str(meta_type->kind));
return -1;
}
}
Expand Down Expand Up @@ -573,6 +590,9 @@ int flecs_add_constant_to_enum(
ecs_assert(cptr != NULL, ECS_INTERNAL_ERROR, NULL);
cptr[0] = value;

cptr = ecs_get_mut_id(world, e, type);
cptr[0] = value;

return 0;
}

Expand Down Expand Up @@ -639,6 +659,9 @@ int flecs_add_constant_to_bitmask(
ecs_assert(cptr != NULL, ECS_INTERNAL_ERROR, NULL);
cptr[0] = value;

cptr = ecs_get_mut_id(world, e, type);
cptr[0] = value;

return 0;
}

Expand Down Expand Up @@ -1021,10 +1044,14 @@ void ecs_meta_type_init_default_ctor(ecs_iter_t *it) {
* contain uninitialized memory, which could cause serializers to crash
* when for example inspecting string fields. */
if (!type->existing) {
ecs_set_hooks_id(world, it->entities[i],
&(ecs_type_hooks_t){
.ctor = ecs_default_ctor
});
ecs_entity_t e = it->entities[i];
const ecs_type_info_t *ti = ecs_get_type_info(world, e);
if (!ti || !ti->hooks.ctor) {
ecs_set_hooks_id(world, e,
&(ecs_type_hooks_t){
.ctor = ecs_default_ctor
});
}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion test/cpp_api/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,9 @@
"add_if",
"add_if_other",
"query_union_enum",
"query_union_enum_invalid_query_type"
"query_union_enum_invalid_query_type",
"component_registered_as_enum",
"mixed_auto_manual_constants"
]
}, {
"id": "Switch",
Expand Down
107 changes: 107 additions & 0 deletions test/cpp_api/src/Enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ enum class EnumIncorrectType : uint8_t {
A, B
};

enum EnumWithLargeConstant {
X, Y, Z = 1000
};

/* Optional, but improves compile time */
FLECS_ENUM_LAST(StandardEnum, Blue)
FLECS_ENUM_LAST(SparseEnum, Grey)
Expand Down Expand Up @@ -785,3 +789,106 @@ void Enum_query_union_enum_invalid_query_type() {
.term_at(1).second(flecs::Wildcard)
.build();
}

void Enum_component_registered_as_enum() {
flecs::world ecs;

auto e = ecs.component<StandardEnum>();

test_assert(e.has<flecs::Enum>());

const flecs::MetaType *mt = e.get<flecs::MetaType>();
test_assert(mt != nullptr);
test_assert(mt->kind == flecs::meta::EnumType);

{
auto c = e.lookup("Red");
test_assert(c != 0);

const StandardEnum *v = c.get<StandardEnum>();
test_assert(v != nullptr);
test_assert(*v == StandardEnum::Red);

const int32_t *vi = c.get_second<int32_t>(flecs::Constant);
test_assert(vi != nullptr);
test_int(*vi, StandardEnum::Red);
}

{
auto c = e.lookup("Green");
test_assert(c != 0);

const StandardEnum *v = c.get<StandardEnum>();
test_assert(v != nullptr);
test_assert(*v == StandardEnum::Green);

const int32_t *vi = c.get_second<int32_t>(flecs::Constant);
test_assert(vi != nullptr);
test_int(*vi, StandardEnum::Green);
}

{
auto c = e.lookup("Blue");
test_assert(c != 0);

const StandardEnum *v = c.get<StandardEnum>();
test_assert(v != nullptr);
test_assert(*v == StandardEnum::Blue);

const int32_t *vi = c.get_second<int32_t>(flecs::Constant);
test_assert(vi != nullptr);
test_int(*vi, StandardEnum::Blue);
}
}

void Enum_mixed_auto_manual_constants() {
flecs::world ecs;

auto e = ecs.component<EnumWithLargeConstant>()
.constant("Z", EnumWithLargeConstant::Z);

test_assert(e.has<flecs::Enum>());

const flecs::MetaType *mt = e.get<flecs::MetaType>();
test_assert(mt != nullptr);
test_assert(mt->kind == flecs::meta::EnumType);

{
auto c = e.lookup("X");
test_assert(c != 0);

const EnumWithLargeConstant *v = c.get<EnumWithLargeConstant>();
test_assert(v != nullptr);
test_assert(*v == EnumWithLargeConstant::X);

const int32_t *vi = c.get_second<int32_t>(flecs::Constant);
test_assert(vi != nullptr);
test_int(*vi, EnumWithLargeConstant::X);
}

{
auto c = e.lookup("Y");
test_assert(c != 0);

const EnumWithLargeConstant *v = c.get<EnumWithLargeConstant>();
test_assert(v != nullptr);
test_assert(*v == EnumWithLargeConstant::Y);

const int32_t *vi = c.get_second<int32_t>(flecs::Constant);
test_assert(vi != nullptr);
test_int(*vi, EnumWithLargeConstant::Y);
}

{
auto c = e.lookup("Z");
test_assert(c != 0);

const EnumWithLargeConstant *v = c.get<EnumWithLargeConstant>();
test_assert(v != nullptr);
test_assert(*v == EnumWithLargeConstant::Z);

const int32_t *vi = c.get_second<int32_t>(flecs::Constant);
test_assert(vi != nullptr);
test_int(*vi, EnumWithLargeConstant::Z);
}
}
5 changes: 4 additions & 1 deletion test/cpp_api/src/Meta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,10 @@ struct EnumWithBitsStruct {
void Meta_enum_w_bits() {
flecs::world ecs;

flecs::log::set_level(-4);

/* It is illegal to register an enumeration as bitset, this test makes sure
* the code doesn't crash. */
ecs.component<EnumWithBits>()
.bit("BitA", (uint32_t)EnumWithBits::BitA)
.bit("BitB", (uint32_t)EnumWithBits::BitB)
Expand All @@ -1025,7 +1029,6 @@ void Meta_enum_w_bits() {
.add<EnumWithBitsStruct>();
}

flecs::log::set_level(-4);
auto q = ecs.query<EnumWithBitsStruct>();
auto s = q.iter().to_json();
test_str(s.c_str(), "");
Expand Down
12 changes: 11 additions & 1 deletion test/cpp_api/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@ void Enum_add_if(void);
void Enum_add_if_other(void);
void Enum_query_union_enum(void);
void Enum_query_union_enum_invalid_query_type(void);
void Enum_component_registered_as_enum(void);
void Enum_mixed_auto_manual_constants(void);

// Testsuite 'Switch'
void Switch_add_case(void);
Expand Down Expand Up @@ -2578,6 +2580,14 @@ bake_test_case Enum_testcases[] = {
{
"query_union_enum_invalid_query_type",
Enum_query_union_enum_invalid_query_type
},
{
"component_registered_as_enum",
Enum_component_registered_as_enum
},
{
"mixed_auto_manual_constants",
Enum_mixed_auto_manual_constants
}
};

Expand Down Expand Up @@ -5895,7 +5905,7 @@ static bake_test_suite suites[] = {
"Enum",
NULL,
NULL,
32,
34,
Enum_testcases
},
{
Expand Down

0 comments on commit 2c0ab43

Please sign in to comment.