12#define FLECS_ENUM_MAX(T) _::to_constant<T, 128>::value
13#define FLECS_ENUM_MAX_COUNT (FLECS_ENUM_MAX(int) + 1)
15#ifndef FLECS_CPP_ENUM_REFLECTION_SUPPORT
16#if !defined(__clang__) && defined(__GNUC__)
17#if __GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 5)
18#define FLECS_CPP_ENUM_REFLECTION_SUPPORT 1
20#define FLECS_CPP_ENUM_REFLECTION_SUPPORT 0
23#define FLECS_CPP_ENUM_REFLECTION_SUPPORT 1
27#if defined(__clang__) && __clang_major__ >= 16
29#define flecs_enum_cast(T, v) __builtin_bit_cast(T, v)
30#elif defined(__GNUC__) && __GNUC__ > 10
31#define flecs_enum_cast(T, v) __builtin_bit_cast(T, v)
33#define flecs_enum_cast(T, v) static_cast<T>(v)
40template <
typename E, underlying_type_t<E> Value>
42 static constexpr E value = flecs_enum_cast(E, Value);
45template <
typename E, underlying_type_t<E> Value>
58 static constexpr E value = FLECS_ENUM_MAX(E);
62#define FLECS_ENUM_LAST(T, Last)\
65 struct enum_last<T> {\
66 static constexpr T value = Last;\
72#if INTPTR_MAX == INT64_MAX
73 #ifdef ECS_TARGET_MSVC
75 #define ECS_SIZE_T_STR "unsigned __int64"
77 #define ECS_SIZE_T_STR "unsigned int"
79 #elif defined(__clang__)
80 #define ECS_SIZE_T_STR "size_t"
82 #ifdef ECS_TARGET_WINDOWS
83 #define ECS_SIZE_T_STR "constexpr size_t; size_t = long long unsigned int"
85 #define ECS_SIZE_T_STR "constexpr size_t; size_t = long unsigned int"
89 #ifdef ECS_TARGET_MSVC
91 #define ECS_SIZE_T_STR "unsigned __int32"
93 #define ECS_SIZE_T_STR "unsigned int"
95 #elif defined(__clang__)
96 #define ECS_SIZE_T_STR "size_t"
98 #ifdef ECS_TARGET_WINDOWS
99 #define ECS_SIZE_T_STR "constexpr size_t; size_t = unsigned int"
101 #define ECS_SIZE_T_STR "constexpr size_t; size_t = unsigned int"
107constexpr size_t enum_type_len() {
108 return ECS_FUNC_TYPE_LEN(, enum_type_len, ECS_FUNC_NAME)
109 - (
sizeof(ECS_SIZE_T_STR) - 1u);
116#if defined(ECS_TARGET_CLANG)
117#if ECS_CLANG_VERSION < 13
118template <
typename E, E C>
122 enum_type_len<E>() + 6 ] >=
'0') &&
124 enum_type_len<E>() + 6 ] <=
'9')) ||
126 enum_type_len<E>() + 6 ] ==
'-'));
129template <
typename E, E C>
132 enum_type_len<E>() + 6 ] !=
'(');
135#elif defined(ECS_TARGET_GNU)
136template <
typename E, E C>
139 enum_type_len<E>() + 8 ] !=
'(');
145template <
typename E, E C>
148 enum_type_len<E>() + 1] !=
'(';
153template <
typename E, underlying_type_t<E> C>
154constexpr bool enum_constant_is_valid_wrap() {
155 return enum_constant_is_valid<E, flecs_enum_cast(E, C)>();
158template <
typename E, E C>
160 static constexpr bool value = enum_constant_is_valid<E, C>();
164template <
typename E, E C>
165static const char* enum_constant_to_name() {
166 static const size_t len = ECS_FUNC_TYPE_LEN(
const char*, enum_constant_to_name, ECS_FUNC_NAME);
167 static char result[len + 1] = {};
168 return ecs_cpp_get_constant_name(
169 result, ECS_FUNC_NAME, string::length(ECS_FUNC_NAME),
190template <
typename E,
typename Handler>
192 using U = underlying_type_t<E>;
208 template <U Low, U High,
typename... Args>
210 return High - Low <= 1
212 ? Handler::template handle_constant<Low>(last_value, args...)
213 : Handler::template handle_constant<High>(Handler::template handle_constant<Low>(last_value, args...), args...)
234 template <U Low, U High,
typename... Args>
237 return (Low & High) || (High <= Low && High != high_bit)
239 : Handler::template handle_constant<High>(
257 template <U Value = static_cast<U>(FLECS_ENUM_MAX(E)),
typename... Args>
259 return each_mask_range<Value, high_bit>(each_enum_range<0, Value>(0, args...), args...);
262 static const U high_bit =
static_cast<U
>(1) << (
sizeof(U) * 8 - 1);
269 using U = underlying_type_t<E>;
274 struct reflection_count {
275 template <U Value, flecs::if_not_t< enum_constant_is_valid_wrap<E, Value>() > = 0>
276 static constexpr U handle_constant(U last_value) {
280 template <U Value, flecs::if_t< enum_constant_is_valid_wrap<E, Value>() > = 0>
281 static constexpr U handle_constant(U last_value) {
282 return 1 + last_value;
303 using U = underlying_type_t<E>;
311 struct reflection_init {
312 template <U Value, flecs::if_not_t< enum_constant_is_valid_wrap<E, Value>() > = 0>
313 static U handle_constant(U last_value, flecs::world_t*) {
318 template <U Value, flecs::if_t< enum_constant_is_valid_wrap<E, Value>() > = 0>
319 static U handle_constant(U last_value, flecs::world_t *
world) {
322 const char *name = enum_constant_to_name<E, flecs_enum_cast(E, Value)>();
335 ecs_assert(!(last_value > 0 && v < std::numeric_limits<U>::min() + last_value), ECS_UNSUPPORTED,
336 "Signed integer enums causes integer overflow when recording offset from high positive to"
337 " low negative. Consider using unsigned integers as underlying type.");
353 flecs::entity_t
entity(E value)
const {
354 int index = index_by_value(value);
356 return data.constants[index].id;
361 void init(flecs::world_t *
world, flecs::entity_t
id) {
362#if !FLECS_CPP_ENUM_REFLECTION_SUPPORT
363 ecs_abort(ECS_UNSUPPORTED,
"enum reflection requires gcc 7.5 or higher")
368 data.has_contiguous =
true;
369 data.contiguous_until = 0;
372 ecs_cpp_enum_init(
world,
id);
384template <typename E, if_t< is_enum<E>::value > = 0>
385inline static void init_enum(flecs::world_t *
world, flecs::entity_t
id) {
389template <typename E, if_not_t< is_enum<E>::value > = 0>
390inline static void init_enum(flecs::world_t*, flecs::entity_t) { }
397 using U = underlying_type_t<E>;
415 return impl_.constants[index].id != 0;
426 return is_valid(
static_cast<U
>(value));
440 if (impl_.has_contiguous && value < impl_.contiguous_until && value >= 0) {
441 return static_cast<int>(value);
443 U accumulator = impl_.contiguous_until? impl_.contiguous_until - 1: 0;
444 for (
int i =
static_cast<int>(impl_.contiguous_until); i <= impl_.max; ++i) {
445 accumulator += impl_.constants[i].offset;
446 if (accumulator == value) {
471 int next(
int cur)
const {
479 flecs::world_t *world_;
480 _::enum_data_impl<E>& impl_;
#define ecs_assert(condition, error_code,...)
Assert.
#define ecs_abort(error_code,...)
Abort.
constexpr bool enum_constant_is_valid()
Test if value is valid for enumeration.
Enumeration constant data.
Provides utilities for enum reflection.
static constexpr U each_mask_range(U last_value, Args... args)
Iterates over the mask range (Low, High] of enum values between Low and High.
static constexpr U each_enum_range(U last_value, Args... args)
Iterates over the range [Low, High] of enum values between Low and High.
static constexpr U each_enum(Args... args)
Handles enum iteration for gathering reflection data.
Class that scans an enum for constants, extracts names & creates entities.
Convenience type with enum reflection data.
int index_by_value(E value) const
Finds the index into the constants array for an enum value, if one exists.
bool is_valid(U value)
Checks if a given integral value is a valid enum value.
int index_by_value(U value) const
Finds the index into the constants array for a value, if one exists.
bool is_valid(E value)
Checks if a given enum value is valid.
Class that wraps around a flecs::id_t.