]> git.ozlabs.org Git - ccan/blob - ccan/structeq/structeq.h
base64: fix for unsigned chars (e.g. ARM).
[ccan] / ccan / structeq / structeq.h
1 /* MIT (BSD) license - see LICENSE file for details */
2 #ifndef CCAN_STRUCTEQ_H
3 #define CCAN_STRUCTEQ_H
4 #include <ccan/build_assert/build_assert.h>
5 #include <ccan/cppmagic/cppmagic.h>
6 #include <string.h>
7 #include <stdbool.h>
8
9 /**
10  * STRUCTEQ_DEF - define an ..._eq function to compare two structures.
11  * @sname: name of the structure, and function (<sname>_eq) to define.
12  * @padbytes: number of bytes of expected padding, or negative "max".
13  * @...: name of every member of the structure.
14  *
15  * This generates a single memcmp() call in the common case where the
16  * structure contains no padding.  Since it can't tell the difference between
17  * padding and a missing member, @padbytes can be used to assert that
18  * there isn't any, or how many we expect.  A negative number means
19  * "up to or equal to that amount of padding", as padding can be
20  * platform dependent.
21  */
22 #define STRUCTEQ_DEF(sname, padbytes, ...)                              \
23 static inline bool CPPMAGIC_GLUE2(sname, _eq)(const struct sname *_a, \
24                                               const struct sname *_b) \
25 {                                                                       \
26         BUILD_ASSERT(((padbytes) < 0 &&                                 \
27                       CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \
28                                                     __VA_ARGS__))       \
29                       - (padbytes) >= sizeof(*_a))                      \
30                      || CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \
31                                                       __VA_ARGS__))     \
32                      + (padbytes) == sizeof(*_a));                      \
33         if (CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, __VA_ARGS__)) \
34             == sizeof(*_a))                                             \
35                 return memcmp(_a, _b, sizeof(*_a)) == 0;                \
36         else                                                            \
37                 return CPPMAGIC_JOIN(&&,                                \
38                                      CPPMAGIC_MAP(STRUCTEQ_MEMBER_CMP_, \
39                                                   __VA_ARGS__));        \
40 }
41
42 /* Helpers */
43 #define STRUCTEQ_MEMBER_SIZE_(m) sizeof((_a)->m)
44 #define STRUCTEQ_MEMBER_CMP_(m) memcmp(&_a->m, &_b->m, sizeof(_a->m)) == 0
45
46 #endif /* CCAN_STRUCTEQ_H */