Commit 7ec5b8e0 authored by David Gibson's avatar David Gibson Committed by Rusty Russell

container_of: Add container_of_or_null()

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.
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent f3c92802
......@@ -36,6 +36,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
......
......@@ -12,9 +12,13 @@ int main(int argc, char *argv[])
int *intp = &foo.a;
char *charp = &foo.b;
plan_tests(8);
plan_tests(12);
ok1(container_of(intp, struct foo, a) == &foo);
ok1(container_of(charp, struct foo, b) == &foo);
ok1(container_of_or_null(intp, struct foo, a) == &foo);
ok1(container_of_or_null(charp, struct foo, b) == &foo);
ok1(container_of_or_null((int *)NULL, struct foo, a) == NULL);
ok1(container_of_or_null((char *)NULL, struct foo, b) == NULL);
ok1(container_of_var(intp, &foo, a) == &foo);
ok1(container_of_var(charp, &foo, b) == &foo);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment