From: David Gibson Date: Tue, 26 Jan 2016 09:52:32 +0000 (+1100) Subject: cppmagic: Logical operations X-Git-Url: http://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=f92c112c47d4d9271b813fd6478d8d6b4b035e9d cppmagic: Logical operations In order to implement fancier things, we need to represent truth values in cpp. We use '0' and '1' strings, like in C, but we need ways to get these values from other conditions. CPPMAGIC_ISZERO() and CPPMAGIC_NONZERO() test if the argument is '0' or anything else (ISZERO doubles as a logical not). CPPMAGIC_ISEMPTY() and CPPMAGIC_NON_EMPTY() expand to 0 or 1 depending on whether they have any arguments at all or not. Signed-off-by: David Gibson --- diff --git a/ccan/cppmagic/cppmagic.h b/ccan/cppmagic/cppmagic.h index f29e0ec6..c4454e77 100644 --- a/ccan/cppmagic/cppmagic.h +++ b/ccan/cppmagic/cppmagic.h @@ -39,4 +39,49 @@ */ #define CPPMAGIC_2ND(a_, b_, ...) b_ +/** + * CPPMAGIC_ISZERO - is argument '0' + * + * CPPMAGIC_ISZERO(@a) + * expands to '1' if @a is '0', otherwise expands to '0'. + */ +#define _CPPMAGIC_ISPROBE(...) CPPMAGIC_2ND(__VA_ARGS__, 0) +#define _CPPMAGIC_PROBE() $, 1 +#define _CPPMAGIC_ISZERO_0 _CPPMAGIC_PROBE() +#define CPPMAGIC_ISZERO(a_) \ + _CPPMAGIC_ISPROBE(CPPMAGIC_GLUE2(_CPPMAGIC_ISZERO_, a_)) + +/** + * CPPMAGIC_NONZERO - is argument not '0' + * + * CPPMAGIC_NONZERO(@a) + * expands to '0' if @a is '0', otherwise expands to '1'. + */ +#define CPPMAGIC_NONZERO(a_) CPPMAGIC_ISZERO(CPPMAGIC_ISZERO(a_)) + +/** + * CPPMAGIC_NONEMPTY - does the macro have any arguments? + * + * CPPMAGIC_NONEMPTY() + * expands to '0' + * CPPMAGIC_NONEMPTY(@a) + * CPPMAGIC_NONEMPTY(@a, ...) + * expand to '1' + */ +#define _CPPMAGIC_EOA() 0 +#define CPPMAGIC_NONEMPTY(...) \ + CPPMAGIC_NONZERO(CPPMAGIC_1ST(_CPPMAGIC_EOA __VA_ARGS__)()) + +/** + * CPPMAGIC_ISEMPTY - does the macro have no arguments? + * + * CPPMAGIC_ISEMPTY() + * expands to '1' + * CPPMAGIC_ISEMPTY(@a) + * CPPMAGIC_ISEMPTY(@a, ...) + * expand to '0' + */ +#define CPPMAGIC_ISEMPTY(...) \ + CPPMAGIC_ISZERO(CPPMAGIC_NONEMPTY(__VA_ARGS__)) + #endif /* CCAN_CPPMAGIC_H */ diff --git a/ccan/cppmagic/test/run.c b/ccan/cppmagic/test/run.c index 0ed830d8..fb2bfb9f 100644 --- a/ccan/cppmagic/test/run.c +++ b/ccan/cppmagic/test/run.c @@ -17,7 +17,7 @@ static inline void check1(const char *orig, const char *expand, int main(void) { - plan_tests(7); + plan_tests(21); CHECK1(CPPMAGIC_NOTHING(), ""); CHECK1(CPPMAGIC_GLUE2(a, b), "ab"); @@ -29,6 +29,24 @@ int main(void) CHECK1(CPPMAGIC_2ND(a, b), "b"); CHECK1(CPPMAGIC_2ND(a, b, c), "b"); + CHECK1(CPPMAGIC_ISZERO(0), "1"); + CHECK1(CPPMAGIC_ISZERO(1), "0"); + CHECK1(CPPMAGIC_ISZERO(123), "0"); + CHECK1(CPPMAGIC_ISZERO(abc), "0"); + + CHECK1(CPPMAGIC_NONZERO(0), "0"); + CHECK1(CPPMAGIC_NONZERO(1), "1"); + CHECK1(CPPMAGIC_NONZERO(123), "1"); + CHECK1(CPPMAGIC_NONZERO(abc), "1"); + + CHECK1(CPPMAGIC_NONEMPTY(), "0"); + CHECK1(CPPMAGIC_NONEMPTY(0), "1"); + CHECK1(CPPMAGIC_NONEMPTY(a, b, c), "1"); + + CHECK1(CPPMAGIC_ISEMPTY(), "1"); + CHECK1(CPPMAGIC_ISEMPTY(0), "0"); + CHECK1(CPPMAGIC_ISEMPTY(a, b, c), "0"); + /* This exits depending on whether all tests passed */ return exit_status(); }