Browse Source

container_of: add container_off() helper.

Just like container_of() (with typechecking, etc), but return the offset
to the enclosing structure.
Rusty Russell 14 years ago
parent
commit
6b0157ffdd
2 changed files with 36 additions and 3 deletions
  1. 32 2
      ccan/container_of/container_of.h
  2. 4 1
      ccan/container_of/test/run.c

+ 32 - 2
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

+ 4 - 1
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();
 }