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