diff --git a/include/sys/util.h b/include/sys/util.h index acec541fa98..bfe3ca42c98 100644 --- a/include/sys/util.h +++ b/include/sys/util.h @@ -711,6 +711,21 @@ u8_t u8_to_dec(char *buf, u8_t buflen, u8_t value); #define UTIL_IF(c) UTIL_IIF(UTIL_BOOL(c)) +/* + * These are like || and &&, but they do evaluation and + * short-circuiting at preprocessor time instead of runtime. + * + * UTIL_OR(foo, bar) is sometimes a replacement for (foo || bar) + * when "bar" is an expression that would cause a build + * error when "foo" is true. + * + * UTIL_AND(foo, bar) is sometimes a replacement for (foo && bar) + * when "bar" is an expression that would cause a build + * error when "foo" is false. + */ +#define UTIL_OR(a, b) COND_CODE_1(UTIL_BOOL(a), (a), (b)) +#define UTIL_AND(a, b) COND_CODE_1(UTIL_BOOL(a), (b), (0)) + #define UTIL_EAT(...) #define UTIL_EXPAND(...) __VA_ARGS__ #define UTIL_WHEN(c) UTIL_IF(c)(UTIL_EXPAND, UTIL_EAT) diff --git a/tests/unit/util/main.c b/tests/unit/util/main.c index 2b6f9c0ef00..7b16fa9e24b 100644 --- a/tests/unit/util/main.c +++ b/tests/unit/util/main.c @@ -110,6 +110,39 @@ void test_COND_CODE_0(void) zassert_true((y3 == 1), NULL); } +#undef ZERO +#undef SEVEN +#undef A_BUILD_ERROR +#define ZERO 0 +#define SEVEN 7 +#define A_BUILD_ERROR (this would be a build error if you used || or &&) + +void test_UTIL_OR(void) +{ + zassert_equal(UTIL_OR(SEVEN, A_BUILD_ERROR), 7, NULL); + zassert_equal(UTIL_OR(7, 0), 7, NULL); + zassert_equal(UTIL_OR(SEVEN, ZERO), 7, NULL); + zassert_equal(UTIL_OR(0, 7), 7, NULL); + zassert_equal(UTIL_OR(ZERO, SEVEN), 7, NULL); + zassert_equal(UTIL_OR(0, 0), 0, NULL); + zassert_equal(UTIL_OR(ZERO, ZERO), 0, NULL); +} + +void test_UTIL_AND(void) +{ + zassert_equal(UTIL_AND(ZERO, A_BUILD_ERROR), 0, NULL); + zassert_equal(UTIL_AND(7, 0), 0, NULL); + zassert_equal(UTIL_AND(SEVEN, ZERO), 0, NULL); + zassert_equal(UTIL_AND(0, 7), 0, NULL); + zassert_equal(UTIL_AND(ZERO, SEVEN), 0, NULL); + zassert_equal(UTIL_AND(0, 0), 0, NULL); + zassert_equal(UTIL_AND(ZERO, ZERO), 0, NULL); + zassert_equal(UTIL_AND(7, 7), 7, NULL); + zassert_equal(UTIL_AND(7, SEVEN), 7, NULL); + zassert_equal(UTIL_AND(SEVEN, 7), 7, NULL); + zassert_equal(UTIL_AND(SEVEN, SEVEN), 7, NULL); +} + void test_IF_ENABLED(void) { #define test_IF_ENABLED_FLAG_A 1 @@ -190,6 +223,8 @@ void test_main(void) ztest_unit_test(test_u8_to_dec), ztest_unit_test(test_COND_CODE_1), ztest_unit_test(test_COND_CODE_0), + ztest_unit_test(test_UTIL_OR), + ztest_unit_test(test_UTIL_AND), ztest_unit_test(test_IF_ENABLED), ztest_unit_test(test_UTIL_LISTIFY), ztest_unit_test(test_MACRO_MAP_CAT),