structeq: new module.
authorRusty Russell <rusty@rustcorp.com.au>
Wed, 25 Jun 2014 02:28:57 +0000 (11:58 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 25 Jun 2014 06:23:34 +0000 (15:53 +0930)
World's most trivial module, but I want it for pettycoin.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Makefile-ccan
ccan/structeq/LICENSE [new symlink]
ccan/structeq/_info [new file with mode: 0644]
ccan/structeq/structeq.h [new file with mode: 0644]
ccan/structeq/test/compile_fail-different.c [new file with mode: 0644]
ccan/structeq/test/run.c [new file with mode: 0644]

index 6410301d1e5d763835c50bc22156f83da6adb42d..40d03891e47c6e619c78b31466c1ea6538ee1ba4 100644 (file)
@@ -23,6 +23,7 @@ MODS_NO_SRC := alignof \
        minmax \
        objset \
        short_types \
+       structeq \
        tcon \
        tlist \
        typesafe_cb \
diff --git a/ccan/structeq/LICENSE b/ccan/structeq/LICENSE
new file mode 120000 (symlink)
index 0000000..b7951da
--- /dev/null
@@ -0,0 +1 @@
+../../licenses/CC0
\ No newline at end of file
diff --git a/ccan/structeq/_info b/ccan/structeq/_info
new file mode 100644 (file)
index 0000000..d66e296
--- /dev/null
@@ -0,0 +1,57 @@
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * structeq - bitwise comparison of structs.
+ *
+ * This is a replacement for memcmp, which checks the argument types are the
+ * same.
+ *
+ * License: CC0 (Public domain)
+ * Author: Rusty Russell <rusty@rustcorp.com.au>
+ *
+ * Example:
+ *     #include <ccan/structeq/structeq.h>
+ *     #include <ccan/build_assert/build_assert.h>
+ *     #include <assert.h>
+ *     
+ *     struct mydata {
+ *             int start, end;
+ *     };
+ *     
+ *     int main(void)
+ *     {
+ *             struct mydata a, b;
+ *     
+ *             // No padding in struct, otherwise this doesn't work!
+ *             BUILD_ASSERT(sizeof(a) == sizeof(a.start) + sizeof(a.end));
+ *     
+ *             a.start = 100;
+ *             a.end = 101;
+ *     
+ *             b.start = 100;
+ *             b.end = 101;
+ *     
+ *             // They are equal.
+ *             assert(structeq(&a, &b));
+ *     
+ *             b.end++;
+ *             // Now they are not.
+ *             assert(!structeq(&a, &b));
+ *     
+ *             return 0;
+ *     }
+ */
+int main(int argc, char *argv[])
+{
+       /* Expect exactly one argument */
+       if (argc != 2)
+               return 1;
+
+       if (strcmp(argv[1], "depends") == 0) {
+               return 0;
+       }
+
+       return 1;
+}
diff --git a/ccan/structeq/structeq.h b/ccan/structeq/structeq.h
new file mode 100644 (file)
index 0000000..3af20c5
--- /dev/null
@@ -0,0 +1,17 @@
+/* CC0 (Public domain) - see LICENSE file for details */
+#ifndef CCAN_STRUCTEQ_H
+#define CCAN_STRUCTEQ_H
+#include <string.h>
+
+/**
+ * structeq - are two structures bitwise equal (including padding!)
+ * @a: a pointer to a structure
+ * @b: a pointer to a structure of the same type.
+ *
+ * If you *know* a structure has no padding, you can memcmp them.  At
+ * least this way, the compiler will issue a warning if the structs are
+ * different types!
+ */
+#define structeq(a, b) \
+       (memcmp((a), (b), sizeof(*(a)) + 0 * sizeof((a) == (b))) == 0)
+#endif /* CCAN_STRUCTEQ_H */
diff --git a/ccan/structeq/test/compile_fail-different.c b/ccan/structeq/test/compile_fail-different.c
new file mode 100644 (file)
index 0000000..9a08503
--- /dev/null
@@ -0,0 +1,22 @@
+#include <ccan/structeq/structeq.h>
+
+struct mydata1 {
+       int start, end;
+};
+
+struct mydata2 {
+       int start, end;
+};
+
+int main(void)
+{
+       struct mydata1 a = { 0, 100 };
+#ifdef FAIL
+       struct mydata2
+#else
+       struct mydata1
+#endif
+               b = { 0, 100 };
+
+       return structeq(&a, &b);
+}
diff --git a/ccan/structeq/test/run.c b/ccan/structeq/test/run.c
new file mode 100644 (file)
index 0000000..9ecb4b7
--- /dev/null
@@ -0,0 +1,27 @@
+#include <ccan/structeq/structeq.h>
+#include <ccan/tap/tap.h>
+
+struct mydata {
+       int start, end;
+};
+
+int main(void)
+{
+       struct mydata a, b;
+
+       /* This is how many tests you plan to run */
+       plan_tests(3);
+
+       a.start = 0;
+       a.end = 100;
+       ok1(structeq(&a, &a));
+
+       b = a;
+       ok1(structeq(&a, &b));
+
+       b.end++;
+       ok1(!structeq(&a, &b));
+
+       /* This exits depending on whether all tests passed */
+       return exit_status();
+}