mirror of https://github.com/lukechilds/damus.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
6.1 KiB
191 lines
6.1 KiB
/* MIT (BSD) license - see LICENSE file for details */
|
|
#ifndef CCAN_CPPMAGIC_H
|
|
#define CCAN_CPPMAGIC_H
|
|
|
|
/**
|
|
* CPPMAGIC_NOTHING - expands to nothing
|
|
*/
|
|
#define CPPMAGIC_NOTHING()
|
|
|
|
/**
|
|
* CPPMAGIC_STRINGIFY - convert arguments to a string literal
|
|
*/
|
|
#define _CPPMAGIC_STRINGIFY(...) #__VA_ARGS__
|
|
#define CPPMAGIC_STRINGIFY(...) _CPPMAGIC_STRINGIFY(__VA_ARGS__)
|
|
|
|
/**
|
|
* CPPMAGIC_GLUE2 - glue arguments together
|
|
*
|
|
* CPPMAGIC_GLUE2(@a_, @b_)
|
|
* expands to the expansion of @a_ followed immediately
|
|
* (combining tokens) by the expansion of @b_
|
|
*/
|
|
#define _CPPMAGIC_GLUE2(a_, b_) a_##b_
|
|
#define CPPMAGIC_GLUE2(a_, b_) _CPPMAGIC_GLUE2(a_, b_)
|
|
|
|
/**
|
|
* CPPMAGIC_1ST - return 1st argument
|
|
*
|
|
* CPPMAGIC_1ST(@a_, ...)
|
|
* expands to the expansion of @a_
|
|
*/
|
|
#define CPPMAGIC_1ST(a_, ...) a_
|
|
|
|
/**
|
|
* CPPMAGIC_2ND - return 2nd argument
|
|
*
|
|
* CPPMAGIC_2ST(@a_, @b_, ...)
|
|
* expands to the expansion of @b_
|
|
*/
|
|
#define CPPMAGIC_2ND(a_, b_, ...) b_
|
|
|
|
/**
|
|
* CPPMAGIC_ISZERO - is argument '0'
|
|
*
|
|
* CPPMAGIC_ISZERO(@a)
|
|
* expands to '1' if @a is '0', otherwise expands to '0'.
|
|
*/
|
|
#define _CPPMAGIC_ISPROBE(...) CPPMAGIC_2ND(__VA_ARGS__, 0)
|
|
#define _CPPMAGIC_PROBE() $, 1
|
|
#define _CPPMAGIC_ISZERO_0 _CPPMAGIC_PROBE()
|
|
#define CPPMAGIC_ISZERO(a_) \
|
|
_CPPMAGIC_ISPROBE(CPPMAGIC_GLUE2(_CPPMAGIC_ISZERO_, a_))
|
|
|
|
/**
|
|
* CPPMAGIC_NONZERO - is argument not '0'
|
|
*
|
|
* CPPMAGIC_NONZERO(@a)
|
|
* expands to '0' if @a is '0', otherwise expands to '1'.
|
|
*/
|
|
#define CPPMAGIC_NONZERO(a_) CPPMAGIC_ISZERO(CPPMAGIC_ISZERO(a_))
|
|
|
|
/**
|
|
* CPPMAGIC_NONEMPTY - does the macro have any arguments?
|
|
*
|
|
* CPPMAGIC_NONEMPTY()
|
|
* expands to '0'
|
|
* CPPMAGIC_NONEMPTY(@a)
|
|
* CPPMAGIC_NONEMPTY(@a, ...)
|
|
* expand to '1'
|
|
*/
|
|
#define _CPPMAGIC_EOA() 0
|
|
#define CPPMAGIC_NONEMPTY(...) \
|
|
CPPMAGIC_NONZERO(CPPMAGIC_1ST(_CPPMAGIC_EOA __VA_ARGS__)())
|
|
|
|
/**
|
|
* CPPMAGIC_ISEMPTY - does the macro have no arguments?
|
|
*
|
|
* CPPMAGIC_ISEMPTY()
|
|
* expands to '1'
|
|
* CPPMAGIC_ISEMPTY(@a)
|
|
* CPPMAGIC_ISEMPTY(@a, ...)
|
|
* expand to '0'
|
|
*/
|
|
#define CPPMAGIC_ISEMPTY(...) \
|
|
CPPMAGIC_ISZERO(CPPMAGIC_NONEMPTY(__VA_ARGS__))
|
|
|
|
/*
|
|
* CPPMAGIC_IFELSE - preprocessor conditional
|
|
*
|
|
* CPPMAGIC_IFELSE(@cond)(@if)(@else)
|
|
* expands to @else if @cond is '0', otherwise expands to @if
|
|
*/
|
|
#define _CPPMAGIC_IF_0(...) _CPPMAGIC_IF_0_ELSE
|
|
#define _CPPMAGIC_IF_1(...) __VA_ARGS__ _CPPMAGIC_IF_1_ELSE
|
|
#define _CPPMAGIC_IF_0_ELSE(...) __VA_ARGS__
|
|
#define _CPPMAGIC_IF_1_ELSE(...)
|
|
#define _CPPMAGIC_IFELSE(cond_) CPPMAGIC_GLUE2(_CPPMAGIC_IF_, cond_)
|
|
#define CPPMAGIC_IFELSE(cond_) \
|
|
_CPPMAGIC_IFELSE(CPPMAGIC_NONZERO(cond_))
|
|
|
|
/**
|
|
* CPPMAGIC_EVAL - force multiple expansion passes
|
|
*
|
|
* Forces macros in the arguments to be expanded repeatedly (up to
|
|
* 1024 times) even when CPP would usually stop expanding.
|
|
*/
|
|
#define CPPMAGIC_EVAL1(...) __VA_ARGS__
|
|
#define CPPMAGIC_EVAL2(...) \
|
|
CPPMAGIC_EVAL1(CPPMAGIC_EVAL1(__VA_ARGS__))
|
|
#define CPPMAGIC_EVAL4(...) \
|
|
CPPMAGIC_EVAL2(CPPMAGIC_EVAL2(__VA_ARGS__))
|
|
#define CPPMAGIC_EVAL8(...) \
|
|
CPPMAGIC_EVAL4(CPPMAGIC_EVAL4(__VA_ARGS__))
|
|
#define CPPMAGIC_EVAL16(...) \
|
|
CPPMAGIC_EVAL8(CPPMAGIC_EVAL8(__VA_ARGS__))
|
|
#define CPPMAGIC_EVAL32(...) \
|
|
CPPMAGIC_EVAL16(CPPMAGIC_EVAL16(__VA_ARGS__))
|
|
#define CPPMAGIC_EVAL64(...) \
|
|
CPPMAGIC_EVAL32(CPPMAGIC_EVAL32(__VA_ARGS__))
|
|
#define CPPMAGIC_EVAL128(...) \
|
|
CPPMAGIC_EVAL64(CPPMAGIC_EVAL64(__VA_ARGS__))
|
|
#define CPPMAGIC_EVAL256(...) \
|
|
CPPMAGIC_EVAL128(CPPMAGIC_EVAL128(__VA_ARGS__))
|
|
#define CPPMAGIC_EVAL512(...) \
|
|
CPPMAGIC_EVAL256(CPPMAGIC_EVAL256(__VA_ARGS__))
|
|
#define CPPMAGIC_EVAL1024(...) \
|
|
CPPMAGIC_EVAL512(CPPMAGIC_EVAL512(__VA_ARGS__))
|
|
#define CPPMAGIC_EVAL(...) CPPMAGIC_EVAL1024(__VA_ARGS__)
|
|
|
|
/**
|
|
* CPPMAGIC_DEFER1, CPPMAGIC_DEFER2 - defer expansion
|
|
*/
|
|
#define CPPMAGIC_DEFER1(a_) a_ CPPMAGIC_NOTHING()
|
|
#define CPPMAGIC_DEFER2(a_) a_ CPPMAGIC_NOTHING CPPMAGIC_NOTHING()()
|
|
|
|
/**
|
|
* CPPMAGIC_MAP - iterate another macro across arguments
|
|
* @m: name of a one argument macro
|
|
*
|
|
* CPPMAGIC_MAP(@m, @a1, @a2, ... @an)
|
|
* expands to the expansion of @m(@a1) , @m(@a2) , ... , @m(@an)
|
|
*/
|
|
#define _CPPMAGIC_MAP_() _CPPMAGIC_MAP
|
|
#define _CPPMAGIC_MAP(m_, a_, ...) \
|
|
m_(a_) \
|
|
CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
|
|
(, CPPMAGIC_DEFER2(_CPPMAGIC_MAP_)()(m_, __VA_ARGS__)) \
|
|
()
|
|
#define CPPMAGIC_MAP(m_, ...) \
|
|
CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
|
|
(CPPMAGIC_EVAL(_CPPMAGIC_MAP(m_, __VA_ARGS__))) \
|
|
()
|
|
|
|
/**
|
|
* CPPMAGIC_2MAP - iterate another macro across pairs of arguments
|
|
* @m: name of a two argument macro
|
|
*
|
|
* CPPMAGIC_2MAP(@m, @a1, @b1, @a2, @b2, ..., @an, @bn)
|
|
* expands to the expansion of
|
|
* @m(@a1, @b1) , @m(@a2, @b2) , ... , @m(@an, @bn)
|
|
*/
|
|
#define _CPPMAGIC_2MAP_() _CPPMAGIC_2MAP
|
|
#define _CPPMAGIC_2MAP(m_, a_, b_, ...) \
|
|
m_(a_, b_) \
|
|
CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
|
|
(, CPPMAGIC_DEFER2(_CPPMAGIC_2MAP_)()(m_, __VA_ARGS__)) \
|
|
()
|
|
#define CPPMAGIC_2MAP(m_, ...) \
|
|
CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
|
|
(CPPMAGIC_EVAL(_CPPMAGIC_2MAP(m_, __VA_ARGS__))) \
|
|
()
|
|
|
|
/**
|
|
* CPPMAGIC_JOIN - separate arguments with given delimiter
|
|
* @d: delimiter
|
|
*
|
|
* CPPMAGIC_JOIN(@d, @a1, @a2, ..., @an)
|
|
* expands to the expansion of @a1 @d @a2 @d ... @d @an
|
|
*/
|
|
#define _CPPMAGIC_JOIN_() _CPPMAGIC_JOIN
|
|
#define _CPPMAGIC_JOIN(d_, a_, ...) \
|
|
a_ \
|
|
CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
|
|
(d_ CPPMAGIC_DEFER2(_CPPMAGIC_JOIN_)()(d_, __VA_ARGS__)) \
|
|
()
|
|
#define CPPMAGIC_JOIN(d_, ...) \
|
|
CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
|
|
(CPPMAGIC_EVAL(_CPPMAGIC_JOIN(d_, __VA_ARGS__))) \
|
|
()
|
|
|
|
#endif /* CCAN_CPPMAGIC_H */
|
|
|