X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fcontainer_of%2Fcontainer_of.h;h=1c9d147ae06df9f4e0e54adea977f6087e4c628d;hp=ec66f106f2aeb0144b17455973607b873ae88731;hb=87f505a56eae7ef2a03a76b5b412d6bc46c58aae;hpb=a8b248ea9de55316cac4423a99a727ca7b54e0fc diff --git a/ccan/container_of/container_of.h b/ccan/container_of/container_of.h index ec66f106..1c9d147a 100644 --- a/ccan/container_of/container_of.h +++ b/ccan/container_of/container_of.h @@ -15,51 +15,94 @@ * subtraction to return the pointer to the enclosing type. * * Example: - * struct info - * { + * struct foo { + * int fielda, fieldb; + * // ... + * }; + * struct info { * int some_other_field; * struct foo my_foo; * }; * - * struct info *foo_to_info(struct foo *foop) + * static struct info *foo_to_info(struct foo *foo) * { * return container_of(foo, struct info, my_foo); * } */ #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(containing_type, member)) \ + + check_types_match(*(member_ptr), ((containing_type *)0)->member)) +/** + * container_off - get offset to enclosing structure + * @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. + * + * 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(struct info, my_foo); + * return (void *)((char *)foo - off); + * } + */ +#define container_off(containing_type, member) \ + offsetof(containing_type, member) /** * container_of_var - get pointer to enclosing structure using a variable * @member_ptr: pointer to the structure member - * @var: a pointer to a structure of same type as this member is within + * @container_var: a pointer of same type as this member's container * @member: the name of this member within the structure. * * Given a pointer to a member of a structure, this macro does pointer * subtraction to return the pointer to the enclosing type. * * Example: - * struct info - * { - * int some_other_field; - * struct foo my_foo; - * }; - * - * struct info *foo_to_info(struct foo *foop) + * static struct info *foo_to_i(struct foo *foo) * { * struct info *i = container_of_var(foo, i, my_foo); * return i; * } */ -#ifdef HAVE_TYPEOF -#define container_of_var(member_ptr, var, member) \ - container_of(member_ptr, typeof(*var), member) +#if HAVE_TYPEOF +#define container_of_var(member_ptr, container_var, member) \ + container_of(member_ptr, typeof(*container_var), member) +#else +#define container_of_var(member_ptr, container_var, member) \ + ((void *)((char *)(member_ptr) - \ + container_off_var(container_var, member))) +#endif + +/** + * container_off_var - get offset of a field in enclosing structure + * @container_var: a pointer to a container structure + * @member: the name of a member within the structure. + * + * Given (any) pointer to a structure and a its member name, this + * macro does pointer subtraction to return offset of member in a + * structure memory layout. + * + */ +#if HAVE_TYPEOF +#define container_off_var(var, member) \ + container_off(typeof(*var), member) #else -#define container_of_var(member_ptr, var, member) \ - ((void *)((char *)(member_ptr) - offsetof(containing_type, member))) +#define container_off_var(var, member) \ + ((char *)&(var)->member - (char *)(var)) #endif #endif /* CCAN_CONTAINER_OF_H */