X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fstructeq%2Fstructeq.h;h=81799539c51e45f9c2f1b9c23a1b3949b47564c1;hp=3af20c53938ce73276da8afa7dfa441d9f3766ed;hb=8e6c2fecfd633171250b7f09ef4aa0328bd5b698;hpb=8b0bdb090e2882aa431e89f4bc7aa4736e9e2838 diff --git a/ccan/structeq/structeq.h b/ccan/structeq/structeq.h index 3af20c53..81799539 100644 --- a/ccan/structeq/structeq.h +++ b/ccan/structeq/structeq.h @@ -1,17 +1,46 @@ -/* CC0 (Public domain) - see LICENSE file for details */ +/* MIT (BSD) license - see LICENSE file for details */ #ifndef CCAN_STRUCTEQ_H #define CCAN_STRUCTEQ_H +#include +#include #include +#include /** - * structeq - are two structures bitwise equal (including padding!) - * @a: a pointer to a structure - * @b: a pointer to a structure of the same type. + * STRUCTEQ_DEF - define an ..._eq function to compare two structures. + * @sname: name of the structure, and function (_eq) to define. + * @padbytes: number of bytes of expected padding, or negative "max". + * @...: name of every member of the structure. * - * 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! + * This generates a single memcmp() call in the common case where the + * structure contains no padding. Since it can't tell the difference between + * padding and a missing member, @padbytes can be used to assert that + * there isn't any, or how many we expect. A negative number means + * "up to or equal to that amount of padding", as padding can be + * platform dependent. */ -#define structeq(a, b) \ - (memcmp((a), (b), sizeof(*(a)) + 0 * sizeof((a) == (b))) == 0) +#define STRUCTEQ_DEF(sname, padbytes, ...) \ +static inline bool CPPMAGIC_GLUE2(sname, _eq)(const struct sname *_a, \ + const struct sname *_b) \ +{ \ + BUILD_ASSERT(((padbytes) < 0 && \ + CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \ + __VA_ARGS__)) \ + - (padbytes) >= sizeof(*_a)) \ + || CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \ + __VA_ARGS__)) \ + + (padbytes) == sizeof(*_a)); \ + if (CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, __VA_ARGS__)) \ + == sizeof(*_a)) \ + return memcmp(_a, _b, sizeof(*_a)) == 0; \ + else \ + return CPPMAGIC_JOIN(&&, \ + CPPMAGIC_MAP(STRUCTEQ_MEMBER_CMP_, \ + __VA_ARGS__)); \ +} + +/* Helpers */ +#define STRUCTEQ_MEMBER_SIZE_(m) sizeof((_a)->m) +#define STRUCTEQ_MEMBER_CMP_(m) memcmp(&_a->m, &_b->m, sizeof(_a->m)) == 0 + #endif /* CCAN_STRUCTEQ_H */