13#define FLECS_ENUM_MAX(T) _::to_constant<T, 126>::value
14#define FLECS_ENUM_MAX_COUNT (FLECS_ENUM_MAX(int) + 1)
17#ifdef FLECS_CPP_NO_ENUM_REFLECTION
18#define FLECS_CPP_ENUM_REFLECTION_SUPPORT 0
22#ifndef FLECS_CPP_ENUM_REFLECTION_SUPPORT
23#if !defined(__clang__) && defined(__GNUC__)
24#if __GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 5)
25#define FLECS_CPP_ENUM_REFLECTION_SUPPORT 1
27#define FLECS_CPP_ENUM_REFLECTION_SUPPORT 0
30#define FLECS_CPP_ENUM_REFLECTION_SUPPORT 1
34#if defined(__clang__) && __clang_major__ >= 16
36#define flecs_enum_cast(T, v) __builtin_bit_cast(T, v)
37#elif defined(__GNUC__) && __GNUC__ > 10
38#define flecs_enum_cast(T, v) __builtin_bit_cast(T, v)
40#define flecs_enum_cast(T, v) static_cast<T>(v)
48template <
typename E, underlying_type_t<E> Value>
50 static constexpr E value = flecs_enum_cast(E, Value);
53template <
typename E, underlying_type_t<E> Value>
54constexpr E to_constant<E, Value>::value;
74 static constexpr E value = FLECS_ENUM_MAX(E);
78#define FLECS_ENUM_LAST(T, Last)\
81 struct enum_last<T> {\
82 static constexpr T value = Last;\
88#if defined(ECS_TARGET_CLANG) || defined(ECS_TARGET_GNU)
89template <
typename E, E C>
90constexpr bool enum_constant_is_valid() {
91 const char *name = ECS_FUNC_NAME;
92 size_t pos =
sizeof(ECS_FUNC_NAME) - 1;
93 while (pos && name[pos - 1] !=
'=') {
96 while (name[pos] ==
' ') {
99 return name[pos] !=
'(' && name[pos] !=
'-' &&
100 !(name[pos] >=
'0' && name[pos] <=
'9');
104constexpr size_t enum_template_arg_separator(
105 const char (&func_name)[N],
112 : func_name[pos] ==
'<'
113 ? enum_template_arg_separator(func_name, pos + 1, end, depth + 1)
114 : func_name[pos] ==
'>'
115 ? enum_template_arg_separator(
116 func_name, pos + 1, end, depth ? depth - 1 : 0)
117 : (func_name[pos] ==
',' && !depth)
119 : enum_template_arg_separator(
120 func_name, pos + 1, end, depth);
127template <
typename E, E C>
128constexpr bool enum_constant_is_valid() {
129 return enum_template_arg_separator(
131 ECS_FUNC_NAME_FRONT(
bool, enum_constant_is_valid),
132 sizeof(ECS_FUNC_NAME) - ECS_FUNC_NAME_BACK - 1u) <
133 (
sizeof(ECS_FUNC_NAME) - ECS_FUNC_NAME_BACK - 1u) &&
134 ECS_FUNC_NAME[enum_template_arg_separator(
136 ECS_FUNC_NAME_FRONT(
bool, enum_constant_is_valid),
137 sizeof(ECS_FUNC_NAME) - ECS_FUNC_NAME_BACK - 1u) + 1u] !=
'(';
142template <
typename E, underlying_type_t<E> C>
143constexpr bool enum_constant_is_valid_wrap() {
144 return enum_constant_is_valid<E, flecs_enum_cast(E, C)>();
148template <
typename E, E C>
149struct enum_is_valid {
150 static constexpr bool value = enum_constant_is_valid<E, C>();
154template <
typename E, E C>
155static const char* enum_constant_to_name() {
156 static const size_t len = ECS_FUNC_TYPE_LEN(
157 const char*, enum_constant_to_name, ECS_FUNC_NAME);
158 static char result[len + 1] = {};
169#ifdef FLECS_MULTI_WORLD
181 bool discovered()
const {
182#ifdef FLECS_MULTI_WORLD
185 return name !=
nullptr ||
id != 0;
194 using U = underlying_type_t<E>;
195 using UU =
typename std::make_unsigned<U>::type;
196 static constexpr size_t linear_count =
197 static_cast<size_t>(enum_last<E>::value) + 1;
199 static constexpr size_t mask_start() {
201 for (UU v =
static_cast<UU
>(enum_last<E>::value); v; v >>= 1) {
207 using candidates = std::make_index_sequence<
208 linear_count +
sizeof(U) * 8 - mask_start()>;
211 static constexpr U candidate() {
212 if constexpr (I < linear_count) {
213 return static_cast<U
>(I);
215 return static_cast<U
>(UU(1) << (I - linear_count + mask_start()));
219 template <
size_t... I>
220 static constexpr unsigned int count_constants(std::index_sequence<I...>) {
221 bool valid[] = {enum_constant_is_valid_wrap<E, candidate<I>()>()...};
222 unsigned int result = 0;
223 for (
bool value : valid) {
230 void add_constant() {
231 if constexpr (enum_constant_is_valid_wrap<E, Value>()) {
233 if (
static_cast<U
>(max) == Value && contiguous_until == max) {
237 constant.
name = enum_constant_to_name<E, flecs_enum_cast(E, Value)>();
238#ifdef FLECS_MULTI_WORLD
239 constant.index = flecs_component_ids_index_get();
244 template <
size_t... I>
245 void init(std::index_sequence<I...>) {
246 int result[] = {(add_constant<candidate<I>()>(), 0)...};
252#if FLECS_CPP_ENUM_REFLECTION_SUPPORT
257 int index_by_value(U value)
const {
258#ifdef FLECS_CPP_NO_ENUM_REFLECTION
259 return value >= 0 &&
static_cast<UU
>(value) <
static_cast<UU
>(contiguous_until)
260 ?
static_cast<int>(value) : -1;
262 if (value >= 0 &&
static_cast<UU
>(value) <
static_cast<UU
>(contiguous_until)) {
263 return static_cast<int>(value);
265 for (
int i = contiguous_until; i <= max; i ++) {
266 if (constants[i].value == value) {
275 static enum_type<E>& get() {
276 static _::enum_type<E> instance;
280#ifndef FLECS_MULTI_WORLD
283 int index = index_by_value(
static_cast<U
>(value));
285 return constants[index].id;
293#if !FLECS_CPP_ENUM_REFLECTION_SUPPORT
300 for (
int v = 0; v <= max; v ++) {
301 if (constants[v].discovered()) {
303 type<E>::id(world), 0, constants[v].name, &constants[v].value,
304 type<U>::id(world),
sizeof(U));
306#ifdef FLECS_MULTI_WORLD
307 flecs_component_ids_set(world, constants[v].index,
constant);
319 int contiguous_until = 0;
321#if FLECS_CPP_ENUM_REFLECTION_SUPPORT
322 static constexpr unsigned int constants_size = count_constants(candidates{});
323 enum_constant<U> constants[constants_size ? constants_size : 1] = {};
325 static constexpr unsigned int constants_size = 0;
326 enum_constant<U> constants[128] = {};
333 (void)world; (void)
id;
334 if constexpr (is_enum_v<E>) {
335 _::enum_type<E>::get().register_for_world(world,
id);
344 using U = underlying_type_t<E>;
363 return impl_.constants[index].discovered();
374 return is_valid(
static_cast<U
>(value));
384 return impl_.index_by_value(value);
425 #ifdef FLECS_CPP_NO_ENUM_REFLECTION
427 if (v >= 0 && v < 128) {
428 int index =
static_cast<int>(v);
429#ifdef FLECS_MULTI_WORLD
430 if (!impl_.constants[index].index) {
431 impl_.constants[index].index = flecs_component_ids_index_get();
435#ifdef FLECS_MULTI_WORLD
436 flecs_component_ids_set(world, impl_.constants[index].index, e);
439 impl_.constants[index].id = e;
444 if (impl_.contiguous_until <= index) {
445 impl_.contiguous_until = index + 1;
452 _::enum_type<E>& impl_;
459 auto&
ref = _::enum_type<E>::get();
FLECS_API void ecs_cpp_enum_init(ecs_world_t *world, ecs_entity_t id, ecs_entity_t underlying_type)
Initialize a C++ enum type.
FLECS_API ecs_entity_t ecs_cpp_enum_constant_register(ecs_world_t *world, ecs_entity_t parent, ecs_entity_t id, const char *name, void *value, ecs_entity_t value_type, size_t value_size)
Register a C++ enum constant.
FLECS_API char * ecs_cpp_get_constant_name(char *constant_name, const char *func_name, size_t len, size_t back_len)
Get constant name from compiler-generated function name.
#define ECS_UNSUPPORTED
Unsupported error code.
#define ecs_log_push()
Push log indentation at the default level.
#define ecs_abort(error_code,...)
Abort.
#define ecs_log_pop()
Pop log indentation at the default level.
ecs_entity_t entity_t
Entity type.
ecs_world_t world_t
World type.
Enumeration constant data.
const char * name
The constant name.
int32_t index
Global index used to obtain a world-local entity ID.
T value
The constant value.
flecs::string_view name() const
Return the entity name.
entity()
Default constructor.
Convenience type with enum reflection data.
int last() const
Return the index of the last constant.
int next(int cur) const
Return the next constant index after the given one.
int index_by_value(E value) const
Find the index into the constants array for an enum value, if one exists.
bool is_valid(U value)
Check if a given integral value is a valid enum value.
enum_data(flecs::world_t *world, _::enum_type< E > &impl)
Construct enum_data from a world and an enum_type implementation.
flecs::world_t * world_
Manually register a constant for an enum.
int index_by_value(U value) const
Find the index into the constants array for a value, if one exists.
bool is_valid(E value)
Check if a given enum value is valid.
int first() const
Return the index of the first constant.
Trait to define the last valid enum value for reflection.
Class that wraps around a flecs::id_t.
std::size_t length() const
Return the string length.