Home | History | Annotate | Download | only in rpc
      1 #ifndef ANDROID_PDX_RPC_MACROS_H_
      2 #define ANDROID_PDX_RPC_MACROS_H_
      3 
      4 // Macros to apply other macros over all elements in a list.
      5 //
      6 // For example, for a macro A(x) and B(x, y):
      7 // - FOR_EACH(A, 1, 2, 3) -> A(1) A(2) A(3).
      8 // - FOR_EACH_BINARY(B, z, 1, 2, 3) -> B(z, 1) B(z, 2) B(z, 3)
      9 // - FOR_EACH_LIST(A, 1, 2, 3) -> A(1), B(2), C(3)
     10 // - FOR_EACH_BINARY_LIST(B, z, 1, 2, 3) -> B(z, 1), B(z, 2), B(z, 3)
     11 //
     12 // Empty lists are supported and will produce no output.
     13 
     14 // Recursive expansion macros.
     15 #define _PDX_EXPAND0(...) __VA_ARGS__
     16 #define _PDX_EXPAND1(...) _PDX_EXPAND0(_PDX_EXPAND0(_PDX_EXPAND0(__VA_ARGS__)))
     17 #define _PDX_EXPAND2(...) _PDX_EXPAND1(_PDX_EXPAND1(_PDX_EXPAND1(__VA_ARGS__)))
     18 #define _PDX_EXPAND3(...) _PDX_EXPAND2(_PDX_EXPAND2(_PDX_EXPAND2(__VA_ARGS__)))
     19 #define _PDX_EXPAND4(...) _PDX_EXPAND3(_PDX_EXPAND3(_PDX_EXPAND3(__VA_ARGS__)))
     20 #define _PDX_EXPAND(...) _PDX_EXPAND4(_PDX_EXPAND4(_PDX_EXPAND4(__VA_ARGS__)))
     21 
     22 // Required to workaround a bug in the VC++ preprocessor.
     23 #define _PDX_INDIRECT_EXPAND(macro, args) macro args
     24 
     25 // Defines a step separation for macro expansion.
     26 #define _PDX_SEPARATOR
     27 
     28 // Clears any remaining contents wrapped in parentheses.
     29 #define _PDX_CLEAR(...)
     30 
     31 // Introduces a first dummy argument and _PDX_CLEAR as second argument.
     32 #define _PDX_CLEAR_IF_LAST() _, _PDX_CLEAR
     33 
     34 // Returns the first argument of a list.
     35 #define _PDX_FIRST_ARG(first, ...) first
     36 
     37 // Returns the second argument of a list.
     38 #define _PDX_SECOND_ARG(_, second, ...) second
     39 
     40 // Expands the arguments and introduces a separator.
     41 #define _PDX_EXPAND_NEXT_FUNC(_, next_func, ...)        \
     42   _PDX_INDIRECT_EXPAND(_PDX_SECOND_ARG, (_, next_func)) \
     43   _PDX_SEPARATOR
     44 
     45 // Returns next_func if the next element is not (), or _PDX_CLEAR
     46 // otherwise.
     47 //
     48 // _PDX_CLEAR_IF_LAST inserts an extra first dummy argument if peek is ().
     49 #define _PDX_NEXT_FUNC(next_element, next_func) \
     50   _PDX_EXPAND_NEXT_FUNC(_PDX_CLEAR_IF_LAST next_element, next_func)
     51 
     52 // Macros for the unary version of PDX_FOR_EACH.
     53 
     54 // Applies the unary macro. Duplicated for macro recursive expansion.
     55 #define _PDX_APPLY_1(macro, head, next, ...) \
     56   macro(head) _PDX_NEXT_FUNC(next, _PDX_APPLY_2)(macro, next, __VA_ARGS__)
     57 
     58 // Applies the unary macro. Duplicated for macro recursive expansion.
     59 #define _PDX_APPLY_2(macro, head, next, ...) \
     60   macro(head) _PDX_NEXT_FUNC(next, _PDX_APPLY_1)(macro, next, __VA_ARGS__)
     61 
     62 // Stops expansion if __VA_ARGS__ is empty, calling _PDX_APPLY_1
     63 // otherwise.
     64 #define _PDX_HANDLE_EMPTY_ARGS(macro, ...)                    \
     65   _PDX_NEXT_FUNC(_PDX_FIRST_ARG(__VA_ARGS__()), _PDX_APPLY_1) \
     66   (macro, __VA_ARGS__, ())
     67 
     68 // Applies a unary macro over all the elements in a list.
     69 #define PDX_FOR_EACH(macro, ...) \
     70   _PDX_EXPAND(_PDX_HANDLE_EMPTY_ARGS(macro, __VA_ARGS__))
     71 
     72 // Applies the unary macro at the end of a list. Duplicated for macro recursive
     73 // expansion.
     74 #define _PDX_APPLY_LIST_1(macro, head, next, ...) \
     75   , macro(head)                                   \
     76         _PDX_NEXT_FUNC(next, _PDX_APPLY_LIST_2)(macro, next, __VA_ARGS__)
     77 
     78 // Applies the unary macro at the end of a list. Duplicated for macro recursive
     79 // expansion.
     80 #define _PDX_APPLY_LIST_2(macro, head, next, ...) \
     81   , macro(head)                                   \
     82         _PDX_NEXT_FUNC(next, _PDX_APPLY_LIST_1)(macro, next, __VA_ARGS__)
     83 
     84 // Applies the unary macro at the start of a list.
     85 #define _PDX_APPLY_LIST_0(macro, head, next, ...) \
     86   macro(head) _PDX_NEXT_FUNC(next, _PDX_APPLY_LIST_1)(macro, next, __VA_ARGS__)
     87 
     88 // Stops expansion if __VA_ARGS__ is empty, calling _PDX_APPLY_LIST_0
     89 // otherwise.
     90 #define _PDX_HANDLE_EMPTY_LIST(macro, ...)                         \
     91   _PDX_NEXT_FUNC(_PDX_FIRST_ARG(__VA_ARGS__()), _PDX_APPLY_LIST_0) \
     92   (macro, __VA_ARGS__, ())
     93 
     94 // Applies a unary macro over all the elements in a list.
     95 #define PDX_FOR_EACH_LIST(macro, ...) \
     96   _PDX_EXPAND(_PDX_HANDLE_EMPTY_LIST(macro, __VA_ARGS__))
     97 
     98 // Macros for the binary version of PDX_FOR_EACH.
     99 
    100 // Applies the binary macro. Duplicated for macro recursive expansion.
    101 #define _PDX_APPLY_BINARY_1(macro, arg, head, next, ...) \
    102   macro(arg, head)                                       \
    103       _PDX_NEXT_FUNC(next, _PDX_APPLY_BINARY_2)(macro, arg, next, __VA_ARGS__)
    104 
    105 // Applies the binary macro. Duplicated for macro recursive expansion.
    106 #define _PDX_APPLY_BINARY_2(macro, arg, head, next, ...) \
    107   macro(arg, head)                                       \
    108       _PDX_NEXT_FUNC(next, _PDX_APPLY_BINARY_1)(macro, arg, next, __VA_ARGS__)
    109 
    110 // Version of _PDX_HANDLE_EMPTY_ARGS that takes 1 fixed argument for a
    111 // binary macro.
    112 #define _PDX_HANDLE_EMPTY_ARGS_BINARY(macro, arg, ...)               \
    113   _PDX_NEXT_FUNC(_PDX_FIRST_ARG(__VA_ARGS__()), _PDX_APPLY_BINARY_1) \
    114   (macro, arg, __VA_ARGS__, ())
    115 
    116 // Applies a binary macro over all the elements in a list and a given argument.
    117 #define PDX_FOR_EACH_BINARY(macro, arg, ...) \
    118   _PDX_EXPAND(_PDX_HANDLE_EMPTY_ARGS_BINARY(macro, arg, __VA_ARGS__))
    119 
    120 // Applies the binary macro at the end of a list. Duplicated for macro recursive
    121 // expansion.
    122 #define _PDX_APPLY_BINARY_LIST_1(macro, arg, head, next, ...)        \
    123   , macro(arg, head) _PDX_NEXT_FUNC(next, _PDX_APPLY_BINARY_LIST_2)( \
    124         macro, arg, next, __VA_ARGS__)
    125 
    126 // Applies the binary macro at the end of a list. Duplicated for macro recursive
    127 // expansion.
    128 #define _PDX_APPLY_BINARY_LIST_2(macro, arg, head, next, ...)        \
    129   , macro(arg, head) _PDX_NEXT_FUNC(next, _PDX_APPLY_BINARY_LIST_1)( \
    130         macro, arg, next, __VA_ARGS__)
    131 
    132 // Applies the binary macro at the start of a list. Duplicated for macro
    133 // recursive expansion.
    134 #define _PDX_APPLY_BINARY_LIST_0(macro, arg, head, next, ...)      \
    135   macro(arg, head) _PDX_NEXT_FUNC(next, _PDX_APPLY_BINARY_LIST_1)( \
    136       macro, arg, next, __VA_ARGS__)
    137 
    138 // Version of _PDX_HANDLE_EMPTY_LIST that takes 1 fixed argument for a
    139 // binary macro.
    140 #define _PDX_HANDLE_EMPTY_LIST_BINARY(macro, arg, ...)                    \
    141   _PDX_NEXT_FUNC(_PDX_FIRST_ARG(__VA_ARGS__()), _PDX_APPLY_BINARY_LIST_0) \
    142   (macro, arg, __VA_ARGS__, ())
    143 
    144 // Applies a binary macro over all the elements in a list and a given argument.
    145 #define PDX_FOR_EACH_BINARY_LIST(macro, arg, ...) \
    146   _PDX_EXPAND(_PDX_HANDLE_EMPTY_LIST_BINARY(macro, arg, __VA_ARGS__))
    147 
    148 #endif  // ANDROID_PDX_RPC_MACROS_H_
    149