]> git.ozlabs.org Git - ccan/blob - ccan/container_of/container_of.h
0449935056f51a84af2a84f5b2dd7fcbf48c7678
[ccan] / ccan / container_of / container_of.h
1 /* CC0 (Public domain) - see LICENSE file for details */
2 #ifndef CCAN_CONTAINER_OF_H
3 #define CCAN_CONTAINER_OF_H
4 #include <stddef.h>
5
6 #include "config.h"
7 #include <ccan/check_type/check_type.h>
8
9 /**
10  * container_of - get pointer to enclosing structure
11  * @member_ptr: pointer to the structure member
12  * @containing_type: the type this member is within
13  * @member: the name of this member within the structure.
14  *
15  * Given a pointer to a member of a structure, this macro does pointer
16  * subtraction to return the pointer to the enclosing type.
17  *
18  * Example:
19  *      struct foo {
20  *              int fielda, fieldb;
21  *              // ...
22  *      };
23  *      struct info {
24  *              int some_other_field;
25  *              struct foo my_foo;
26  *      };
27  *
28  *      static struct info *foo_to_info(struct foo *foo)
29  *      {
30  *              return container_of(foo, struct info, my_foo);
31  *      }
32  */
33 #define container_of(member_ptr, containing_type, member)               \
34          ((containing_type *)                                           \
35           ((char *)(member_ptr)                                         \
36            - container_off(containing_type, member))                    \
37           + check_types_match(*(member_ptr), ((containing_type *)0)->member))
38
39 /**
40  * container_off - get offset to enclosing structure
41  * @containing_type: the type this member is within
42  * @member: the name of this member within the structure.
43  *
44  * Given a pointer to a member of a structure, this macro does
45  * typechecking and figures out the offset to the enclosing type.
46  *
47  * Example:
48  *      struct foo {
49  *              int fielda, fieldb;
50  *              // ...
51  *      };
52  *      struct info {
53  *              int some_other_field;
54  *              struct foo my_foo;
55  *      };
56  *
57  *      static struct info *foo_to_info(struct foo *foo)
58  *      {
59  *              size_t off = container_off(struct info, my_foo);
60  *              return (void *)((char *)foo - off);
61  *      }
62  */
63 #define container_off(containing_type, member)  \
64         offsetof(containing_type, member)
65
66 /**
67  * container_of_var - get pointer to enclosing structure using a variable
68  * @member_ptr: pointer to the structure member
69  * @container_var: a pointer of same type as this member's container
70  * @member: the name of this member within the structure.
71  *
72  * Given a pointer to a member of a structure, this macro does pointer
73  * subtraction to return the pointer to the enclosing type.
74  *
75  * Example:
76  *      static struct info *foo_to_i(struct foo *foo)
77  *      {
78  *              struct info *i = container_of_var(foo, i, my_foo);
79  *              return i;
80  *      }
81  */
82 #if HAVE_TYPEOF
83 #define container_of_var(member_ptr, container_var, member) \
84         container_of(member_ptr, typeof(*container_var), member)
85 #else
86 #define container_of_var(member_ptr, container_var, member)     \
87         ((void *)((char *)(member_ptr)  -                       \
88                   container_off_var(container_var, member)))
89 #endif
90
91 /**
92  * container_off_var - get offset of a field in enclosing structure
93  * @container_var: a pointer to a container structure
94  * @member: the name of a member within the structure.
95  *
96  * Given (any) pointer to a structure and a its member name, this
97  * macro does pointer subtraction to return offset of member in a
98  * structure memory layout.
99  *
100  */
101 #if HAVE_TYPEOF
102 #define container_off_var(var, member)          \
103         container_off(typeof(*var), member)
104 #else
105 #define container_off_var(var, member)                  \
106         ((const char *)&(var)->member - (const char *)(var))
107 #endif
108
109 #endif /* CCAN_CONTAINER_OF_H */