With this trick from CCAN (http://ccodearchive.net/info/array_size.html)
we ensure at build-time user is indeed passing an array and not a
pointer.

The code in CCAN uses several other macros like BUILD_ASSERT,
BUILD_ASSERT_OR_ZERO. Since this is a public header, i think it's
preferred not to export these other macros, unless there's interest in
them.
---
 .gitignore       |    1 +
 Makefile.am      |    4 +++-
 ell/util.h       |    4 +++-
 unit/test-util.c |   59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 66 insertions(+), 2 deletions(-)
 create mode 100644 unit/test-util.c

diff --git a/.gitignore b/.gitignore
index 81c83c7..01a9406 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,6 +38,7 @@ unit/test-netlink
 unit/test-dbus
 unit/test-dbus-message
 unit/test-array
+unit/test-util
 
 doc/*.bak
 doc/*.stamp
diff --git a/Makefile.am b/Makefile.am
index e822cd8..37b1781 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -61,7 +61,7 @@ noinst_PROGRAMS = unit/test-unit unit/test-queue \
                                unit/test-plugin unit/test-checksum \
                                unit/test-settings unit/test-netlink \
                                unit/test-dbus unit/test-dbus-message \
-                               unit/test-array
+                               unit/test-array unit/test-util
 
 unit_test_unit_LDADD = ell/libell-private.la
 
@@ -91,6 +91,8 @@ unit_test_dbus_message_LDADD = ell/libell-private.la
 
 unit_test_array_LDADD = ell/libell-private.la
 
+unit_test_util_LDADD = ell/libell-private.la
+
 noinst_LTLIBRARIES += unit/example-plugin.la
 
 unit_example_plugin_la_LDFLAGS = -no-undefined -module -avoid-version \
diff --git a/ell/util.h b/ell/util.h
index d7849c1..3c9b14f 100644
--- a/ell/util.h
+++ b/ell/util.h
@@ -52,7 +52,9 @@ do {                                          \
        __p->__v = (val);                       \
 } while(0)
 
-#define L_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#define L_ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])) + \
+       sizeof(char[1 - 2 * !!__builtin_types_compatible_p(typeof(x), \
+                                                       typeof(&(x)[0]))]) - 1)
 
 void *l_malloc(size_t size) __attribute__ ((warn_unused_result, malloc));
 void l_free(void *ptr);
diff --git a/unit/test-util.c b/unit/test-util.c
new file mode 100644
index 0000000..ec7fecf
--- /dev/null
+++ b/unit/test-util.c
@@ -0,0 +1,59 @@
+/*
+ *
+ *  Embedded Linux library
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ell/ell.h>
+#include <assert.h>
+
+static void array_size1(const void *data)
+{
+       const char dummy[20];
+
+       assert(L_ARRAY_SIZE(dummy) == 20);
+}
+
+struct a {
+       int n;
+       const char *s;
+};
+
+static void array_size2(const void *data)
+{
+       struct a dummy[] = {
+               { 20, "test 1" },
+               { 30, "test 2" }
+       };
+
+       assert(L_ARRAY_SIZE(dummy) == 2);
+}
+
+int main(int argc, char *argv[])
+{
+       l_test_init(&argc, &argv);
+
+       l_test_add("array-size1", array_size1, NULL);
+       l_test_add("array-size2", array_size2, NULL);
+
+       return l_test_run();
+}
-- 
1.7.10.2

_______________________________________________
connman mailing list
connman@connman.net
http://lists.connman.net/listinfo/connman

Reply via email to