esphome-ratgdo/components/ratgdo/macros.h

90 lines
3.9 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; \
} \
}
#define SUM_TYPE_UNION_MEMBER0(type, var) type var;
#define SUM_TYPE_UNION_MEMBER(name, tuple) SUM_TYPE_UNION_MEMBER0 tuple
#define SUM_TYPE_ENUM_MEMBER0(type, var) var,
#define SUM_TYPE_ENUM_MEMBER(name, tuple) SUM_TYPE_ENUM_MEMBER0 tuple
#define SUM_TYPE_CONSTRUCTOR0(name, type, val) \
name(type&& arg) \
: tag(Tag::val) \
{ \
value.val = std::move(arg); \
}
#define SUM_TYPE_CONSTRUCTOR(name, tuple) SUM_TYPE_CONSTRUCTOR0 LPAREN name, TUPLE tuple)
#define SUM_TYPE(name, ...) \
class name { \
public: \
union { \
FOR_EACH(SUM_TYPE_UNION_MEMBER, name, __VA_ARGS__) \
} value; \
enum class Tag { \
void_, \
FOR_EACH(SUM_TYPE_ENUM_MEMBER, name, __VA_ARGS__) \
} tag; \
\
name() \
: tag(Tag::void_) \
{ \
} \
FOR_EACH(SUM_TYPE_CONSTRUCTOR, name, __VA_ARGS__) \
};