Skip to content

Commit 90e614d

Browse files
committed
[nrf fromlist] sys: util_macro: Add UTIL_CONCAT_AND and UTIL_CONCAT_OR
-Add macro UTIL_CONCAT_AND which does a concatenation of a variable list of arguments with && between the arguments. This macro uses primitive concatenation and doesn't try to process them in the preprocessor -Add macro UTIL_CONCAT_OR which does a concatenation of a variable list of arguments with && between the arguments. This macro uses primitive concatenation and doesn't try to process them in the preprocessor -Added unit tests for UTIL_CONCAT_AND and UTIL_CONCAT_OR Signed-off-by: Frank Audun Kvamtrø <frank.kvamtro@nordicsemi.no> (cherry picked from commit f69266b8b529a9fe751e50767e745e696c216003)
1 parent 714945e commit 90e614d

File tree

3 files changed

+182
-0
lines changed

3 files changed

+182
-0
lines changed

include/zephyr/sys/util_internal.h

+78
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,84 @@
334334
#define UTIL_EXPAND(...) __VA_ARGS__
335335
#define UTIL_REPEAT(...) UTIL_LISTIFY(__VA_ARGS__)
336336

337+
#define UTIL_AND_CAT(a, b) a && b
338+
/* Used by UTIL_CONCAT_AND */
339+
#define Z_UTIL_CONCAT_AND(...) \
340+
(Z_UTIL_CONCAT_AND_N(NUM_VA_ARGS(__VA_ARGS__), __VA_ARGS__))
341+
#define Z_UTIL_CONCAT_AND_N(N, ...) UTIL_CAT(Z_UTIL_CONCAT_AND_, N)(__VA_ARGS__)
342+
#define Z_UTIL_CONCAT_AND_0
343+
#define Z_UTIL_CONCAT_AND_1(a, ...) a
344+
#define Z_UTIL_CONCAT_AND_2(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_1(__VA_ARGS__,))
345+
#define Z_UTIL_CONCAT_AND_3(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_2(__VA_ARGS__,))
346+
#define Z_UTIL_CONCAT_AND_4(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_3(__VA_ARGS__,))
347+
#define Z_UTIL_CONCAT_AND_5(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_4(__VA_ARGS__,))
348+
#define Z_UTIL_CONCAT_AND_6(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_5(__VA_ARGS__,))
349+
#define Z_UTIL_CONCAT_AND_7(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_6(__VA_ARGS__,))
350+
#define Z_UTIL_CONCAT_AND_8(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_7(__VA_ARGS__,))
351+
#define Z_UTIL_CONCAT_AND_9(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_8(__VA_ARGS__,))
352+
#define Z_UTIL_CONCAT_AND_10(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_9(__VA_ARGS__,))
353+
#define Z_UTIL_CONCAT_AND_11(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_10(__VA_ARGS__,))
354+
#define Z_UTIL_CONCAT_AND_12(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_11(__VA_ARGS__,))
355+
#define Z_UTIL_CONCAT_AND_13(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_12(__VA_ARGS__,))
356+
#define Z_UTIL_CONCAT_AND_14(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_13(__VA_ARGS__,))
357+
#define Z_UTIL_CONCAT_AND_15(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_14(__VA_ARGS__,))
358+
#define Z_UTIL_CONCAT_AND_16(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_15(__VA_ARGS__,))
359+
#define Z_UTIL_CONCAT_AND_17(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_16(__VA_ARGS__,))
360+
#define Z_UTIL_CONCAT_AND_18(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_17(__VA_ARGS__,))
361+
#define Z_UTIL_CONCAT_AND_19(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_18(__VA_ARGS__,))
362+
#define Z_UTIL_CONCAT_AND_20(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_19(__VA_ARGS__,))
363+
#define Z_UTIL_CONCAT_AND_21(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_20(__VA_ARGS__,))
364+
#define Z_UTIL_CONCAT_AND_22(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_21(__VA_ARGS__,))
365+
#define Z_UTIL_CONCAT_AND_23(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_22(__VA_ARGS__,))
366+
#define Z_UTIL_CONCAT_AND_24(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_23(__VA_ARGS__,))
367+
#define Z_UTIL_CONCAT_AND_25(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_24(__VA_ARGS__,))
368+
#define Z_UTIL_CONCAT_AND_26(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_25(__VA_ARGS__,))
369+
#define Z_UTIL_CONCAT_AND_27(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_26(__VA_ARGS__,))
370+
#define Z_UTIL_CONCAT_AND_28(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_27(__VA_ARGS__,))
371+
#define Z_UTIL_CONCAT_AND_29(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_28(__VA_ARGS__,))
372+
#define Z_UTIL_CONCAT_AND_30(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_29(__VA_ARGS__,))
373+
#define Z_UTIL_CONCAT_AND_31(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_30(__VA_ARGS__,))
374+
#define Z_UTIL_CONCAT_AND_32(a, ...) UTIL_AND_CAT(a, Z_UTIL_CONCAT_AND_31(__VA_ARGS__,))
375+
376+
#define UTIL_OR_CAT(a, b) a || b
377+
/* Used by UTIL_CONCAT_OR */
378+
#define Z_UTIL_CONCAT_OR(...) \
379+
(Z_UTIL_CONCAT_OR_N(NUM_VA_ARGS(__VA_ARGS__), __VA_ARGS__))
380+
#define Z_UTIL_CONCAT_OR_N(N, ...) UTIL_CAT(Z_UTIL_CONCAT_OR_, N)(__VA_ARGS__)
381+
#define Z_UTIL_CONCAT_OR_0
382+
#define Z_UTIL_CONCAT_OR_1(a, ...) a
383+
#define Z_UTIL_CONCAT_OR_2(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_1(__VA_ARGS__,))
384+
#define Z_UTIL_CONCAT_OR_3(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_2(__VA_ARGS__,))
385+
#define Z_UTIL_CONCAT_OR_4(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_3(__VA_ARGS__,))
386+
#define Z_UTIL_CONCAT_OR_5(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_4(__VA_ARGS__,))
387+
#define Z_UTIL_CONCAT_OR_6(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_5(__VA_ARGS__,))
388+
#define Z_UTIL_CONCAT_OR_7(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_6(__VA_ARGS__,))
389+
#define Z_UTIL_CONCAT_OR_8(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_7(__VA_ARGS__,))
390+
#define Z_UTIL_CONCAT_OR_9(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_8(__VA_ARGS__,))
391+
#define Z_UTIL_CONCAT_OR_10(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_9(__VA_ARGS__,))
392+
#define Z_UTIL_CONCAT_OR_11(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_10(__VA_ARGS__,))
393+
#define Z_UTIL_CONCAT_OR_12(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_11(__VA_ARGS__,))
394+
#define Z_UTIL_CONCAT_OR_13(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_12(__VA_ARGS__,))
395+
#define Z_UTIL_CONCAT_OR_14(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_13(__VA_ARGS__,))
396+
#define Z_UTIL_CONCAT_OR_15(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_14(__VA_ARGS__,))
397+
#define Z_UTIL_CONCAT_OR_16(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_15(__VA_ARGS__,))
398+
#define Z_UTIL_CONCAT_OR_17(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_16(__VA_ARGS__,))
399+
#define Z_UTIL_CONCAT_OR_18(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_17(__VA_ARGS__,))
400+
#define Z_UTIL_CONCAT_OR_19(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_18(__VA_ARGS__,))
401+
#define Z_UTIL_CONCAT_OR_20(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_19(__VA_ARGS__,))
402+
#define Z_UTIL_CONCAT_OR_21(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_20(__VA_ARGS__,))
403+
#define Z_UTIL_CONCAT_OR_22(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_21(__VA_ARGS__,))
404+
#define Z_UTIL_CONCAT_OR_23(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_22(__VA_ARGS__,))
405+
#define Z_UTIL_CONCAT_OR_24(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_23(__VA_ARGS__,))
406+
#define Z_UTIL_CONCAT_OR_25(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_24(__VA_ARGS__,))
407+
#define Z_UTIL_CONCAT_OR_26(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_25(__VA_ARGS__,))
408+
#define Z_UTIL_CONCAT_OR_27(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_26(__VA_ARGS__,))
409+
#define Z_UTIL_CONCAT_OR_28(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_27(__VA_ARGS__,))
410+
#define Z_UTIL_CONCAT_OR_29(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_28(__VA_ARGS__,))
411+
#define Z_UTIL_CONCAT_OR_30(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_29(__VA_ARGS__,))
412+
#define Z_UTIL_CONCAT_OR_31(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_30(__VA_ARGS__,))
413+
#define Z_UTIL_CONCAT_OR_32(a, ...) UTIL_OR_CAT(a, Z_UTIL_CONCAT_OR_31(__VA_ARGS__,))
414+
337415
#define _CONCAT_0(arg, ...) arg
338416
#define _CONCAT_1(arg, ...) UTIL_CAT(arg, _CONCAT_0(__VA_ARGS__))
339417
#define _CONCAT_2(arg, ...) UTIL_CAT(arg, _CONCAT_1(__VA_ARGS__))

