[ccan] [PATCH 2/5] cppmagic: Logical operations

David Gibson david at gibson.dropbear.id.au
Wed Jan 27 22:39:58 AEDT 2016


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 <david at gibson.dropbear.id.au>
---
 ccan/cppmagic/cppmagic.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
 ccan/cppmagic/test/run.c | 20 +++++++++++++++++++-
 2 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/ccan/cppmagic/cppmagic.h b/ccan/cppmagic/cppmagic.h
index f29e0ec..c4454e7 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 0ed830d..fb2bfb9 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();
 }
-- 
2.5.0



More information about the ccan mailing list