Skip to content

Commit 2c0ab43

Browse files
committed
Fix inconsistencies between C/C++ API in enum constant registration
1 parent 1d1ec0c commit 2c0ab43

7 files changed

Lines changed: 211 additions & 25 deletions

File tree

flecs.c

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19098,9 +19098,11 @@ void ecs_cpp_enum_init(
1909819098
{
1909919099
ecs_suspend_readonly_state_t readonly_state;
1910019100
world = flecs_suspend_readonly(world, &readonly_state);
19101-
ecs_add_id(world, id, EcsExclusive);
19102-
ecs_add_id(world, id, EcsOneOf);
19103-
ecs_add_id(world, id, EcsTag);
19101+
19102+
#ifdef FLECS_META
19103+
ecs_set(world, id, EcsEnum, {0});
19104+
#endif
19105+
1910419106
flecs_resume_readonly(world, &readonly_state);
1910519107
}
1910619108

@@ -19138,7 +19140,10 @@ ecs_entity_t ecs_cpp_enum_constant_register(
1913819140
"enum component must have 32bit size");
1913919141
#endif
1914019142

19141-
ecs_set_id(world, id, parent, sizeof(int), &value);
19143+
#ifdef FLECS_META
19144+
ecs_set_id(world, id, ecs_pair(EcsConstant, ecs_id(ecs_i32_t)),
19145+
sizeof(ecs_i32_t), &value);
19146+
#endif
1914219147

1914319148
flecs_resume_readonly(world, &readonly_state);
1914419149

@@ -23894,9 +23899,24 @@ static ECS_MOVE(EcsUnitPrefix, dst, src, {
2389423899

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

23897-
2389823902
/* Type initialization */
2389923903

23904+
static
23905+
const char* flecs_type_kind_str(
23906+
ecs_type_kind_t kind)
23907+
{
23908+
switch(kind) {
23909+
case EcsPrimitiveType: return "Primitive";
23910+
case EcsBitmaskType: return "Bitmask";
23911+
case EcsEnumType: return "Enum";
23912+
case EcsStructType: return "Struct";
23913+
case EcsArrayType: return "Array";
23914+
case EcsVectorType: return "Vector";
23915+
case EcsOpaqueType: return "Opaque";
23916+
default: return "unknown";
23917+
}
23918+
}
23919+
2390023920
static
2390123921
int flecs_init_type(
2390223922
ecs_world_t *world,
@@ -23920,8 +23940,10 @@ int flecs_init_type(
2392023940
}
2392123941
} else {
2392223942
if (meta_type->kind != kind) {
23923-
ecs_err("type '%s' reregistered with different kind",
23924-
ecs_get_name(world, type));
23943+
ecs_err("type '%s' reregistered as '%s' (was '%s')",
23944+
ecs_get_name(world, type),
23945+
flecs_type_kind_str(kind),
23946+
flecs_type_kind_str(meta_type->kind));
2392523947
return -1;
2392623948
}
2392723949
}
@@ -24239,6 +24261,9 @@ int flecs_add_constant_to_enum(
2423924261
ecs_assert(cptr != NULL, ECS_INTERNAL_ERROR, NULL);
2424024262
cptr[0] = value;
2424124263

24264+
cptr = ecs_get_mut_id(world, e, type);
24265+
cptr[0] = value;
24266+
2424224267
return 0;
2424324268
}
2424424269

@@ -24305,6 +24330,9 @@ int flecs_add_constant_to_bitmask(
2430524330
ecs_assert(cptr != NULL, ECS_INTERNAL_ERROR, NULL);
2430624331
cptr[0] = value;
2430724332

24333+
cptr = ecs_get_mut_id(world, e, type);
24334+
cptr[0] = value;
24335+
2430824336
return 0;
2430924337
}
2431024338

@@ -24687,10 +24715,14 @@ void ecs_meta_type_init_default_ctor(ecs_iter_t *it) {
2468724715
* contain uninitialized memory, which could cause serializers to crash
2468824716
* when for example inspecting string fields. */
2468924717
if (!type->existing) {
24690-
ecs_set_hooks_id(world, it->entities[i],
24691-
&(ecs_type_hooks_t){
24692-
.ctor = ecs_default_ctor
24693-
});
24718+
ecs_entity_t e = it->entities[i];
24719+
const ecs_type_info_t *ti = ecs_get_type_info(world, e);
24720+
if (!ti || !ti->hooks.ctor) {
24721+
ecs_set_hooks_id(world, e,
24722+
&(ecs_type_hooks_t){
24723+
.ctor = ecs_default_ctor
24724+
});
24725+
}
2469424726
}
2469524727
}
2469624728
}

src/addons/flecs_cpp.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,11 @@ void ecs_cpp_enum_init(
427427
{
428428
ecs_suspend_readonly_state_t readonly_state;
429429
world = flecs_suspend_readonly(world, &readonly_state);
430-
ecs_add_id(world, id, EcsExclusive);
431-
ecs_add_id(world, id, EcsOneOf);
432-
ecs_add_id(world, id, EcsTag);
430+
431+
#ifdef FLECS_META
432+
ecs_set(world, id, EcsEnum, {0});
433+
#endif
434+
433435
flecs_resume_readonly(world, &readonly_state);
434436
}
435437

@@ -467,7 +469,10 @@ ecs_entity_t ecs_cpp_enum_constant_register(
467469
"enum component must have 32bit size");
468470
#endif
469471

470-
ecs_set_id(world, id, parent, sizeof(int), &value);
472+
#ifdef FLECS_META
473+
ecs_set_id(world, id, ecs_pair(EcsConstant, ecs_id(ecs_i32_t)),
474+
sizeof(ecs_i32_t), &value);
475+
#endif
471476

472477
flecs_resume_readonly(world, &readonly_state);
473478

src/addons/meta/meta.c

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,24 @@ static ECS_MOVE(EcsUnitPrefix, dst, src, {
228228

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

231-
232231
/* Type initialization */
233232

233+
static
234+
const char* flecs_type_kind_str(
235+
ecs_type_kind_t kind)
236+
{
237+
switch(kind) {
238+
case EcsPrimitiveType: return "Primitive";
239+
case EcsBitmaskType: return "Bitmask";
240+
case EcsEnumType: return "Enum";
241+
case EcsStructType: return "Struct";
242+
case EcsArrayType: return "Array";
243+
case EcsVectorType: return "Vector";
244+
case EcsOpaqueType: return "Opaque";
245+
default: return "unknown";
246+
}
247+
}
248+
234249
static
235250
int flecs_init_type(
236251
ecs_world_t *world,
@@ -254,8 +269,10 @@ int flecs_init_type(
254269
}
255270
} else {
256271
if (meta_type->kind != kind) {
257-
ecs_err("type '%s' reregistered with different kind",
258-
ecs_get_name(world, type));
272+
ecs_err("type '%s' reregistered as '%s' (was '%s')",
273+
ecs_get_name(world, type),
274+
flecs_type_kind_str(kind),
275+
flecs_type_kind_str(meta_type->kind));
259276
return -1;
260277
}
261278
}
@@ -573,6 +590,9 @@ int flecs_add_constant_to_enum(
573590
ecs_assert(cptr != NULL, ECS_INTERNAL_ERROR, NULL);
574591
cptr[0] = value;
575592

593+
cptr = ecs_get_mut_id(world, e, type);
594+
cptr[0] = value;
595+
576596
return 0;
577597
}
578598

@@ -639,6 +659,9 @@ int flecs_add_constant_to_bitmask(
639659
ecs_assert(cptr != NULL, ECS_INTERNAL_ERROR, NULL);
640660
cptr[0] = value;
641661

662+
cptr = ecs_get_mut_id(world, e, type);
663+
cptr[0] = value;
664+
642665
return 0;
643666
}
644667

@@ -1021,10 +1044,14 @@ void ecs_meta_type_init_default_ctor(ecs_iter_t *it) {
10211044
* contain uninitialized memory, which could cause serializers to crash
10221045
* when for example inspecting string fields. */
10231046
if (!type->existing) {
1024-
ecs_set_hooks_id(world, it->entities[i],
1025-
&(ecs_type_hooks_t){
1026-
.ctor = ecs_default_ctor
1027-
});
1047+
ecs_entity_t e = it->entities[i];
1048+
const ecs_type_info_t *ti = ecs_get_type_info(world, e);
1049+
if (!ti || !ti->hooks.ctor) {
1050+
ecs_set_hooks_id(world, e,
1051+
&(ecs_type_hooks_t){
1052+
.ctor = ecs_default_ctor
1053+
});
1054+
}
10281055
}
10291056
}
10301057
}

test/cpp_api/project.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,9 @@
366366
"add_if",
367367
"add_if_other",
368368
"query_union_enum",
369-
"query_union_enum_invalid_query_type"
369+
"query_union_enum_invalid_query_type",
370+
"component_registered_as_enum",
371+
"mixed_auto_manual_constants"
370372
]
371373
}, {
372374
"id": "Switch",

test/cpp_api/src/Enum.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ enum class EnumIncorrectType : uint8_t {
3030
A, B
3131
};
3232

33+
enum EnumWithLargeConstant {
34+
X, Y, Z = 1000
35+
};
36+
3337
/* Optional, but improves compile time */
3438
FLECS_ENUM_LAST(StandardEnum, Blue)
3539
FLECS_ENUM_LAST(SparseEnum, Grey)
@@ -785,3 +789,106 @@ void Enum_query_union_enum_invalid_query_type() {
785789
.term_at(1).second(flecs::Wildcard)
786790
.build();
787791
}
792+
793+
void Enum_component_registered_as_enum() {
794+
flecs::world ecs;
795+
796+
auto e = ecs.component<StandardEnum>();
797+
798+
test_assert(e.has<flecs::Enum>());
799+
800+
const flecs::MetaType *mt = e.get<flecs::MetaType>();
801+
test_assert(mt != nullptr);
802+
test_assert(mt->kind == flecs::meta::EnumType);
803+
804+
{
805+
auto c = e.lookup("Red");
806+
test_assert(c != 0);
807+
808+
const StandardEnum *v = c.get<StandardEnum>();
809+
test_assert(v != nullptr);
810+
test_assert(*v == StandardEnum::Red);
811+
812+
const int32_t *vi = c.get_second<int32_t>(flecs::Constant);
813+
test_assert(vi != nullptr);
814+
test_int(*vi, StandardEnum::Red);
815+
}
816+
817+
{
818+
auto c = e.lookup("Green");
819+
test_assert(c != 0);
820+
821+
const StandardEnum *v = c.get<StandardEnum>();
822+
test_assert(v != nullptr);
823+
test_assert(*v == StandardEnum::Green);
824+
825+
const int32_t *vi = c.get_second<int32_t>(flecs::Constant);
826+
test_assert(vi != nullptr);
827+
test_int(*vi, StandardEnum::Green);
828+
}
829+
830+
{
831+
auto c = e.lookup("Blue");
832+
test_assert(c != 0);
833+
834+
const StandardEnum *v = c.get<StandardEnum>();
835+
test_assert(v != nullptr);
836+
test_assert(*v == StandardEnum::Blue);
837+
838+
const int32_t *vi = c.get_second<int32_t>(flecs::Constant);
839+
test_assert(vi != nullptr);
840+
test_int(*vi, StandardEnum::Blue);
841+
}
842+
}
843+
844+
void Enum_mixed_auto_manual_constants() {
845+
flecs::world ecs;
846+
847+
auto e = ecs.component<EnumWithLargeConstant>()
848+
.constant("Z", EnumWithLargeConstant::Z);
849+
850+
test_assert(e.has<flecs::Enum>());
851+
852+
const flecs::MetaType *mt = e.get<flecs::MetaType>();
853+
test_assert(mt != nullptr);
854+
test_assert(mt->kind == flecs::meta::EnumType);
855+
856+
{
857+
auto c = e.lookup("X");
858+
test_assert(c != 0);
859+
860+
const EnumWithLargeConstant *v = c.get<EnumWithLargeConstant>();
861+
test_assert(v != nullptr);
862+
test_assert(*v == EnumWithLargeConstant::X);
863+
864+
const int32_t *vi = c.get_second<int32_t>(flecs::Constant);
865+
test_assert(vi != nullptr);
866+
test_int(*vi, EnumWithLargeConstant::X);
867+
}
868+
869+
{
870+
auto c = e.lookup("Y");
871+
test_assert(c != 0);
872+
873+
const EnumWithLargeConstant *v = c.get<EnumWithLargeConstant>();
874+
test_assert(v != nullptr);
875+
test_assert(*v == EnumWithLargeConstant::Y);
876+
877+
const int32_t *vi = c.get_second<int32_t>(flecs::Constant);
878+
test_assert(vi != nullptr);
879+
test_int(*vi, EnumWithLargeConstant::Y);
880+
}
881+
882+
{
883+
auto c = e.lookup("Z");
884+
test_assert(c != 0);
885+
886+
const EnumWithLargeConstant *v = c.get<EnumWithLargeConstant>();
887+
test_assert(v != nullptr);
888+
test_assert(*v == EnumWithLargeConstant::Z);
889+
890+
const int32_t *vi = c.get_second<int32_t>(flecs::Constant);
891+
test_assert(vi != nullptr);
892+
test_int(*vi, EnumWithLargeConstant::Z);
893+
}
894+
}

test/cpp_api/src/Meta.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,10 @@ struct EnumWithBitsStruct {
10101010
void Meta_enum_w_bits() {
10111011
flecs::world ecs;
10121012

1013+
flecs::log::set_level(-4);
1014+
1015+
/* It is illegal to register an enumeration as bitset, this test makes sure
1016+
* the code doesn't crash. */
10131017
ecs.component<EnumWithBits>()
10141018
.bit("BitA", (uint32_t)EnumWithBits::BitA)
10151019
.bit("BitB", (uint32_t)EnumWithBits::BitB)
@@ -1025,7 +1029,6 @@ void Meta_enum_w_bits() {
10251029
.add<EnumWithBitsStruct>();
10261030
}
10271031

1028-
flecs::log::set_level(-4);
10291032
auto q = ecs.query<EnumWithBitsStruct>();
10301033
auto s = q.iter().to_json();
10311034
test_str(s.c_str(), "");

test/cpp_api/src/main.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ void Enum_add_if(void);
355355
void Enum_add_if_other(void);
356356
void Enum_query_union_enum(void);
357357
void Enum_query_union_enum_invalid_query_type(void);
358+
void Enum_component_registered_as_enum(void);
359+
void Enum_mixed_auto_manual_constants(void);
358360

359361
// Testsuite 'Switch'
360362
void Switch_add_case(void);
@@ -2578,6 +2580,14 @@ bake_test_case Enum_testcases[] = {
25782580
{
25792581
"query_union_enum_invalid_query_type",
25802582
Enum_query_union_enum_invalid_query_type
2583+
},
2584+
{
2585+
"component_registered_as_enum",
2586+
Enum_component_registered_as_enum
2587+
},
2588+
{
2589+
"mixed_auto_manual_constants",
2590+
Enum_mixed_auto_manual_constants
25812591
}
25822592
};
25832593

@@ -5895,7 +5905,7 @@ static bake_test_suite suites[] = {
58955905
"Enum",
58965906
NULL,
58975907
NULL,
5898-
32,
5908+
34,
58995909
Enum_testcases
59005910
},
59015911
{

0 commit comments

Comments
 (0)