Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /** genc_container_of(obj, cont_type, member_name)
- * Get pointer to struct object from a pointer to one of its members.
- * obj - pointer to a struct member, or NULL
- * cont_type - structure type of the containing object
- * member_name - name of the member of cont_type referenced by obj
- *
- * Similar to Linux's container_of macro, except it also handles NULL pointers
- * correctly, which is to say it evaluates to NULL when the obj is NULL. We also
- * try to support non-GCC compilers which don't support the ({ }) expression
- * syntax.
- *
- * Where the obj can be guaranteed to be non-NULL, genc_container_of_notnull()
- * may be used. It omits the NULL check and its behaviour is therefore undefined
- * if obj is indeed NULL.
- */
- #ifndef genc_container_of
- #ifndef __has_feature
- #define __has_feature(x) 0
- #endif
- #ifndef __has_extension
- #define __has_extension __has_feature
- #endif
- /* Where possible, make the helper functions const-correct via overloading.
- * C++ compilers obviously support it, but so does clang. For pure GCC,
- * we have a different solution. */
- #if defined(__cplusplus) || __has_extension(attribute_overloadable)
- #ifdef __cplusplus
- #define GENC_OVERLOADABLE
- #else
- /* This is clang, basically */
- #define GENC_OVERLOADABLE __attribute__((overloadable))
- #endif
- /* function for avoiding multiple evaluation */
- static inline void* GENC_OVERLOADABLE genc_container_of_helper(void* obj, ptrdiff_t offset)
- {
- return (obj ? ((char*)obj - offset) : NULL);
- }
- static inline const void* GENC_OVERLOADABLE genc_container_of_helper(const void* obj, ptrdiff_t offset)
- {
- return (obj ? ((const char*)obj - offset) : NULL);
- }
- /* function for avoiding multiple evaluation */
- static inline const void* GENC_OVERLOADABLE genc_container_of_notnull_helper(const void* obj, ptrdiff_t offset)
- {
- return ((const char*)obj - offset);
- }
- static inline void* GENC_OVERLOADABLE genc_container_of_notnull_helper(void* obj, ptrdiff_t offset)
- {
- return ((char*)obj - offset);
- }
- #else
- /* function for avoiding multiple evaluation */
- static GENC_INLINE void* genc_container_of_helper(void* obj, ptrdiff_t offset)
- {
- return (obj ? ((char*)obj - offset) : NULL);
- }
- /* function for avoiding multiple evaluation */
- static GENC_INLINE void* genc_container_of_notnull_helper(void* obj, ptrdiff_t offset)
- {
- return ((char*)obj - offset);
- }
- #if __GNUC__
- /* GNU C has some builtin trickery that is almost as good as overloading */
- /* function for avoiding multiple evaluation */
- static GENC_INLINE const void* genc_container_of_const_helper(const void* obj, ptrdiff_t offset)
- {
- return (obj ? ((const char*)obj - offset) : NULL);
- }
- /* function for avoiding multiple evaluation */
- static GENC_INLINE const void* genc_container_of_const_notnull_helper(const void* obj, ptrdiff_t offset)
- {
- return ((const char*)obj - offset);
- }
- #endif
- #endif
- #ifdef __cplusplus
- extern "C" {
- #endif
- #ifdef __GNUC__
- #if defined(__cplusplus) || __has_extension(attribute_overloadable)
- /* the unused _p attribute is for causing a compiler warning if member_name of
- * cont_type does not have same type as target of obj*/
- #define genc_container_of(obj, cont_type, member_name) \
- ({ \
- cont_type* _c = ((cont_type*)genc_container_of_helper((obj), offsetof(cont_type, member_name))); \
- __typeof__(obj) __attribute__ ((unused)) _p = _c ? &_c->member_name : NULL; \
- _c; \
- })
- #define genc_container_of_notnull(obj, cont_type, member_name) \
- ({ \
- cont_type* _c = ((cont_type*)genc_container_of_notnull_helper((obj), offsetof(cont_type, member_name))); \
- __typeof__(obj) __attribute__ ((unused)) _p = &_c->member_name; \
- _c; \
- })
- #else
- /* GCC builtin trickery (C mode only, no overloading possible) so that different helpers
- * get called for const and non-const types (avoids warnings even with -Wcast-qual).
- * Checks if pointers to const type and type are compatible - only the case if
- * type is already const - and dispatches to the 2 different helper functions. */
- #define genc_container_of(obj, cont_type, member_name) \
- ({ \
- cont_type* _c = \
- (cont_type*)(__builtin_choose_expr(__builtin_types_compatible_p(const cont_type*, cont_type*), \
- genc_container_of_const_helper, genc_container_of_helper) \
- ((obj), offsetof(cont_type, member_name))); \
- __typeof__(obj) __attribute__ ((unused)) _p = _c ? &_c->member_name : NULL; \
- _c; \
- })
- #define genc_container_of_notnull(obj, cont_type, member_name) \
- ({ \
- cont_type* _c = \
- (cont_type*)(__builtin_choose_expr(__builtin_types_compatible_p(const cont_type*, cont_type*), \
- genc_container_of_const_notnull_helper, genc_container_of_notnull_helper) \
- ((obj), offsetof(cont_type, member_name))); \
- __typeof__(obj) __attribute__ ((unused)) _p = &_c->member_name; \
- _c; \
- })
- #endif
- #else
- #define genc_container_of(obj, cont_type, member_name) \
- ((cont_type*)genc_container_of_helper((obj), offsetof(cont_type, member_name)))
- #define genc_container_of_notnull(obj, cont_type, member_name) \
- ((cont_type*)genc_container_of_notnull_helper((obj), offsetof(cont_type, member_name)))
- #endif
- static GENC_INLINE void* genc_member_of_helper(void* obj, ptrdiff_t offset)
- {
- return obj ? ((char*)obj + offset) : NULL;
- }
- #endif
Add Comment
Please, Sign In to add comment