From: Rusty Russell Date: Wed, 30 Nov 2011 03:02:06 +0000 (+1030) Subject: container_of: add container_off() helper. X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=6b0157ffdd333a7e2af9738551df4fbf2eca73db container_of: add container_off() helper. Just like container_of() (with typechecking, etc), but return the offset to the enclosing structure. --- diff --git a/ccan/container_of/container_of.h b/ccan/container_of/container_of.h index 2a6b1cd5..4490184c 100644 --- a/ccan/container_of/container_of.h +++ b/ccan/container_of/container_of.h @@ -31,9 +31,39 @@ */ #define container_of(member_ptr, containing_type, member) \ ((containing_type *) \ - ((char *)(member_ptr) - offsetof(containing_type, member)) \ - - check_types_match(*(member_ptr), ((containing_type *)0)->member)) + ((char *)(member_ptr) \ + - container_off((member_ptr), containing_type, member))) +/** + * container_off - get offset to enclosing structure + * @member_ptr: pointer to the structure member + * @containing_type: the type this member is within + * @member: the name of this member within the structure. + * + * Given a pointer to a member of a structure, this macro does + * typechecking and figures out the offset to the enclosing type. + * + * Note that @member_ptr is not evaluated. + * + * Example: + * struct foo { + * int fielda, fieldb; + * // ... + * }; + * struct info { + * int some_other_field; + * struct foo my_foo; + * }; + * + * static struct info *foo_to_info(struct foo *foo) + * { + * size_t off = container_off(foo, struct info, my_foo); + * return (void *)((char *)foo - off); + * } + */ +#define container_off(member_ptr, containing_type, member) \ + (offsetof(containing_type, member) \ + + check_types_match(*(member_ptr), ((containing_type *)0)->member)) /** * container_of_var - get pointer to enclosing structure using a variable diff --git a/ccan/container_of/test/run.c b/ccan/container_of/test/run.c index f28d9998..8f86bc8d 100644 --- a/ccan/container_of/test/run.c +++ b/ccan/container_of/test/run.c @@ -12,10 +12,13 @@ int main(int argc, char *argv[]) int *intp = &foo.a; char *charp = &foo.b; - plan_tests(4); + plan_tests(6); ok1(container_of(intp, struct foo, a) == &foo); ok1(container_of(charp, struct foo, b) == &foo); ok1(container_of_var(intp, &foo, a) == &foo); ok1(container_of_var(charp, &foo, b) == &foo); + + ok1(container_off(intp, struct foo, a) == 0); + ok1(container_off(charp, struct foo, b) == offsetof(struct foo, b)); return exit_status(); }