summaryrefslogtreecommitdiff
path: root/ccan
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-13 23:49:28 (GMT)
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-13 23:49:28 (GMT)
commite7f6d9e25ab69cc986d10ad8d9ce91610f14b378 (patch)
treee7c7871904f6baebfa0d80001ec0f20c156ccf63 /ccan
parenta5fc33c0e234e5ad80a9ed2a8413c2f50e508482 (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.h36
1 files changed, 36 insertions, 0 deletions
diff --git a/ccan/container_of/container_of.h b/ccan/container_of/container_of.h
index 6d1a5be..ae3e1fc 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