mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-09 23:27:17 +01:00
fed5a117e7
structeq() is too dangerous: if a structure has padding, it can fail silently. The new ccan/structeq instead provides a macro to define foo_eq(), which does the right thing in case of padding (which none of our structures currently have anyway). Upgrade ccan, and use it everywhere. Except run-peer-wire.c, which is only testing code and can use raw memcmp(): valgrind will tell us if padding exists. Interestingly, we still declared short_channel_id_eq, even though we didn't define it any more! Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
46 lines
1.7 KiB
C
46 lines
1.7 KiB
C
/* MIT (BSD) license - see LICENSE file for details */
|
|
#ifndef CCAN_STRUCTEQ_H
|
|
#define CCAN_STRUCTEQ_H
|
|
#include <ccan/build_assert/build_assert.h>
|
|
#include <ccan/cppmagic/cppmagic.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
|
|
/**
|
|
* STRUCTEQ_DEF - define an ..._eq function to compare two structures.
|
|
* @sname: name of the structure, and function (<sname>_eq) to define.
|
|
* @padbytes: number of bytes of expected padding, or -1 if unknown.
|
|
* @...: name of every member of the structure.
|
|
*
|
|
* 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. -1 means "expect some", since
|
|
* it can be platform dependent.
|
|
*/
|
|
#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__)) \
|
|
> 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 */
|