container_of: add container_off_var macro
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 12 Dec 2011 03:20:05 +0000 (13:50 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 12 Dec 2011 03:20:05 +0000 (13:50 +1030)
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.

ccan/container_of/container_of.h
ccan/container_of/test/run.c

index ea8f1dd36cc191d6d3d3f690d342c0845d61d32e..1c9d147ae06df9f4e0e54adea977f6087e4c628d 100644 (file)
 #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 */
index 96ef483c55879e36df948a82f5af847c0dee9df1..5da440a1e5d09ca05c3c36f03d04a149d694a9ab 100644 (file)
@@ -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();
 }