diff options
author | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-09-13 23:49:28 +0000 |
---|---|---|
committer | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-09-13 23:49:28 +0000 |
commit | e7f6d9e25ab69cc986d10ad8d9ce91610f14b378 (patch) | |
tree | e7c7871904f6baebfa0d80001ec0f20c156ccf63 /ccan | |
parent | a5fc33c0e234e5ad80a9ed2a8413c2f50e508482 (diff) |
ccan/container_of: add container_of_or_null
* ccan/container_of/container_of.h (container_of_or_null): added
[ccan 7ec5b8e06b2fd5fa98b1fcde1158c286d2d429d8] (David Gibson)
It's quite common to have a pointer which could be either a pointer to a
structure member, or NULL. This needs special casing with container_of(),
or it will convert NULL into something strange.
This patch adds container_of_or_null(), which will return NULL if passed
(an appropriately typed) NULL, or the containining structure as
container_of() otherwise.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47579 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ccan')
-rw-r--r-- | ccan/container_of/container_of.h | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/ccan/container_of/container_of.h b/ccan/container_of/container_of.h index 6d1a5be8ac..ae3e1fc81f 100644 --- a/ccan/container_of/container_of.h +++ b/ccan/container_of/container_of.h @@ -33,6 +33,42 @@ - container_off(containing_type, member)) \ + check_types_match(*(member_ptr), ((containing_type *)0)->member)) + +/** + * container_of_or_null - get pointer to enclosing structure, or NULL + * @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 pointer + * subtraction to return the pointer to the enclosing type, unless it + * is given NULL, in which case it also returns NULL. + * + * Example: + * struct foo { + * int fielda, fieldb; + * // ... + * }; + * struct info { + * int some_other_field; + * struct foo my_foo; + * }; + * + * static struct info *foo_to_info_allowing_null(struct foo *foo) + * { + * return container_of_or_null(foo, struct info, my_foo); + * } + */ +static inline char *container_of_or_null_(void *member_ptr, size_t offset) +{ + return member_ptr ? (char *)member_ptr - offset : NULL; +} +#define container_of_or_null(member_ptr, containing_type, member) \ + ((containing_type *) \ + container_of_or_null_(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 |