sys: util: Add GET_ARG_N and GET_ARGS_LESS_N macros

Macro GET_ARG_N is geting nth argument from the variable list provided.
GET_ARGS_LESS_N returns argument list without n first arguments.

Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruscinski 2020-05-08 10:35:06 +02:00 committed by Carles Cufí
commit c58b80d805
2 changed files with 64 additions and 6 deletions

View file

@ -534,8 +534,28 @@ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value);
*/
#define EMPTY
/**
* @brief Get nth argument from argument list.
*
* @param N Argument index to fetch. Counter from 1.
* @param ... Variable list of argments from which one argument is returned.
*
* @return Nth argument.
*/
#define GET_ARG_N(N, ...) _Z_GET_ARG_N(N, 1, __VA_ARGS__)
/**
* @brief Strips n first arguments from the argument list.
*
* @param N Number of arguments to discard.
* @param ... Variable list of argments.
*
* @return argument list without N first arguments.
*/
#define GET_ARGS_LESS_N(N, ...) _Z_GET_ARG_N(UTIL_INC(N), 0, __VA_ARGS__)
/** @brief Expands to @p arg1 */
#define GET_ARG1(arg1, ...) arg1
#define GET_ARG1(...) GET_ARG_N(1, )
/** @brief Expands to @p arg2 */
#define GET_ARG2(arg1, arg2, ...) arg2

View file

@ -67,8 +67,7 @@
/* Used by IS_EMPTY() */
#define Z_IS_EMPTY_(...) Z_IS_EMPTY__(__VA_ARGS__)
#define Z_IS_EMPTY__(a, ...) Z_IS_EMPTY___(_ZZ##a##ZZ0, __VA_ARGS__)
#define Z_IS_EMPTY___(...) Z_IS_EMPTY____(GET_ARGS_LESS_1(__VA_ARGS__))
#define Z_IS_EMPTY____(...) GET_ARG2(__VA_ARGS__)
#define Z_IS_EMPTY___(...) GET_ARG_N(3, __VA_ARGS__)
/* Used by LIST_DROP_EMPTY() */
/* Adding ',' after each element would add empty element at the end of
@ -76,7 +75,7 @@
* this way first element is empty, and this one is easy to drop.
*/
#define Z_LIST_ADD_ELEM(e) EMPTY, e
#define Z_LIST_DROP_FIRST(...) GET_ARGS_LESS_1(__VA_ARGS__)
#define Z_LIST_DROP_FIRST(...) GET_ARGS_LESS_N(1, __VA_ARGS__)
#define Z_LIST_NO_EMPTIES(e) \
COND_CODE_1(IS_EMPTY(e), (), (Z_LIST_ADD_ELEM(e)))
@ -678,16 +677,19 @@
( \
UTIL_OBSTRUCT(macro) \
( \
fixed_arg0, fixed_arg1, n, GET_ARG1(__VA_ARGS__)\
fixed_arg0, fixed_arg1, n, Z_GET_ARG1(__VA_ARGS__)\
) COND_CODE_1(count, (), (__DEBRACKET sep)) \
UTIL_OBSTRUCT(Z_FOR_EACH_IDX_INDIRECT) () \
( \
UTIL_DEC(count), UTIL_INC(n), macro, sep, \
fixed_arg0, fixed_arg1, \
GET_ARGS_LESS_1(__VA_ARGS__) \
Z_GET_ARGS_LESS_1(__VA_ARGS__) \
) \
)
#define Z_GET_ARG1(arg1, ...) arg1
#define Z_GET_ARGS_LESS_1(arg1, ...) __VA_ARGS__
#define Z_FOR_EACH_IDX_INDIRECT() Z_FOR_EACH_IDX
#define Z_FOR_EACH_IDX2(count, iter, macro, sc, fixed_arg0, fixed_arg1, ...) \
@ -702,6 +704,42 @@
#define Z_FOR_EACH_SWALLOW_INDEX_FIXED_ARG(F, fixed_arg, index, arg) F(arg)
#define Z_FOR_EACH_SWALLOW_INDEX(F, fixed_arg, index, arg) F(arg, fixed_arg)
/* This is a workaround to enable mixing GET_ARG_N with FOR_EACH macros. If
* same UTIL_EVAL macro is used then macro is incorrectly resolved.
*/
#define Z_GET_ARG_N_EVAL(...) \
Z_GET_ARG_N_EVAL1(Z_GET_ARG_N_EVAL1(Z_GET_ARG_N_EVAL1(__VA_ARGS__)))
#define Z_GET_ARG_N_EVAL1(...) \
Z_GET_ARG_N_EVAL2(Z_GET_ARG_N_EVAL2(Z_GET_ARG_N_EVAL2(__VA_ARGS__)))
#define Z_GET_ARG_N_EVAL2(...) \
Z_GET_ARG_N_EVAL3(Z_GET_ARG_N_EVAL3(Z_GET_ARG_N_EVAL3(__VA_ARGS__)))
#define Z_GET_ARG_N_EVAL3(...) \
Z_GET_ARG_N_EVAL4(Z_GET_ARG_N_EVAL4(Z_GET_ARG_N_EVAL4(__VA_ARGS__)))
#define Z_GET_ARG_N_EVAL4(...) \
Z_GET_ARG_N_EVAL5(Z_GET_ARG_N_EVAL5(Z_GET_ARG_N_EVAL5(__VA_ARGS__)))
#define Z_GET_ARG_N_EVAL5(...) __VA_ARGS__
/* Set of internal macros used for GET_ARG_N of macros. */
#define Z_GET_ARG_N(count, single_arg, ...) \
UTIL_WHEN(count) \
( \
IF_ENABLED(count, (UTIL_OBSTRUCT(__DEBRACKET) \
( \
COND_CODE_1(single_arg, \
(Z_GET_ARG1(__VA_ARGS__)), (__VA_ARGS__))\
))) \
UTIL_OBSTRUCT(Z_GET_ARG_N_INDIRECT) () \
( \
UTIL_DEC(count), single_arg, \
Z_GET_ARGS_LESS_1(__VA_ARGS__) \
) \
)
#define Z_GET_ARG_N_INDIRECT() Z_GET_ARG_N
#define _Z_GET_ARG_N(N, single_arg, ...) \
Z_GET_ARG_N_EVAL(Z_GET_ARG_N(N, single_arg, __VA_ARGS__))
/* Implementation details for NUM_VA_ARGS_LESS_1 */
#define NUM_VA_ARGS_LESS_1_IMPL( \
_ignored, \