Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 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 | |
Peiyong Lin | d8460c8 | 2020-07-28 16:04:22 -0700 | [diff] [blame] | 31 | // Introduces a first stub argument and _PDX_CLEAR as second argument. |
Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 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 | // |
Peiyong Lin | d8460c8 | 2020-07-28 16:04:22 -0700 | [diff] [blame] | 48 | // _PDX_CLEAR_IF_LAST inserts an extra first stub argument if peek is (). |
Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 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_ |