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