summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-11-11 13:33:46 +0100
committerThomas Haller <thaller@redhat.com>2015-11-18 13:25:21 +0100
commit37824def11c2c7947103ae668ec487bc90c10c35 (patch)
treed99eddb56c8387a404cfe72de0a6f6586ed1c8d2
parent0c65b289601d46edb0a950e291ddd376e368ccfd (diff)
all: add C99's "bool" define
https://mail.gnome.org/archives/networkmanager-list/2015-November/msg00036.html
-rw-r--r--include/nm-default.h47
-rw-r--r--libnm-core/tests/test-general.c8
2 files changed, 55 insertions, 0 deletions
diff --git a/include/nm-default.h b/include/nm-default.h
index d5c9d1064d..70069a92e8 100644
--- a/include/nm-default.h
+++ b/include/nm-default.h
@@ -70,4 +70,51 @@
/*****************************************************************************/
+/**
+ * The boolean type _Bool is C99 while we mostly stick to C89. However, _Bool is too
+ * convinient to miss and is effectively available in gcc and clang. So, just use it.
+ *
+ * Usually, one would include "stdbool.h" to get the "bool" define which aliases
+ * _Bool. We provide this define here, because we want to make use of it anywhere.
+ * (also, stdbool.h is again C99).
+ *
+ * Using _Bool has advantages over gboolean:
+ *
+ * - commonly _Bool is one byte large, instead of gboolean's 4 bytes (because gboolean
+ * is a typedef for gint). Especially when having boolean fields in a struct, we can
+ * thereby easily save some space.
+ *
+ * - _Bool type guarantees that two "true" expressions compare equal. E.g. the follwing
+ * will not work:
+ * gboolean v1 = 1;
+ * gboolean v2 = 2;
+ * g_assert_cmpint (v1, ==, v2); // will fail
+ * For that, we often to use !! to coerce gboolean values to 0 or 1:
+ * g_assert_cmpint (!!v2, ==, TRUE);
+ * With _Bool type, this will be handled properly by the compiler.
+ *
+ * - For structs, we might want to safe even more space and use bitfields:
+ * struct s1 {
+ * gboolean v1:1;
+ * };
+ * But the problem here is that gboolean is signed, so that
+ * v1 will be either 0 or -1 (not 1, TRUE). Thus, the following
+ * fails:
+ * struct s1 s = { .v1 = TRUE, };
+ * g_assert_cmpint (s1.v1, ==, TRUE);
+ * It will however work just fine with bool/_Bool while retaining the
+ * notion of having a boolean value.
+ *
+ * Also, add the defines for "true" and "false". Those are nicely highlighted by the editor
+ * as special types, contrary to glib's "TRUE"/"FALSE".
+ */
+
+#ifndef bool
+#define bool _Bool
+#define true 1
+#define false 0
+#endif
+
+/*****************************************************************************/
+
#endif /* __NM_DEFAULT_H__ */
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index 2873f755ac..5d95f26aed 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -65,6 +65,14 @@
#include "nm-test-utils.h"
#include "test-general-enums.h"
+/* When passing a "bool" typed argument to a variadic function that
+ * expects a gboolean, the compiler will promote the integer type
+ * to have at least size (int). That way:
+ * g_object_set (obj, PROP_BOOL, bool_val, NULL);
+ * will just work correctly. */
+G_STATIC_ASSERT (sizeof (gboolean) == sizeof (int));
+G_STATIC_ASSERT (sizeof (bool) <= sizeof (int));
+
static void
vpn_check_func (const char *key, const char *value, gpointer user_data)
{