structeq.h (2017B)
1 /* MIT (BSD) license - see LICENSE file for details */ 2 #ifndef CCAN_STRUCTEQ_H 3 #define CCAN_STRUCTEQ_H 4 #include "build_assert.h" 5 #include "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 */