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>
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.
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
22 #define STRUCTEQ_DEF(sname, padbytes, ...) \
23 static inline bool CPPMAGIC_GLUE2(sname, _eq)(const struct sname *_a, \
24 const struct sname *_b) \
26 BUILD_ASSERT(((padbytes) < 0 && \
27 CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \
29 - (padbytes) >= sizeof(*_a)) \
30 || CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \
32 + (padbytes) == sizeof(*_a)); \
33 if (CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, __VA_ARGS__)) \
35 return memcmp(_a, _b, sizeof(*_a)) == 0; \
37 return CPPMAGIC_JOIN(&&, \
38 CPPMAGIC_MAP(STRUCTEQ_MEMBER_CMP_, \
43 #define STRUCTEQ_MEMBER_SIZE_(m) sizeof((_a)->m)
44 #define STRUCTEQ_MEMBER_CMP_(m) memcmp(&_a->m, &_b->m, sizeof(_a->m)) == 0
46 #endif /* CCAN_STRUCTEQ_H */