Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions include/zephyr/sys/util_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,47 @@
/* Used to remove brackets from around a single argument. */
#define __DEBRACKET(...) __VA_ARGS__

/* Used by COND_CASE_1(); supports up to 16 flag/value pairs */
#define Z_COND_CASE_1(...) \
Z_COND_CASE_1_CAT_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__)

#define Z_COND_CASE_1_CAT_N(count_minus_one, ...) \
UTIL_CAT(Z_COND_CASE_1_N_, count_minus_one)(__VA_ARGS__)

#define Z_COND_CASE_1_N_0(_default) __DEBRACKET _default
#define Z_COND_CASE_1_N_2(flag0, value0, _default) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (__DEBRACKET _default))
#define Z_COND_CASE_1_N_4(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_2(__VA_ARGS__)))
#define Z_COND_CASE_1_N_6(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_4(__VA_ARGS__)))
#define Z_COND_CASE_1_N_8(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_6(__VA_ARGS__)))
#define Z_COND_CASE_1_N_10(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_8(__VA_ARGS__)))
#define Z_COND_CASE_1_N_12(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_10(__VA_ARGS__)))
#define Z_COND_CASE_1_N_14(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_12(__VA_ARGS__)))
#define Z_COND_CASE_1_N_16(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_14(__VA_ARGS__)))
#define Z_COND_CASE_1_N_18(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_16(__VA_ARGS__)))
#define Z_COND_CASE_1_N_20(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_18(__VA_ARGS__)))
#define Z_COND_CASE_1_N_22(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_20(__VA_ARGS__)))
#define Z_COND_CASE_1_N_24(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_22(__VA_ARGS__)))
#define Z_COND_CASE_1_N_26(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_24(__VA_ARGS__)))
#define Z_COND_CASE_1_N_28(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_26(__VA_ARGS__)))
#define Z_COND_CASE_1_N_30(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_28(__VA_ARGS__)))
#define Z_COND_CASE_1_N_32(flag0, value0, ...) \
Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_30(__VA_ARGS__)))

/* Used by IS_EMPTY() */
/* reference: https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/ */
#define Z_HAS_COMMA(...) \
Expand Down
25 changes: 25 additions & 0 deletions include/zephyr/sys/util_macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,31 @@ extern "C" {
#define COND_CODE_0(_flag, _if_0_code, _else_code) \
Z_COND_CODE_0(_flag, _if_0_code, _else_code)

/**
* @brief Evaluate a list of COND_CODE_1-style cases.
*
* Each case consists of a flag and a value wrapped in parentheses. The
* arguments are processed from left to right until a flag expands to the
* literal 1, in which case the corresponding value is expanded. If no flags
* expand to 1, the last argument (which must also be wrapped in parentheses)
* is used as the default value. Supplying only the default argument is also
* supported.
*
* Example:
*
* int foo = COND_CASE_1(CONFIG_SOME_BOOL, (handle_a()),
* CONFIG_SOME_OTHER_BOOL, (handle_b()),
* (handle_default()));
*
* Supports up to 16 flag/value pairs before the default.
*
* @param ... Flag/value pairs followed by the default value. Each value must
* be provided in parentheses to avoid comma handling issues.
* @see COND_CODE_1()
*/
#define COND_CASE_1(...) \
Z_COND_CASE_1(__VA_ARGS__)

/**
* @brief Insert code if @p _flag is defined and equals 1.
*
Expand Down
31 changes: 31 additions & 0 deletions tests/unit/util/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,37 @@ ZTEST(util, test_COND_CODE_0) {
zassert_true((y3 == 1));
}

ZTEST(util, test_COND_CASE_1) {
/* Intentionally undefined symbols used to verify that only the selected
* branch expands.
*/
int val;

#define CASE_TRUE 1
#define CASE_FALSE 0

val = COND_CASE_1(CASE_TRUE, (42),
CASE_TRUE, (COND_CASE_1_SHOULD_NOT_REACH_SECOND_TRUE_CASE),
(0));
zexpect_equal(val, 42);

val = COND_CASE_1(CASE_FALSE, (COND_CASE_1_SHOULD_NOT_USE_FIRST_CASE),
CASE_TRUE, (7),
(11));
zexpect_equal(val, 7);

val = COND_CASE_1(CASE_FALSE, (COND_CASE_1_SHOULD_NOT_USE_SECOND_CASE),
CASE_FALSE, (COND_CASE_1_SHOULD_NOT_USE_THIRD_CASE),
(5));
zexpect_equal(val, 5);

val = COND_CASE_1((9));
zexpect_equal(val, 9);

#undef CASE_TRUE
#undef CASE_FALSE
}

#undef ZERO
#undef SEVEN
#undef A_BUILD_ERROR
Expand Down