Browse Source

container_of: add container_off_var macro

Based on patch by Andrey Smirnov <andrew.smirnov@gmail.com>:
    
    There is are certain use-cases when it is necessary to know the offset
    of the member in a structure's memory layout. One such use-case can be
    seen in `ccan/list/list.h' in macros `list_for_each' and
    `list_for_each_safe'. This commit implements said functionality with
    `container_of_var_off' macro.

Renamed container_of_var_off -> container_off_var now we have container_off.
Rusty Russell 14 years ago
parent
commit
87f505a56e
2 changed files with 24 additions and 5 deletions
  1. 21 4
      ccan/container_of/container_of.h
  2. 3 1
      ccan/container_of/test/run.c

+ 21 - 4
ccan/container_of/container_of.h

@@ -82,10 +82,27 @@
 #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)					\
-		  - ((char *)&(container_var)->member			\
-		     - (char *)(container_var))))
+#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_off_var(var, member)			\
+	((char *)&(var)->member - (char *)(var))
 #endif
 
 #endif /* CCAN_CONTAINER_OF_H */

+ 3 - 1
ccan/container_of/test/run.c

@@ -12,7 +12,7 @@ int main(int argc, char *argv[])
 	int *intp = &foo.a;
 	char *charp = &foo.b;
 
-	plan_tests(6);
+	plan_tests(8);
 	ok1(container_of(intp, struct foo, a) == &foo);
 	ok1(container_of(charp, struct foo, b) == &foo);
 	ok1(container_of_var(intp, &foo, a) == &foo);
@@ -20,5 +20,7 @@ int main(int argc, char *argv[])
 
 	ok1(container_off(struct foo, a) == 0);
 	ok1(container_off(struct foo, b) == offsetof(struct foo, b));
+	ok1(container_off_var(&foo, a) == 0);
+	ok1(container_off_var(&foo, b) == offsetof(struct foo, b));
 	return exit_status();
 }