Guest User

Untitled

a guest
Oct 21st, 2018
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.07 KB | None | 0 0
  1. /** genc_container_of(obj, cont_type, member_name)
  2. * Get pointer to struct object from a pointer to one of its members.
  3. * obj - pointer to a struct member, or NULL
  4. * cont_type - structure type of the containing object
  5. * member_name - name of the member of cont_type referenced by obj
  6. *
  7. * Similar to Linux's container_of macro, except it also handles NULL pointers
  8. * correctly, which is to say it evaluates to NULL when the obj is NULL. We also
  9. * try to support non-GCC compilers which don't support the ({ }) expression
  10. * syntax.
  11. *
  12. * Where the obj can be guaranteed to be non-NULL, genc_container_of_notnull()
  13. * may be used. It omits the NULL check and its behaviour is therefore undefined
  14. * if obj is indeed NULL.
  15. */
  16. #ifndef genc_container_of
  17.  
  18. #ifndef __has_feature
  19. #define __has_feature(x) 0
  20. #endif
  21. #ifndef __has_extension
  22. #define __has_extension __has_feature
  23. #endif
  24.  
  25.  
  26. /* Where possible, make the helper functions const-correct via overloading.
  27. * C++ compilers obviously support it, but so does clang. For pure GCC,
  28. * we have a different solution. */
  29. #if defined(__cplusplus) || __has_extension(attribute_overloadable)
  30. #ifdef __cplusplus
  31. #define GENC_OVERLOADABLE
  32. #else
  33. /* This is clang, basically */
  34. #define GENC_OVERLOADABLE __attribute__((overloadable))
  35. #endif
  36. /* function for avoiding multiple evaluation */
  37. static inline void* GENC_OVERLOADABLE genc_container_of_helper(void* obj, ptrdiff_t offset)
  38. {
  39. return (obj ? ((char*)obj - offset) : NULL);
  40. }
  41. static inline const void* GENC_OVERLOADABLE genc_container_of_helper(const void* obj, ptrdiff_t offset)
  42. {
  43. return (obj ? ((const char*)obj - offset) : NULL);
  44. }
  45. /* function for avoiding multiple evaluation */
  46. static inline const void* GENC_OVERLOADABLE genc_container_of_notnull_helper(const void* obj, ptrdiff_t offset)
  47. {
  48. return ((const char*)obj - offset);
  49. }
  50. static inline void* GENC_OVERLOADABLE genc_container_of_notnull_helper(void* obj, ptrdiff_t offset)
  51. {
  52. return ((char*)obj - offset);
  53. }
  54.  
  55. #else
  56. /* function for avoiding multiple evaluation */
  57. static GENC_INLINE void* genc_container_of_helper(void* obj, ptrdiff_t offset)
  58. {
  59. return (obj ? ((char*)obj - offset) : NULL);
  60. }
  61. /* function for avoiding multiple evaluation */
  62. static GENC_INLINE void* genc_container_of_notnull_helper(void* obj, ptrdiff_t offset)
  63. {
  64. return ((char*)obj - offset);
  65. }
  66.  
  67. #if __GNUC__
  68. /* GNU C has some builtin trickery that is almost as good as overloading */
  69. /* function for avoiding multiple evaluation */
  70. static GENC_INLINE const void* genc_container_of_const_helper(const void* obj, ptrdiff_t offset)
  71. {
  72. return (obj ? ((const char*)obj - offset) : NULL);
  73. }
  74. /* function for avoiding multiple evaluation */
  75. static GENC_INLINE const void* genc_container_of_const_notnull_helper(const void* obj, ptrdiff_t offset)
  76. {
  77. return ((const char*)obj - offset);
  78. }
  79.  
  80. #endif
  81.  
  82. #endif
  83.  
  84. #ifdef __cplusplus
  85. extern "C" {
  86. #endif
  87.  
  88. #ifdef __GNUC__
  89.  
  90. #if defined(__cplusplus) || __has_extension(attribute_overloadable)
  91. /* the unused _p attribute is for causing a compiler warning if member_name of
  92. * cont_type does not have same type as target of obj*/
  93. #define genc_container_of(obj, cont_type, member_name) \
  94. ({ \
  95. cont_type* _c = ((cont_type*)genc_container_of_helper((obj), offsetof(cont_type, member_name))); \
  96. __typeof__(obj) __attribute__ ((unused)) _p = _c ? &_c->member_name : NULL; \
  97. _c; \
  98. })
  99.  
  100. #define genc_container_of_notnull(obj, cont_type, member_name) \
  101. ({ \
  102. cont_type* _c = ((cont_type*)genc_container_of_notnull_helper((obj), offsetof(cont_type, member_name))); \
  103. __typeof__(obj) __attribute__ ((unused)) _p = &_c->member_name; \
  104. _c; \
  105. })
  106.  
  107. #else
  108.  
  109. /* GCC builtin trickery (C mode only, no overloading possible) so that different helpers
  110. * get called for const and non-const types (avoids warnings even with -Wcast-qual).
  111. * Checks if pointers to const type and type are compatible - only the case if
  112. * type is already const - and dispatches to the 2 different helper functions. */
  113. #define genc_container_of(obj, cont_type, member_name) \
  114. ({ \
  115. cont_type* _c = \
  116. (cont_type*)(__builtin_choose_expr(__builtin_types_compatible_p(const cont_type*, cont_type*), \
  117. genc_container_of_const_helper, genc_container_of_helper) \
  118. ((obj), offsetof(cont_type, member_name))); \
  119. __typeof__(obj) __attribute__ ((unused)) _p = _c ? &_c->member_name : NULL; \
  120. _c; \
  121. })
  122.  
  123. #define genc_container_of_notnull(obj, cont_type, member_name) \
  124. ({ \
  125. cont_type* _c = \
  126. (cont_type*)(__builtin_choose_expr(__builtin_types_compatible_p(const cont_type*, cont_type*), \
  127. genc_container_of_const_notnull_helper, genc_container_of_notnull_helper) \
  128. ((obj), offsetof(cont_type, member_name))); \
  129. __typeof__(obj) __attribute__ ((unused)) _p = &_c->member_name; \
  130. _c; \
  131. })
  132.  
  133. #endif
  134.  
  135. #else
  136. #define genc_container_of(obj, cont_type, member_name) \
  137. ((cont_type*)genc_container_of_helper((obj), offsetof(cont_type, member_name)))
  138. #define genc_container_of_notnull(obj, cont_type, member_name) \
  139. ((cont_type*)genc_container_of_notnull_helper((obj), offsetof(cont_type, member_name)))
  140. #endif
  141.  
  142. static GENC_INLINE void* genc_member_of_helper(void* obj, ptrdiff_t offset)
  143. {
  144. return obj ? ((char*)obj + offset) : NULL;
  145. }
  146.  
  147. #endif
Add Comment
Please, Sign In to add comment