58 lines
2.4 KiB
C
58 lines
2.4 KiB
C
|
|
||
|
|
||
|
#define PARENS ()
|
||
|
|
||
|
// Rescan macro tokens 256 times
|
||
|
#define EXPAND(...) EXPAND4(EXPAND4(EXPAND4(EXPAND4(__VA_ARGS__))))
|
||
|
#define EXPAND4(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__))))
|
||
|
#define EXPAND3(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__))))
|
||
|
#define EXPAND2(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__))))
|
||
|
#define EXPAND1(...) __VA_ARGS__
|
||
|
|
||
|
#define FOR_EACH(macro, name, ...) \
|
||
|
__VA_OPT__(EXPAND(FOR_EACH_HELPER(macro, name, __VA_ARGS__)))
|
||
|
#define FOR_EACH_HELPER(macro, name, a1, ...) \
|
||
|
macro(name, a1) \
|
||
|
__VA_OPT__(FOR_EACH_AGAIN PARENS(macro, name, __VA_ARGS__))
|
||
|
#define FOR_EACH_AGAIN() FOR_EACH_HELPER
|
||
|
|
||
|
#define ENUM_VARIANT0(name, val) name = val,
|
||
|
#define ENUM_VARIANT(name, tuple) ENUM_VARIANT0 tuple
|
||
|
|
||
|
#define TUPLE(x, y) x, y
|
||
|
|
||
|
#define LPAREN (
|
||
|
|
||
|
#define TO_STRING_CASE0(type, name, val) \
|
||
|
case type::name: \
|
||
|
return #name;
|
||
|
#define TO_STRING_CASE(type, tuple) TO_STRING_CASE0 LPAREN type, TUPLE tuple)
|
||
|
|
||
|
#define FROM_INT_CASE0(type, name, val) \
|
||
|
case val: \
|
||
|
return type::name;
|
||
|
#define FROM_INT_CASE(type, tuple) FROM_INT_CASE0 LPAREN type, TUPLE tuple)
|
||
|
|
||
|
#define ENUM(name, type, ...) \
|
||
|
enum class name : type { \
|
||
|
FOR_EACH(ENUM_VARIANT, name, __VA_ARGS__) \
|
||
|
}; \
|
||
|
inline const char* \
|
||
|
name##_to_string(name _e) \
|
||
|
{ \
|
||
|
switch (_e) { \
|
||
|
FOR_EACH(TO_STRING_CASE, name, __VA_ARGS__) \
|
||
|
default: \
|
||
|
return "UNKNOWN"; \
|
||
|
} \
|
||
|
} \
|
||
|
inline name \
|
||
|
to_##name(type _t, name _unknown) \
|
||
|
{ \
|
||
|
switch (_t) { \
|
||
|
FOR_EACH(FROM_INT_CASE, name, __VA_ARGS__) \
|
||
|
default: \
|
||
|
return _unknown; \
|
||
|
} \
|
||
|
}
|