damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

cppmagic.h (6228B)


      1 /* MIT (BSD) license - see LICENSE file for details */
      2 #ifndef CCAN_CPPMAGIC_H
      3 #define CCAN_CPPMAGIC_H
      4 
      5 /**
      6  * CPPMAGIC_NOTHING - expands to nothing
      7  */
      8 #define CPPMAGIC_NOTHING()
      9 
     10 /**
     11  * CPPMAGIC_STRINGIFY - convert arguments to a string literal
     12  */
     13 #define _CPPMAGIC_STRINGIFY(...)    #__VA_ARGS__
     14 #define CPPMAGIC_STRINGIFY(...)        _CPPMAGIC_STRINGIFY(__VA_ARGS__)
     15 
     16 /**
     17  * CPPMAGIC_GLUE2 - glue arguments together
     18  *
     19  * CPPMAGIC_GLUE2(@a_, @b_)
     20  *    expands to the expansion of @a_ followed immediately
     21  *    (combining tokens) by the expansion of @b_
     22  */
     23 #define _CPPMAGIC_GLUE2(a_, b_)        a_##b_
     24 #define CPPMAGIC_GLUE2(a_, b_)        _CPPMAGIC_GLUE2(a_, b_)
     25 
     26 /**
     27  * CPPMAGIC_1ST - return 1st argument
     28  *
     29  * CPPMAGIC_1ST(@a_, ...)
     30  *    expands to the expansion of @a_
     31  */
     32 #define CPPMAGIC_1ST(a_, ...)        a_
     33 
     34 /**
     35  * CPPMAGIC_2ND - return 2nd argument
     36  *
     37  * CPPMAGIC_2ST(@a_, @b_, ...)
     38  *    expands to the expansion of @b_
     39  */
     40 #define CPPMAGIC_2ND(a_, b_, ...)    b_
     41 
     42 /**
     43  * CPPMAGIC_ISZERO - is argument '0'
     44  *
     45  * CPPMAGIC_ISZERO(@a)
     46  *    expands to '1' if @a is '0', otherwise expands to '0'.
     47  */
     48 #define _CPPMAGIC_ISPROBE(...)        CPPMAGIC_2ND(__VA_ARGS__, 0)
     49 #define _CPPMAGIC_PROBE()        $, 1
     50 #define _CPPMAGIC_ISZERO_0        _CPPMAGIC_PROBE()
     51 #define CPPMAGIC_ISZERO(a_)        \
     52     _CPPMAGIC_ISPROBE(CPPMAGIC_GLUE2(_CPPMAGIC_ISZERO_, a_))
     53 
     54 /**
     55  * CPPMAGIC_NONZERO - is argument not '0'
     56  *
     57  * CPPMAGIC_NONZERO(@a)
     58  *    expands to '0' if @a is '0', otherwise expands to '1'.
     59  */
     60 #define CPPMAGIC_NONZERO(a_)        CPPMAGIC_ISZERO(CPPMAGIC_ISZERO(a_))
     61 
     62 /**
     63  * CPPMAGIC_NONEMPTY - does the macro have any arguments?
     64  *
     65  * CPPMAGIC_NONEMPTY()
     66  *     expands to '0'
     67  * CPPMAGIC_NONEMPTY(@a)
     68  * CPPMAGIC_NONEMPTY(@a, ...)
     69  *     expand to '1'
     70  */
     71 #define _CPPMAGIC_EOA()            0
     72 #define CPPMAGIC_NONEMPTY(...)        \
     73     CPPMAGIC_NONZERO(CPPMAGIC_1ST(_CPPMAGIC_EOA __VA_ARGS__)())
     74 
     75 /**
     76  * CPPMAGIC_ISEMPTY - does the macro have no arguments?
     77  *
     78  * CPPMAGIC_ISEMPTY()
     79  *     expands to '1'
     80  * CPPMAGIC_ISEMPTY(@a)
     81  * CPPMAGIC_ISEMPTY(@a, ...)
     82  *     expand to '0'
     83  */
     84 #define CPPMAGIC_ISEMPTY(...)        \
     85     CPPMAGIC_ISZERO(CPPMAGIC_NONEMPTY(__VA_ARGS__))
     86 
     87 /*
     88  * CPPMAGIC_IFELSE - preprocessor conditional
     89  *
     90  * CPPMAGIC_IFELSE(@cond)(@if)(@else)
     91  *    expands to @else if @cond is '0', otherwise expands to @if
     92  */
     93 #define _CPPMAGIC_IF_0(...)        _CPPMAGIC_IF_0_ELSE
     94 #define _CPPMAGIC_IF_1(...)        __VA_ARGS__ _CPPMAGIC_IF_1_ELSE
     95 #define _CPPMAGIC_IF_0_ELSE(...)    __VA_ARGS__
     96 #define _CPPMAGIC_IF_1_ELSE(...)
     97 #define _CPPMAGIC_IFELSE(cond_)        CPPMAGIC_GLUE2(_CPPMAGIC_IF_, cond_)
     98 #define CPPMAGIC_IFELSE(cond_)        \
     99     _CPPMAGIC_IFELSE(CPPMAGIC_NONZERO(cond_))
    100 
    101 /**
    102  * CPPMAGIC_EVAL - force multiple expansion passes
    103  *
    104  * Forces macros in the arguments to be expanded repeatedly (up to
    105  * 1024 times) even when CPP would usually stop expanding.
    106  */
    107 #define CPPMAGIC_EVAL1(...)        __VA_ARGS__
    108 #define CPPMAGIC_EVAL2(...)        \
    109     CPPMAGIC_EVAL1(CPPMAGIC_EVAL1(__VA_ARGS__))
    110 #define CPPMAGIC_EVAL4(...)        \
    111     CPPMAGIC_EVAL2(CPPMAGIC_EVAL2(__VA_ARGS__))
    112 #define CPPMAGIC_EVAL8(...)        \
    113     CPPMAGIC_EVAL4(CPPMAGIC_EVAL4(__VA_ARGS__))
    114 #define CPPMAGIC_EVAL16(...)        \
    115     CPPMAGIC_EVAL8(CPPMAGIC_EVAL8(__VA_ARGS__))
    116 #define CPPMAGIC_EVAL32(...)        \
    117     CPPMAGIC_EVAL16(CPPMAGIC_EVAL16(__VA_ARGS__))
    118 #define CPPMAGIC_EVAL64(...)        \
    119     CPPMAGIC_EVAL32(CPPMAGIC_EVAL32(__VA_ARGS__))
    120 #define CPPMAGIC_EVAL128(...)        \
    121     CPPMAGIC_EVAL64(CPPMAGIC_EVAL64(__VA_ARGS__))
    122 #define CPPMAGIC_EVAL256(...)        \
    123     CPPMAGIC_EVAL128(CPPMAGIC_EVAL128(__VA_ARGS__))
    124 #define CPPMAGIC_EVAL512(...)        \
    125     CPPMAGIC_EVAL256(CPPMAGIC_EVAL256(__VA_ARGS__))
    126 #define CPPMAGIC_EVAL1024(...)        \
    127     CPPMAGIC_EVAL512(CPPMAGIC_EVAL512(__VA_ARGS__))
    128 #define CPPMAGIC_EVAL(...)        CPPMAGIC_EVAL1024(__VA_ARGS__)
    129 
    130 /**
    131  * CPPMAGIC_DEFER1, CPPMAGIC_DEFER2 - defer expansion
    132  */
    133 #define CPPMAGIC_DEFER1(a_)    a_ CPPMAGIC_NOTHING()
    134 #define CPPMAGIC_DEFER2(a_)    a_ CPPMAGIC_NOTHING CPPMAGIC_NOTHING()()
    135 
    136 /**
    137  * CPPMAGIC_MAP - iterate another macro across arguments
    138  * @m: name of a one argument macro
    139  *
    140  * CPPMAGIC_MAP(@m, @a1, @a2, ... @an)
    141  *    expands to the expansion of @m(@a1) , @m(@a2) , ... , @m(@an)
    142  */
    143 #define _CPPMAGIC_MAP_()        _CPPMAGIC_MAP
    144 #define _CPPMAGIC_MAP(m_, a_, ...)                    \
    145     m_(a_)                                \
    146     CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__))            \
    147         (, CPPMAGIC_DEFER2(_CPPMAGIC_MAP_)()(m_, __VA_ARGS__))    \
    148         ()
    149 #define CPPMAGIC_MAP(m_, ...)                        \
    150     CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__))            \
    151         (CPPMAGIC_EVAL(_CPPMAGIC_MAP(m_, __VA_ARGS__)))        \
    152         ()
    153 
    154 /**
    155  * CPPMAGIC_2MAP - iterate another macro across pairs of arguments
    156  * @m: name of a two argument macro
    157  *
    158  * CPPMAGIC_2MAP(@m, @a1, @b1, @a2, @b2, ..., @an, @bn)
    159  *    expands to the expansion of
    160  *         @m(@a1, @b1) , @m(@a2, @b2) , ... , @m(@an, @bn)
    161  */
    162 #define _CPPMAGIC_2MAP_()        _CPPMAGIC_2MAP
    163 #define _CPPMAGIC_2MAP(m_, a_, b_, ...)                \
    164     m_(a_, b_)                            \
    165     CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__))            \
    166         (, CPPMAGIC_DEFER2(_CPPMAGIC_2MAP_)()(m_, __VA_ARGS__)) \
    167         ()
    168 #define CPPMAGIC_2MAP(m_, ...)                    \
    169     CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__))            \
    170         (CPPMAGIC_EVAL(_CPPMAGIC_2MAP(m_, __VA_ARGS__)))    \
    171         ()
    172 
    173 /**
    174  * CPPMAGIC_JOIN - separate arguments with given delimiter
    175  * @d: delimiter
    176  *
    177  * CPPMAGIC_JOIN(@d, @a1, @a2, ..., @an)
    178  *    expands to the expansion of @a1 @d @a2 @d ... @d @an
    179  */
    180 #define _CPPMAGIC_JOIN_()        _CPPMAGIC_JOIN
    181 #define _CPPMAGIC_JOIN(d_, a_, ...)                    \
    182     a_                                \
    183     CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__))            \
    184         (d_ CPPMAGIC_DEFER2(_CPPMAGIC_JOIN_)()(d_, __VA_ARGS__)) \
    185         ()
    186 #define CPPMAGIC_JOIN(d_, ...)                    \
    187     CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__))            \
    188         (CPPMAGIC_EVAL(_CPPMAGIC_JOIN(d_, __VA_ARGS__)))    \
    189         ()
    190 
    191 #endif /* CCAN_CPPMAGIC_H */