@@ -18225,26 +18225,20 @@ struct enum_is_valid {
18225
18225
/** Extract name of constant from string */
18226
18226
template <typename E, E C>
18227
18227
static const char* enum_constant_to_name() {
18228
- static const size_t len = ECS_FUNC_TYPE_LEN(const char*, enum_constant_to_name, ECS_FUNC_NAME);
18228
+ static const size_t len = ECS_FUNC_TYPE_LEN(
18229
+ const char*, enum_constant_to_name, ECS_FUNC_NAME);
18229
18230
static char result[len + 1] = {};
18230
18231
return ecs_cpp_get_constant_name(
18231
18232
result, ECS_FUNC_NAME, string::length(ECS_FUNC_NAME),
18232
18233
ECS_FUNC_NAME_BACK);
18233
18234
}
18234
18235
18235
- /** Enumeration constant data */
18236
- template<typename T>
18237
- struct enum_constant_data {
18238
- int32_t index; // Global index used to obtain world local entity id
18239
- T offset;
18240
- };
18241
-
18242
18236
/**
18243
18237
* @brief Provides utilities for enum reflection.
18244
18238
*
18245
- * This struct provides static functions for enum reflection, including conversion
18246
- * between enum values and their underlying integral types, and iteration over enum
18247
- * values.
18239
+ * This struct provides static functions for enum reflection, including
18240
+ * conversion between enum values and their underlying integral types, and
18241
+ * iteration over enum values.
18248
18242
*
18249
18243
* @tparam E The enum type.
18250
18244
* @tparam Handler The handler for enum reflection operations.
@@ -18254,11 +18248,13 @@ struct enum_reflection {
18254
18248
using U = underlying_type_t<E>;
18255
18249
18256
18250
/**
18257
- * @brief Iterates over the range [Low, High] of enum values between Low and High.
18251
+ * @brief Iterates over the range [Low, High] of enum values between Low and
18252
+ * High.
18258
18253
*
18259
- * Recursively divide and conquers the search space to reduce the template-depth. Once
18260
- * recursive division is complete, calls Handle<E>::handle_constant in ascending order,
18261
- * passing the values computed up the chain.
18254
+ * Recursively divide and conquers the search space to reduce the
18255
+ * template-depth. Once recursive division is complete, calls
18256
+ * Handle<E>::handle_constant in ascending order, passing the values
18257
+ * computed up the chain.
18262
18258
*
18263
18259
* @tparam Low The lower bound of the search range, inclusive.
18264
18260
* @tparam High The upper bound of the search range, inclusive.
@@ -18268,23 +18264,27 @@ struct enum_reflection {
18268
18264
* @return constexpr U The result of the iteration.
18269
18265
*/
18270
18266
template <U Low, U High, typename... Args>
18271
- static constexpr U each_enum_range(U last_value, Args... args) {
18267
+ static constexpr U each_enum_range(U last_value, Args& ... args) {
18272
18268
return High - Low <= 1
18273
18269
? High == Low
18274
18270
? Handler::template handle_constant<Low>(last_value, args...)
18275
- : Handler::template handle_constant<High>(Handler::template handle_constant<Low>(last_value, args...), args...)
18271
+ : Handler::template handle_constant<High>(
18272
+ Handler::template handle_constant<Low>(last_value, args...),
18273
+ args...)
18276
18274
: each_enum_range<(Low + High) / 2 + 1, High>(
18277
18275
each_enum_range<Low, (Low + High) / 2>(last_value, args...),
18278
18276
args...
18279
18277
);
18280
18278
}
18281
18279
18282
18280
/**
18283
- * @brief Iterates over the mask range (Low, High] of enum values between Low and High.
18281
+ * @brief Iterates over the mask range (Low, High] of enum values between
18282
+ * Low and High.
18284
18283
*
18285
- * Recursively iterates the search space, looking for enums defined as multiple-of-2
18286
- * bitmasks. Each iteration, shifts bit to the right until it hits Low, then calls
18287
- * Handler::handle_constant for each bitmask in ascending order.
18284
+ * Recursively iterates the search space, looking for enums defined as
18285
+ * multiple-of-2 bitmasks. Each iteration, shifts bit to the right until it
18286
+ * hits Low, then calls Handler::handle_constant for each bitmask in
18287
+ * ascending order.
18288
18288
*
18289
18289
* @tparam Low The lower bound of the search range, not inclusive
18290
18290
* @tparam High The upper bound of the search range, inclusive.
@@ -18294,8 +18294,9 @@ struct enum_reflection {
18294
18294
* @return constexpr U The result of the iteration.
18295
18295
*/
18296
18296
template <U Low, U High, typename... Args>
18297
- static constexpr U each_mask_range(U last_value, Args... args) {
18298
- // If Low shares any bits with Current Flag, or if High is less than/equal to Low (and High isn't negative because max-flag signed)
18297
+ static constexpr U each_mask_range(U last_value, Args&... args) {
18298
+ // If Low shares any bits with Current Flag, or if High is less
18299
+ // than/equal to Low (and High isn't negative because max-flag signed)
18299
18300
return (Low & High) || (High <= Low && High != high_bit)
18300
18301
? last_value
18301
18302
: Handler::template handle_constant<High>(
@@ -18317,105 +18318,116 @@ struct enum_reflection {
18317
18318
* @return constexpr U The result of the iteration.
18318
18319
*/
18319
18320
template <U Value = static_cast<U>(FLECS_ENUM_MAX(E)), typename... Args>
18320
- static constexpr U each_enum(Args... args) {
18321
- return each_mask_range<Value, high_bit>(each_enum_range<0, Value>(0, args...), args...);
18321
+ static constexpr U each_enum(Args&... args) {
18322
+ return each_mask_range<Value, high_bit>(
18323
+ each_enum_range<0, Value>(0, args...), args...);
18322
18324
}
18323
18325
/* to avoid warnings with bit manipulation, calculate the high bit with an
18324
18326
unsigned type of the same size: */
18325
18327
using UU = typename std::make_unsigned<U>::type;
18326
- static const U high_bit = static_cast<U>(static_cast<UU>(1) << (sizeof(UU) * 8 - 1));
18328
+ static const U high_bit =
18329
+ static_cast<U>(static_cast<UU>(1) << (sizeof(UU) * 8 - 1));
18330
+ };
18331
+
18332
+ /** Enumeration constant data */
18333
+ template<typename T>
18334
+ struct enum_constant {
18335
+ int32_t index; // Global index used to obtain world local entity id
18336
+ T value;
18337
+ T offset;
18338
+ const char *name;
18327
18339
};
18328
18340
18329
- /** Enumeration type data */
18330
- template<typename E>
18331
- struct enum_data_impl {
18341
+ /** Class that scans an enum for constants, extracts names & creates entities */
18342
+ template <typename E>
18343
+ struct enum_type {
18332
18344
private:
18345
+ using This = enum_type<E>;
18333
18346
using U = underlying_type_t<E>;
18334
18347
18335
18348
/**
18336
18349
* @brief Handler struct for generating compile-time count of enum constants.
18337
18350
*/
18338
18351
struct reflection_count {
18339
- template <U Value, flecs::if_not_t< enum_constant_is_valid_wrap<E, Value>() > = 0>
18352
+ template <U Value,
18353
+ flecs::if_not_t< enum_constant_is_valid_wrap<E, Value>() > = 0>
18340
18354
static constexpr U handle_constant(U last_value) {
18341
18355
return last_value;
18342
18356
}
18343
18357
18344
- template <U Value, flecs::if_t< enum_constant_is_valid_wrap<E, Value>() > = 0>
18358
+ template <U Value,
18359
+ flecs::if_t< enum_constant_is_valid_wrap<E, Value>() > = 0>
18345
18360
static constexpr U handle_constant(U last_value) {
18346
18361
return 1 + last_value;
18347
18362
}
18348
18363
};
18349
18364
18350
- public:
18351
- int min;
18352
- int max;
18353
- bool has_contiguous;
18354
- // If enum constants start not-sparse, contiguous_until will be the index of the first sparse value, or end of the constants array
18355
- U contiguous_until;
18356
- // Compile-time generated count of enum constants.
18357
- static constexpr unsigned int constants_size = enum_reflection<E, reflection_count>::template each_enum< static_cast<U>(enum_last<E>::value) >();
18358
- // Constants array is sized to the number of found-constants, or 1 (to avoid 0-sized array)
18359
- enum_constant_data<U> constants[constants_size? constants_size: 1];
18360
- };
18361
-
18362
- /** Class that scans an enum for constants, extracts names & creates entities */
18363
- template <typename E>
18364
- struct enum_type {
18365
- private:
18366
- using U = underlying_type_t<E>;
18367
-
18368
18365
/**
18369
- * @brief Helper struct for filling enum_type's static `enum_data_impl<E>` member with reflection data.
18366
+ * @brief Helper struct for filling enum_type's static `enum_data_impl<E>`
18367
+ * member with reflection data.
18370
18368
*
18371
- * Because reflection occurs in-order, we can use current value/last value to determine continuity, and
18372
- * use that as a lookup heuristic later on.
18369
+ * Because reflection occurs in-order, we can use current value/last value
18370
+ * to determine continuity, and use that as a lookup heuristic later on.
18373
18371
*/
18374
18372
struct reflection_init {
18375
- template <U Value, flecs::if_not_t< enum_constant_is_valid_wrap<E, Value>() > = 0>
18376
- static U handle_constant(U last_value, flecs::world_t*) {
18373
+ template <U Value,
18374
+ flecs::if_not_t< enum_constant_is_valid_wrap<E, Value>() > = 0>
18375
+ static U handle_constant(U last_value, This&) {
18377
18376
// Search for constant failed. Pass last valid value through.
18378
18377
return last_value;
18379
18378
}
18380
18379
18381
- template <U Value, flecs::if_t< enum_constant_is_valid_wrap<E, Value>() > = 0>
18382
- static U handle_constant(U last_value, flecs::world_t *world) {
18380
+ template <U Value,
18381
+ flecs::if_t< enum_constant_is_valid_wrap<E, Value>() > = 0>
18382
+ static U handle_constant(U last_value, This& me) {
18383
18383
// Constant is valid, so fill reflection data.
18384
18384
auto v = Value;
18385
18385
const char *name = enum_constant_to_name<E, flecs_enum_cast(E, Value)>();
18386
18386
18387
- ++enum_type<E>::data .max; // Increment cursor as we build constants array.
18387
+ ++me .max; // Increment cursor as we build constants array.
18388
18388
18389
- // If the enum was previously contiguous, and continues to be through the current value...
18390
- if (enum_type<E>::data.has_contiguous && static_cast<U>(enum_type<E>::data.max) == v && enum_type<E>::data.contiguous_until == v) {
18391
- ++enum_type<E>::data.contiguous_until;
18389
+ // If the enum was previously contiguous, and continues to be
18390
+ // through the current value...
18391
+ if (me.has_contiguous && static_cast<U>(me.max) == v && me.contiguous_until == v) {
18392
+ ++me.contiguous_until;
18392
18393
}
18393
- // else, if the enum was never contiguous and hasn't been set as not contiguous...
18394
- else if (!enum_type<E>::data.contiguous_until && enum_type<E>::data.has_contiguous) {
18395
- enum_type<E>::data.has_contiguous = false;
18394
+
18395
+ // else, if the enum was never contiguous and hasn't been set as not
18396
+ // contiguous...
18397
+ else if (!me.contiguous_until && me.has_contiguous) {
18398
+ me.has_contiguous = false;
18396
18399
}
18397
18400
18398
- ecs_assert(!(last_value > 0 && v < std::numeric_limits<U>::min() + last_value), ECS_UNSUPPORTED,
18399
- "Signed integer enums causes integer overflow when recording offset from high positive to"
18400
- " low negative. Consider using unsigned integers as underlying type.");
18401
- enum_type<E>::data.constants[enum_type<E>::data.max].offset = v - last_value;
18402
- if (!enum_type<E>::data.constants[enum_type<E>::data.max].index) {
18403
- enum_type<E>::data.constants[enum_type<E>::data.max].index =
18401
+ ecs_assert(!(last_value > 0 &&
18402
+ v < std::numeric_limits<U>::min() + last_value),
18403
+ ECS_UNSUPPORTED,
18404
+ "Signed integer enums causes integer overflow when recording "
18405
+ "offset from high positive to low negative. Consider using "
18406
+ "unsigned integers as underlying type.");
18407
+
18408
+ me.constants[me.max].value = v;
18409
+ me.constants[me.max].offset = v - last_value;
18410
+ me.constants[me.max].name = name;
18411
+ if (!me.constants[me.max].index) {
18412
+ me.constants[me.max].index =
18404
18413
flecs_component_ids_index_get();
18405
18414
}
18406
-
18407
- flecs::entity_t constant = ecs_cpp_enum_constant_register(
18408
- world, type<E>::id(world), 0, name, &v, type<U>::id(world), sizeof(U));
18409
- flecs_component_ids_set(world,
18410
- enum_type<E>::data.constants[enum_type<E>::data.max].index,
18411
- constant);
18412
18415
18413
18416
return v;
18414
18417
}
18415
18418
};
18416
18419
public:
18417
18420
18418
- static enum_data_impl<E> data;
18421
+ enum_type() {
18422
+ // Initialize/reset reflection data values to default state.
18423
+ min = 0;
18424
+ max = -1;
18425
+ has_contiguous = true;
18426
+ contiguous_until = 0;
18427
+
18428
+ enum_reflection<E, reflection_init>::
18429
+ template each_enum< static_cast<U>(enum_last<E>::value) >(*this);
18430
+ }
18419
18431
18420
18432
static enum_type<E>& get() {
18421
18433
static _::enum_type<E> instance;
@@ -18425,37 +18437,53 @@ struct enum_type {
18425
18437
flecs::entity_t entity(E value) const {
18426
18438
int index = index_by_value(value);
18427
18439
if (index >= 0) {
18428
- return data. constants[index].id;
18440
+ return constants[index].id;
18429
18441
}
18430
18442
return 0;
18431
18443
}
18432
18444
18433
- void init (flecs::world_t *world, flecs::entity_t id) {
18445
+ void register_for_world (flecs::world_t *world, flecs::entity_t id) {
18434
18446
#if !FLECS_CPP_ENUM_REFLECTION_SUPPORT
18435
18447
ecs_abort(ECS_UNSUPPORTED, "enum reflection requires gcc 7.5 or higher")
18436
18448
#endif
18437
- // Initialize/reset reflection data values to default state.
18438
- data.min = 0;
18439
- data.max = -1;
18440
- data.has_contiguous = true;
18441
- data.contiguous_until = 0;
18442
18449
18443
18450
ecs_log_push();
18444
18451
ecs_cpp_enum_init(world, id, type<U>::id(world));
18445
- // data.id = id;
18446
18452
18447
- // Generate reflection data
18448
- enum_reflection<E, reflection_init>::template each_enum< static_cast<U>(enum_last<E>::value) >(world);
18453
+ for (U v = 0; v < static_cast<U>(max + 1); v ++) {
18454
+ if (constants[v].index) {
18455
+ flecs::entity_t constant = ecs_cpp_enum_constant_register(world,
18456
+ type<E>::id(world), 0, constants[v].name, &constants[v].value,
18457
+ type<U>::id(world), sizeof(U));
18458
+
18459
+ flecs_component_ids_set(world, constants[v].index, constant);
18460
+ }
18461
+ }
18462
+
18449
18463
ecs_log_pop();
18450
18464
}
18451
- };
18452
18465
18453
- template <typename E>
18454
- enum_data_impl<E> enum_type<E>::data;
18466
+ int min;
18467
+ int max;
18468
+ bool has_contiguous;
18469
+
18470
+ // If enum constants start not-sparse, contiguous_until will be the index of
18471
+ // the first sparse value, or end of the constants array
18472
+ U contiguous_until;
18473
+
18474
+ // Compile-time generated count of enum constants.
18475
+ static constexpr unsigned int constants_size =
18476
+ enum_reflection<E, reflection_count>::
18477
+ template each_enum< static_cast<U>(enum_last<E>::value) >();
18478
+
18479
+ // Constants array is sized to the number of found-constants, or 1
18480
+ // to avoid 0-sized array
18481
+ enum_constant<U> constants[constants_size? constants_size: 1] = {};
18482
+ };
18455
18483
18456
18484
template <typename E, if_t< is_enum<E>::value > = 0>
18457
18485
inline static void init_enum(flecs::world_t *world, flecs::entity_t id) {
18458
- _::enum_type<E>::get().init (world, id);
18486
+ _::enum_type<E>::get().register_for_world (world, id);
18459
18487
}
18460
18488
18461
18489
template <typename E, if_not_t< is_enum<E>::value > = 0>
@@ -18468,7 +18496,7 @@ template <typename E>
18468
18496
struct enum_data {
18469
18497
using U = underlying_type_t<E>;
18470
18498
18471
- enum_data(flecs::world_t *world, _::enum_data_impl <E>& impl)
18499
+ enum_data(flecs::world_t *world, _::enum_type <E>& impl)
18472
18500
: world_(world)
18473
18501
, impl_(impl) { }
18474
18502
@@ -18549,15 +18577,15 @@ struct enum_data {
18549
18577
flecs::entity entity(E value) const;
18550
18578
18551
18579
flecs::world_t *world_;
18552
- _::enum_data_impl <E>& impl_;
18580
+ _::enum_type <E>& impl_;
18553
18581
};
18554
18582
18555
18583
/** Convenience function for getting enum reflection data */
18556
18584
template <typename E>
18557
18585
enum_data<E> enum_type(flecs::world_t *world) {
18558
18586
_::type<E>::id(world); // Ensure enum is registered
18559
18587
auto& ref = _::enum_type<E>::get();
18560
- return enum_data<E>(world, ref.data );
18588
+ return enum_data<E>(world, ref);
18561
18589
}
18562
18590
18563
18591
} // namespace flecs
0 commit comments