include/zephyr/sys/util_macro.h

+23
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,29 @@ extern "C" {
530530
*/
531531
#define UTIL_X2(y) UTIL_PRIMITIVE_CAT(Z_UTIL_X2_, y)
532532

533+
/**
534+
* @brief Concatenates all arguments with "&&" between them into a single token
535+
*
536+
* This macro does primitive concatenation and doesn't try to process the
537+
* parameters in preprocessor.
538+
*
539+
* @param ... Arguments to concatenate with @p && between them
540+
* @return A concatenation of all the arguments with @p || between them or a
541+
* single argument
542+
*/
543+
#define UTIL_CONCAT_AND(...) Z_UTIL_CONCAT_AND(__VA_ARGS__)
544+
545+
/**
546+
* @brief Concatenates all arguments with "||" between them into a single token
547+
*
548+
* This macro does primitive concatenation and doesn't try to process the
549+
* parameters in preprocessor.
550+
*
551+
* @param ... Arguments to concatenate with @p || between them
552+
* @return A concatenation of all the arguments with @p || between them or a
553+
* single argument
554+
*/
555+
#define UTIL_CONCAT_OR(...) Z_UTIL_CONCAT_OR(__VA_ARGS__)
533556

534557
/**
535558
* @brief Generates a sequence of code with configurable separator.

tests/unit/util/main.c

+81
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,87 @@ ZTEST(util, test_UTIL_AND) {
274274
zassert_equal(UTIL_AND(SEVEN, SEVEN), 7);
275275
}
276276

277+
ZTEST(util, test_UTIL_CONCAT_OR) {
278+
#define TEST_FLAG_A 1
279+
#define TEST_FLAG_B 1
280+
#define TEST_FLAG_C 0
281+
#define TEST_FLAG_D 0
282+
#define TEST_VALUE_SEVEN 7
283+
#define TEST_VALUE_ZERO 0
284+
285+
if (!(UTIL_CONCAT_OR(TEST_FLAG_A, TEST_FLAG_B))) {
286+
zassert_false(true, "UTIL_CONCAT_OR failed (all valid)");
287+
}
288+
289+
if (!UTIL_CONCAT_OR(TEST_FLAG_A, TEST_FLAG_C)) {
290+
zassert_false(true, "UTIL_CONCAT_OR failed (one valid)");
291+
}
292+
293+
if (!UTIL_CONCAT_OR(TEST_FLAG_A)) {
294+
zassert_false(true, "UTIL_CONCAT_OR failed (single valid)");
295+
}
296+
297+
if (UTIL_CONCAT_OR(TEST_FLAG_C)) {
298+
zassert_false(true, "UTIL_CONCAT_OR failed (single invalid)");
299+
}
300+
301+
if (!UTIL_CONCAT_OR(TEST_FLAG_C, TEST_FLAG_D, TEST_FLAG_A, TEST_FLAG_B)) {
302+
zassert_false(true, "UTIL_CONCAT_OR failed (negative first)");
303+
}
304+
305+
zassert_equal(1, UTIL_CONCAT_OR(TEST_VALUE_SEVEN, TEST_VALUE_ZERO));
306+
307+
zassert_equal(0, UTIL_CONCAT_OR(TEST_VALUE_ZERO, TEST_VALUE_ZERO,
308+
TEST_VALUE_ZERO));
309+
zassert_true(true, "");
310+
311+
#undef TEST_FLAG_A
312+
#undef TEST_FLAG_B
313+
#undef TEST_FLAG_C
314+
#undef TEST_FLAG_D
315+
#undef TEST_VALUE_SEVEN
316+
#undef TEST_VALUE_ZERO
317+
}
318+
319+
ZTEST(util, test_UTIL_CONCAT_AND) {
320+
#define TEST_FLAG_A 1
321+
#define TEST_FLAG_B 1
322+
#define TEST_FLAG_C 0
323+
#define TEST_FLAG_D 0
324+
#define TEST_VALUE_ZERO 0
325+
#define TEST_VALUE_ONE 1
326+
#define TEST_VALUE_SEVEN 7
327+
328+
if (!UTIL_CONCAT_AND(TEST_FLAG_A, TEST_FLAG_B)) {
329+
zassert_false(true, "UTIL_CONCAT_AND failed (all valid)");
330+
}
331+
332+
if (!UTIL_CONCAT_AND(TEST_FLAG_A)) {
333+
zassert_false(true, "UTIL_CONCAT_AND failed (single valid)");
334+
}
335+
336+
if (UTIL_CONCAT_AND(TEST_FLAG_A, TEST_FLAG_C)) {
337+
zassert_false(true, "UTIL_CONCAT_AND failed (one invalid)");
338+
}
339+
340+
if (UTIL_CONCAT_AND(TEST_FLAG_C, TEST_FLAG_D)) {
341+
zassert_false(true, "UTIL_CONCAT_AND failed (no valid)");
342+
}
343+
344+
zassert_equal(1, UTIL_CONCAT_AND(TEST_VALUE_ONE, TEST_VALUE_SEVEN));
345+
346+
zassert_equal(0,
347+
UTIL_CONCAT_AND(TEST_VALUE_ONE, TEST_VALUE_SEVEN, TEST_VALUE_ZERO));
348+
349+
#undef TEST_FLAG_A
350+
#undef TEST_FLAG_B
351+
#undef TEST_FLAG_C
352+
#undef TEST_FLAG_D
353+
#undef TEST_VALUE_ZERO
354+
#undef TEST_VALUE_ONE
355+
#undef TEST_VALUE_SEVEN
356+
}
357+
277358
ZTEST(util, test_IF_ENABLED) {
278359
#define TEST_FLAG_A 1
279360
#define TEST_FLAG_B 0

0 commit comments

Comments
 (0)