CaptainHook.h 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. // Possible defines:
  2. // CHDebug if defined, CHDebugLog is equivalent to CHLog; else, emits no code
  3. // CHUseSubstrate if defined, uses MSMessageHookEx to hook methods, otherwise uses internal hooking routines. Warning! super call closures are only available on ARM platforms for recent releases of MobileSubstrate
  4. // CHEnableProfiling if defined, enables calls to CHProfileScope()
  5. // CHAppName should be set to the name of the application (if not, defaults to "CaptainHook"); used for logging and profiling
  6. #import <objc/runtime.h>
  7. #import <objc/message.h>
  8. #import <Foundation/NSObject.h>
  9. #import <Foundation/NSObjCRuntime.h>
  10. #ifndef CHAppName
  11. #define CHAppName "CaptainHook"
  12. #endif
  13. #ifdef __clang__
  14. #if __has_feature(objc_arc)
  15. #define CHHasARC
  16. #endif
  17. #endif
  18. // Some Debugging/Logging Commands
  19. #define CHStringify_(x) #x
  20. #define CHStringify(x) CHStringify_(x)
  21. #define CHConcat_(a, b) a ## b
  22. #define CHConcat(a, b) CHConcat_(a, b)
  23. #define CHNothing() do { } while(0)
  24. #define CHLocationInSource [NSString stringWithFormat:@CHStringify(__LINE__) " in %s", __FUNCTION__]
  25. #define CHLog(args...) NSLog(@CHAppName ": %@", [NSString stringWithFormat:args])
  26. #define CHLogSource(args...) NSLog(@CHAppName " @ " CHStringify(__LINE__) " in %s: %@", __FUNCTION__, [NSString stringWithFormat:args])
  27. #ifdef CHDebug
  28. #define CHDebugLog(args...) CHLog(args)
  29. #define CHDebugLogSource(args...) CHLogSource(args)
  30. #else
  31. #define CHDebugLog(args...) CHNothing()
  32. #define CHDebugLogSource(args...) CHNothing()
  33. #endif
  34. // Constructor
  35. #define CHConstructor static __attribute__((constructor)) void CHConcat(CHConstructor, __LINE__)()
  36. #define CHInline inline __attribute__((always_inline))
  37. // Cached Class Declaration (allows hooking methods, and fast lookup of classes)
  38. struct CHClassDeclaration_ {
  39. Class class_;
  40. Class metaClass_;
  41. Class superClass_;
  42. };
  43. typedef struct CHClassDeclaration_ CHClassDeclaration_;
  44. #define CHDeclareClass(name) \
  45. @class name; \
  46. static CHClassDeclaration_ name ## $;
  47. // Loading Cached Classes (use CHLoadClass when class is linkable, CHLoadLateClass when it isn't)
  48. static inline Class CHLoadClass_(CHClassDeclaration_ *declaration, Class value)
  49. {
  50. declaration->class_ = value;
  51. declaration->metaClass_ = object_getClass(value);
  52. declaration->superClass_ = class_getSuperclass(value);
  53. return value;
  54. }
  55. #define CHLoadLateClass(name) CHLoadClass_(&name ## $, objc_getClass(#name))
  56. #define CHLoadClass(name) CHLoadClass_(&name ## $, [name class])
  57. // Quick Lookup of cached classes, and common methods on them
  58. #define CHClass(name) name ## $.class_
  59. #define CHMetaClass(name) name ## $.metaClass_
  60. #define CHSuperClass(name) name ## $.superClass_
  61. #define CHAlloc(name) ((name *)[CHClass(name) alloc])
  62. #define CHSharedInstance(name) ((name *)[CHClass(name) sharedInstance])
  63. #define CHIsClass(obj, name) [obj isKindOfClass:CHClass(name)]
  64. #define CHRespondsTo(obj, sel) [obj respondsToSelector:@selector(sel)]
  65. // Replacement Method Definition
  66. #define CHDeclareSig0_(return_type) \
  67. const char *return_ = @encode(return_type); \
  68. size_t return_len = __builtin_strlen(return_); \
  69. char sig[return_len+2+1]; \
  70. __builtin_memcpy(sig, return_, return_len); \
  71. sig[return_len] = _C_ID; \
  72. sig[return_len+1] = _C_SEL; \
  73. sig[return_len+2] = '\0';
  74. #define CHDeclareSig1_(return_type, type1) \
  75. const char *return_ = @encode(return_type); \
  76. size_t return_len = __builtin_strlen(return_); \
  77. const char *type1_ = @encode(type1); \
  78. size_t type1_len = __builtin_strlen(type1_); \
  79. char sig[return_len+2+type1_len+1]; \
  80. __builtin_memcpy(sig, return_, return_len); \
  81. sig[return_len] = _C_ID; \
  82. sig[return_len+1] = _C_SEL; \
  83. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  84. sig[return_len+type1_len+2] = '\0';
  85. #define CHDeclareSig2_(return_type, type1, type2) \
  86. const char *return_ = @encode(return_type); \
  87. size_t return_len = __builtin_strlen(return_); \
  88. const char *type1_ = @encode(type1); \
  89. size_t type1_len = __builtin_strlen(type1_); \
  90. const char *type2_ = @encode(type2); \
  91. size_t type2_len = __builtin_strlen(type2_); \
  92. char sig[return_len+2+type1_len+type2_len+1]; \
  93. __builtin_memcpy(sig, return_, return_len); \
  94. sig[return_len] = _C_ID; \
  95. sig[return_len+1] = _C_SEL; \
  96. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  97. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  98. sig[return_len+type1_len+type2_len+2] = '\0';
  99. #define CHDeclareSig3_(return_type, type1, type2, type3) \
  100. const char *return_ = @encode(return_type); \
  101. size_t return_len = __builtin_strlen(return_); \
  102. const char *type1_ = @encode(type1); \
  103. size_t type1_len = __builtin_strlen(type1_); \
  104. const char *type2_ = @encode(type2); \
  105. size_t type2_len = __builtin_strlen(type2_); \
  106. const char *type3_ = @encode(type3); \
  107. size_t type3_len = __builtin_strlen(type3_); \
  108. char sig[return_len+2+type1_len+type2_len+type3_len+1]; \
  109. __builtin_memcpy(sig, return_, return_len); \
  110. sig[return_len] = _C_ID; \
  111. sig[return_len+1] = _C_SEL; \
  112. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  113. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  114. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  115. sig[return_len+type1_len+type2_len+type3_len+2] = '\0';
  116. #define CHDeclareSig4_(return_type, type1, type2, type3, type4) \
  117. const char *return_ = @encode(return_type); \
  118. size_t return_len = __builtin_strlen(return_); \
  119. const char *type1_ = @encode(type1); \
  120. size_t type1_len = __builtin_strlen(type1_); \
  121. const char *type2_ = @encode(type2); \
  122. size_t type2_len = __builtin_strlen(type2_); \
  123. const char *type3_ = @encode(type3); \
  124. size_t type3_len = __builtin_strlen(type3_); \
  125. const char *type4_ = @encode(type4); \
  126. size_t type4_len = __builtin_strlen(type4_); \
  127. char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+1]; \
  128. __builtin_memcpy(sig, return_, return_len); \
  129. sig[return_len] = _C_ID; \
  130. sig[return_len+1] = _C_SEL; \
  131. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  132. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  133. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  134. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \
  135. sig[return_len+type1_len+type2_len+type3_len+type4_len+2] = '\0';
  136. #define CHDeclareSig5_(return_type, type1, type2, type3, type4, type5) \
  137. const char *return_ = @encode(return_type); \
  138. size_t return_len = __builtin_strlen(return_); \
  139. const char *type1_ = @encode(type1); \
  140. size_t type1_len = __builtin_strlen(type1_); \
  141. const char *type2_ = @encode(type2); \
  142. size_t type2_len = __builtin_strlen(type2_); \
  143. const char *type3_ = @encode(type3); \
  144. size_t type3_len = __builtin_strlen(type3_); \
  145. const char *type4_ = @encode(type4); \
  146. size_t type4_len = __builtin_strlen(type4_); \
  147. const char *type5_ = @encode(type5); \
  148. size_t type5_len = __builtin_strlen(type5_); \
  149. char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+1]; \
  150. __builtin_memcpy(sig, return_, return_len); \
  151. sig[return_len] = _C_ID; \
  152. sig[return_len+1] = _C_SEL; \
  153. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  154. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  155. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  156. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \
  157. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \
  158. sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+2] = '\0';
  159. #define CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6) \
  160. const char *return_ = @encode(return_type); \
  161. size_t return_len = __builtin_strlen(return_); \
  162. const char *type1_ = @encode(type1); \
  163. size_t type1_len = __builtin_strlen(type1_); \
  164. const char *type2_ = @encode(type2); \
  165. size_t type2_len = __builtin_strlen(type2_); \
  166. const char *type3_ = @encode(type3); \
  167. size_t type3_len = __builtin_strlen(type3_); \
  168. const char *type4_ = @encode(type4); \
  169. size_t type4_len = __builtin_strlen(type4_); \
  170. const char *type5_ = @encode(type5); \
  171. size_t type5_len = __builtin_strlen(type5_); \
  172. const char *type6_ = @encode(type6); \
  173. size_t type6_len = __builtin_strlen(type6_); \
  174. char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+1]; \
  175. __builtin_memcpy(sig, return_, return_len); \
  176. sig[return_len] = _C_ID; \
  177. sig[return_len+1] = _C_SEL; \
  178. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  179. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  180. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  181. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \
  182. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \
  183. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len], type6_, type6_len); \
  184. sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+2] = '\0';
  185. #define CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7) \
  186. const char *return_ = @encode(return_type); \
  187. size_t return_len = __builtin_strlen(return_); \
  188. const char *type1_ = @encode(type1); \
  189. size_t type1_len = __builtin_strlen(type1_); \
  190. const char *type2_ = @encode(type2); \
  191. size_t type2_len = __builtin_strlen(type2_); \
  192. const char *type3_ = @encode(type3); \
  193. size_t type3_len = __builtin_strlen(type3_); \
  194. const char *type4_ = @encode(type4); \
  195. size_t type4_len = __builtin_strlen(type4_); \
  196. const char *type5_ = @encode(type5); \
  197. size_t type5_len = __builtin_strlen(type5_); \
  198. const char *type6_ = @encode(type6); \
  199. size_t type6_len = __builtin_strlen(type6_); \
  200. const char *type7_ = @encode(type7); \
  201. size_t type7_len = __builtin_strlen(type7_); \
  202. char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+1]; \
  203. __builtin_memcpy(sig, return_, return_len); \
  204. sig[return_len] = _C_ID; \
  205. sig[return_len+1] = _C_SEL; \
  206. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  207. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  208. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  209. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \
  210. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \
  211. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len], type6_, type6_len); \
  212. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len], type7_, type7_len); \
  213. sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+2] = '\0';
  214. #define CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8) \
  215. const char *return_ = @encode(return_type); \
  216. size_t return_len = __builtin_strlen(return_); \
  217. const char *type1_ = @encode(type1); \
  218. size_t type1_len = __builtin_strlen(type1_); \
  219. const char *type2_ = @encode(type2); \
  220. size_t type2_len = __builtin_strlen(type2_); \
  221. const char *type3_ = @encode(type3); \
  222. size_t type3_len = __builtin_strlen(type3_); \
  223. const char *type4_ = @encode(type4); \
  224. size_t type4_len = __builtin_strlen(type4_); \
  225. const char *type5_ = @encode(type5); \
  226. size_t type5_len = __builtin_strlen(type5_); \
  227. const char *type6_ = @encode(type6); \
  228. size_t type6_len = __builtin_strlen(type6_); \
  229. const char *type7_ = @encode(type7); \
  230. size_t type7_len = __builtin_strlen(type7_); \
  231. const char *type8_ = @encode(type8); \
  232. size_t type8_len = __builtin_strlen(type8_); \
  233. char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len+1]; \
  234. __builtin_memcpy(sig, return_, return_len); \
  235. sig[return_len] = _C_ID; \
  236. sig[return_len+1] = _C_SEL; \
  237. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  238. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  239. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  240. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \
  241. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \
  242. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len], type6_, type6_len); \
  243. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len], type7_, type7_len); \
  244. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len], type8_, type8_len); \
  245. sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len+2] = '\0';
  246. #define CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9) \
  247. const char *return_ = @encode(return_type); \
  248. size_t return_len = __builtin_strlen(return_); \
  249. const char *type1_ = @encode(type1); \
  250. size_t type1_len = __builtin_strlen(type1_); \
  251. const char *type2_ = @encode(type2); \
  252. size_t type2_len = __builtin_strlen(type2_); \
  253. const char *type3_ = @encode(type3); \
  254. size_t type3_len = __builtin_strlen(type3_); \
  255. const char *type4_ = @encode(type4); \
  256. size_t type4_len = __builtin_strlen(type4_); \
  257. const char *type5_ = @encode(type5); \
  258. size_t type5_len = __builtin_strlen(type5_); \
  259. const char *type6_ = @encode(type6); \
  260. size_t type6_len = __builtin_strlen(type6_); \
  261. const char *type7_ = @encode(type7); \
  262. size_t type7_len = __builtin_strlen(type7_); \
  263. const char *type8_ = @encode(type8); \
  264. size_t type8_len = __builtin_strlen(type8_); \
  265. const char *type9_ = @encode(type9); \
  266. size_t type9_len = __builtin_strlen(type9_); \
  267. char sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len+type9_len+1]; \
  268. __builtin_memcpy(sig, return_, return_len); \
  269. sig[return_len] = _C_ID; \
  270. sig[return_len+1] = _C_SEL; \
  271. __builtin_memcpy(&sig[return_len+2], type1_, type1_len); \
  272. __builtin_memcpy(&sig[return_len+2+type1_len], type2_, type2_len); \
  273. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len], type3_, type3_len); \
  274. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len], type4_, type4_len); \
  275. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len], type5_, type5_len); \
  276. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len], type6_, type6_len); \
  277. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len], type7_, type7_len); \
  278. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len], type8_, type8_len); \
  279. __builtin_memcpy(&sig[return_len+2+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len], type9_, type9_len); \
  280. sig[return_len+type1_len+type2_len+type3_len+type4_len+type5_len+type6_len+type7_len+type8_len+type9_len+2] = '\0';
  281. #ifdef CHUseSubstrate
  282. #import <substrate.h>
  283. #define CHMethod_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  284. static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \
  285. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  286. __attribute__((always_inline)) \
  287. static inline void $ ## class_name ## _ ## name ## _register() { \
  288. if (class_val) { \
  289. MSHookMessageEx(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, (IMP *)&$ ## class_name ## _ ## name ## _super); \
  290. if (!$ ## class_name ## _ ## name ## _super) { \
  291. sigdef; \
  292. class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, sig); \
  293. } \
  294. } \
  295. } \
  296. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  297. #define CHMethod_new_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  298. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  299. __attribute__((always_inline)) \
  300. static inline void $ ## class_name ## _ ## name ## _register() { \
  301. sigdef; \
  302. class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, sig); \
  303. } \
  304. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  305. #define CHMethod_super_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  306. static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \
  307. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  308. __attribute__((always_inline)) \
  309. static inline void $ ## class_name ## _ ## name ## _register() { \
  310. if (class_val) { \
  311. MSHookMessageEx(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, (IMP *)&$ ## class_name ## _ ## name ## _super); \
  312. } \
  313. } \
  314. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  315. #define CHMethod_self_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  316. static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \
  317. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  318. __attribute__((always_inline)) \
  319. static inline void $ ## class_name ## _ ## name ## _register() { \
  320. if (class_val) { \
  321. MSHookMessageEx(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, (IMP *)&$ ## class_name ## _ ## name ## _super); \
  322. } \
  323. } \
  324. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  325. #else
  326. #define CHMethod_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  327. static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \
  328. static return_type $ ## class_name ## _ ## name ## _closure(class_type self, SEL _cmd, ##args) { \
  329. typedef return_type (*supType)(class_type, SEL, ## args); \
  330. supType supFn = (supType)class_getMethodImplementation(super_class_val, _cmd); \
  331. return supFn supercall; \
  332. } \
  333. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  334. __attribute__((always_inline)) \
  335. static inline void $ ## class_name ## _ ## name ## _register() { \
  336. Method method = class_getInstanceMethod(class_val, @selector(sel)); \
  337. if (method) { \
  338. $ ## class_name ## _ ## name ## _super = (__typeof__($ ## class_name ## _ ## name ## _super))method_getImplementation(method); \
  339. if (class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, method_getTypeEncoding(method))) { \
  340. $ ## class_name ## _ ## name ## _super = &$ ## class_name ## _ ## name ## _closure; \
  341. } else { \
  342. method_setImplementation(method, (IMP)&$ ## class_name ## _ ## name ## _method); \
  343. } \
  344. } else { \
  345. sigdef; \
  346. class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, sig); \
  347. } \
  348. } \
  349. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  350. #define CHMethod_new_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  351. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  352. __attribute__((always_inline)) \
  353. static inline void $ ## class_name ## _ ## name ## _register() { \
  354. sigdef; \
  355. class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, sig); \
  356. } \
  357. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  358. #define CHMethod_super_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  359. static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \
  360. static return_type $ ## class_name ## _ ## name ## _closure(class_type self, SEL _cmd, ##args) { \
  361. typedef return_type (*supType)(class_type, SEL, ## args); \
  362. supType supFn = (supType)class_getMethodImplementation(super_class_val, _cmd); \
  363. return supFn supercall; \
  364. } \
  365. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  366. __attribute__((always_inline)) \
  367. static inline void $ ## class_name ## _ ## name ## _register() { \
  368. Method method = class_getInstanceMethod(class_val, @selector(sel)); \
  369. if (method) { \
  370. $ ## class_name ## _ ## name ## _super = (__typeof__($ ## class_name ## _ ## name ## _super))method_getImplementation(method); \
  371. if (class_addMethod(class_val, @selector(sel), (IMP)&$ ## class_name ## _ ## name ## _method, method_getTypeEncoding(method))) { \
  372. $ ## class_name ## _ ## name ## _super = &$ ## class_name ## _ ## name ## _closure; \
  373. } else { \
  374. method_setImplementation(method, (IMP)&$ ## class_name ## _ ## name ## _method); \
  375. } \
  376. } \
  377. } \
  378. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  379. #define CHMethod_self_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  380. static return_type (*$ ## class_name ## _ ## name ## _super)(class_type self, SEL _cmd, ##args); \
  381. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args); \
  382. __attribute__((always_inline)) \
  383. static inline void $ ## class_name ## _ ## name ## _register() { \
  384. Method method = class_getInstanceMethod(class_val, @selector(sel)); \
  385. if (method) { \
  386. $ ## class_name ## _ ## name ## _super = (__typeof__($ ## class_name ## _ ## name ## _super))method_getImplementation(method); \
  387. method_setImplementation(method, (IMP)&$ ## class_name ## _ ## name ## _method); \
  388. } \
  389. } \
  390. static return_type $ ## class_name ## _ ## name ## _method(class_type self, SEL _cmd, ##args)
  391. #endif
  392. #define CHMethod(count, args...) \
  393. CHMethod ## count(args)
  394. #define CHMethod0(return_type, class_type, name) \
  395. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name, name, CHDeclareSig0_(return_type), (self, _cmd))
  396. #define CHMethod1(return_type, class_type, name1, type1, arg1) \
  397. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1)
  398. #define CHMethod2(return_type, class_type, name1, type1, arg1, name2, type2, arg2) \
  399. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2)
  400. #define CHMethod3(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \
  401. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3)
  402. #define CHMethod4(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \
  403. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4)
  404. #define CHMethod5(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \
  405. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)
  406. #define CHMethod6(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \
  407. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)
  408. #define CHMethod7(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \
  409. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7)
  410. #define CHMethod8(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \
  411. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8)
  412. #define CHMethod9(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \
  413. CHMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9)
  414. #define CHClassMethod(count, args...) \
  415. CHClassMethod ## count(args)
  416. #define CHClassMethod0(return_type, class_type, name) \
  417. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name, name, CHDeclareSig0_(return_type), (self, _cmd))
  418. #define CHClassMethod1(return_type, class_type, name1, type1, arg1) \
  419. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1)
  420. #define CHClassMethod2(return_type, class_type, name1, type1, arg1, name2, type2, arg2) \
  421. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2)
  422. #define CHClassMethod3(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \
  423. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3)
  424. #define CHClassMethod4(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \
  425. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4)
  426. #define CHClassMethod5(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \
  427. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)
  428. #define CHClassMethod6(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \
  429. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)
  430. #define CHClassMethod7(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \
  431. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7)
  432. #define CHClassMethod8(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \
  433. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8)
  434. #define CHClassMethod9(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \
  435. CHMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9)
  436. #define CHOptimizedMethod(count, args...) \
  437. CHOptimizedMethod ## count(args)
  438. #define CHOptimizedMethod0(optimization, return_type, class_type, name) \
  439. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name, name, CHDeclareSig0_(return_type), (self, _cmd))
  440. #define CHOptimizedMethod1(optimization, return_type, class_type, name1, type1, arg1) \
  441. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1)
  442. #define CHOptimizedMethod2(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2) \
  443. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2)
  444. #define CHOptimizedMethod3(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \
  445. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3)
  446. #define CHOptimizedMethod4(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \
  447. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4)
  448. #define CHOptimizedMethod5(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \
  449. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)
  450. #define CHOptimizedMethod6(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \
  451. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)
  452. #define CHOptimizedMethod7(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \
  453. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7)
  454. #define CHOptimizedMethod8(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \
  455. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8)
  456. #define CHOptimizedMethod9(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \
  457. CHMethod_ ## optimization ## _(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9)
  458. #define CHOptimizedClassMethod(count, args...) \
  459. CHOptimizedClassMethod ## count(args)
  460. #define CHOptimizedClassMethod0(optimization, return_type, class_type, name) \
  461. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name, name, CHDeclareSig0_(return_type), (self, _cmd))
  462. #define CHOptimizedClassMethod1(optimization, return_type, class_type, name1, type1, arg1) \
  463. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1)
  464. #define CHOptimizedClassMethod2(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2) \
  465. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2)
  466. #define CHOptimizedClassMethod3(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \
  467. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3)
  468. #define CHOptimizedClassMethod4(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \
  469. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4)
  470. #define CHOptimizedClassMethod5(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \
  471. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)
  472. #define CHOptimizedClassMethod6(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \
  473. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)
  474. #define CHOptimizedClassMethod7(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \
  475. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7)
  476. #define CHOptimizedClassMethod8(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \
  477. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8)
  478. #define CHOptimizedClassMethod9(optimization, return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \
  479. CHMethod_ ## optimization ## _(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9)
  480. // Replacement Method Registration
  481. #define CHHook_(class_name, name) \
  482. $ ## class_name ## _ ## name ## _register()
  483. #define CHHook(count, args...) CHHook ## count(args)
  484. #define CHHook0(class, name) CHHook_(class, name)
  485. #define CHHook1(class, name1) CHHook_(class, name1 ## $)
  486. #define CHHook2(class, name1, name2) CHHook_(class, name1 ## $ ## name2 ## $)
  487. #define CHHook3(class, name1, name2, name3) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $)
  488. #define CHHook4(class, name1, name2, name3, name4) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $)
  489. #define CHHook5(class, name1, name2, name3, name4, name5) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $)
  490. #define CHHook6(class, name1, name2, name3, name4, name5, name6) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $)
  491. #define CHHook7(class, name1, name2, name3, name4, name5, name6, name7) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $)
  492. #define CHHook8(class, name1, name2, name3, name4, name5, name6, name7, name8) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $)
  493. #define CHHook9(class, name1, name2, name3, name4, name5, name6, name7, name8, name9) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $)
  494. #define CHClassHook(count, args...) CHClassHook ## count(args)
  495. #define CHClassHook0(class, name) CHHook_(class, name)
  496. #define CHClassHook1(class, name1) CHHook_(class, name1 ## $)
  497. #define CHClassHook2(class, name1, name2) CHHook_(class, name1 ## $ ## name2 ## $)
  498. #define CHClassHook3(class, name1, name2, name3) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $)
  499. #define CHClassHook4(class, name1, name2, name3, name4) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $)
  500. #define CHClassHook5(class, name1, name2, name3, name4, name5) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $)
  501. #define CHClassHook6(class, name1, name2, name3, name4, name5, name6) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $)
  502. #define CHClassHook7(class, name1, name2, name3, name4, name5, name6, name7) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $)
  503. #define CHClassHook8(class, name1, name2, name3, name4, name5, name6, name7, name8) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $)
  504. #define CHClassHook9(class, name1, name2, name3, name4, name5, name6, name7, name8, name9) CHHook_(class, name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $)
  505. // Declarative style methods (automatically calls CHHook)
  506. #define CHDeclareMethod_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, args...) \
  507. static inline void $ ## class_name ## _ ## name ## _register(); \
  508. __attribute__((constructor)) \
  509. static inline void $ ## class_name ## _ ## name ## _constructor() { \
  510. CHLoadLateClass(class_name); \
  511. $ ## class_name ## _ ## name ## _register(); \
  512. } \
  513. CHMethod_(return_type, class_type, class_name, class_val, super_class_val, name, sel, sigdef, supercall, ##args)
  514. #define CHDeclareMethod(count, args...) \
  515. CHDeclareMethod ## count(args)
  516. #define CHDeclareMethod0(return_type, class_type, name) \
  517. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name, name, CHDeclareSig0_(return_type), (self, _cmd))
  518. #define CHDeclareMethod1(return_type, class_type, name1, type1, arg1) \
  519. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1)
  520. #define CHDeclareMethod2(return_type, class_type, name1, type1, arg1, name2, type2, arg2) \
  521. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2)
  522. #define CHDeclareMethod3(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \
  523. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3)
  524. #define CHDeclareMethod4(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \
  525. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4)
  526. #define CHDeclareMethod5(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \
  527. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## arg5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)
  528. #define CHDeclareMethod6(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \
  529. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)
  530. #define CHDeclareMethod7(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \
  531. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7)
  532. #define CHDeclareMethod8(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \
  533. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8)
  534. #define CHDeclareMethod9(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \
  535. CHDeclareMethod_(return_type, class_type *, class_type, CHClass(class_type), CHSuperClass(class_type), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9)
  536. #define CHDeclareClassMethod(count, args...) \
  537. CHDeclareClassMethod ## count(args)
  538. #define CHDeclareClassMethod0(return_type, class_type, name) \
  539. CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name, name, CHDeclareSig0_(return_type), (self, _cmd))
  540. #define CHDeclareClassMethod1(return_type, class_type, name1, type1, arg1) \
  541. CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $, name1:, CHDeclareSig1_(return_type, type1), (self, _cmd, arg1), type1 arg1)
  542. #define CHDeclareClassMethod2(return_type, class_type, name1, type1, arg1, name2, type2, arg2) \
  543. CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $, name1:name2:, CHDeclareSig2_(return_type, type1, type2), (self, _cmd, arg1, arg2), type1 arg1, type2 arg2)
  544. #define CHDeclareClassMethod3(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3) \
  545. CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $, name1:name2:name3:, CHDeclareSig3_(return_type, type1, type2, type3), (self, _cmd, arg1, arg2, arg3), type1 arg1, type2 arg2, type3 arg3)
  546. #define CHDeclareClassMethod4(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4) \
  547. CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, name1:name2:name3:name4:, CHDeclareSig4_(return_type, type1, type2, type3, type4), (self, _cmd, arg1, arg2, arg3, arg4), type1 arg1, type2 arg2, type3 arg3, type4 arg4)
  548. #define CHDeclareClassMethod5(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5) \
  549. CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, name1:name2:name3:name4:name5:, CHDeclareSig5_(return_type, type1, type2, type3, type4, type5), (self, _cmd, arg1, arg2, arg3, arg4, arg5), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)
  550. #define CHDeclareClassMethod6(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6) \
  551. CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, name1:name2:name3:name4:name5:name6:, CHDeclareSig6_(return_type, type1, type2, type3, type4, type5, type6), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6)
  552. #define CHDeclareClassMethod7(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7) \
  553. CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, name1:name2:name3:name4:name5:name6:name7:, CHDeclareSig7_(return_type, type1, type2, type3, type4, type5, type6, type7), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7)
  554. #define CHDeclareClassMethod8(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8) \
  555. CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, name1:name2:name3:name4:name5:name6:name7:name8:, CHDeclareSig8_(return_type, type1, type2, type3, type4, type5, type6, type7, type8), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8)
  556. #define CHDeclareClassMethod9(return_type, class_type, name1, type1, arg1, name2, type2, arg2, name3, type3, arg3, name4, type4, arg4, name5, type5, arg5, name6, type6, arg6, name7, type7, arg7, name8, type8, arg8, name9, type9, arg9) \
  557. CHDeclareMethod_(return_type, id, class_type, CHMetaClass(class_type), object_getClass(CHMetaClass(class_type)), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, name1:name2:name3:name4:name5:name6:name7:name8:name9:, CHDeclareSig9_(return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9), (self, _cmd, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6, type7 arg7, type8 arg8, type9 arg9)
  558. // Calling super class (or the old method as the case may be)
  559. #define CHSuper_(class_type, _cmd, name, args...) \
  560. $ ## class_type ## _ ## name ## _super(self, _cmd, ##args)
  561. #define CHSuper(count, args...) \
  562. CHSuper ## count(args)
  563. #define CHSuper0(class_type, name) \
  564. CHSuper_(class_type, @selector(name), name)
  565. #define CHSuper1(class_type, name1, val1) \
  566. CHSuper_(class_type, @selector(name1:), name1 ## $, val1)
  567. #define CHSuper2(class_type, name1, val1, name2, val2) \
  568. CHSuper_(class_type, @selector(name1:name2:), name1 ## $ ## name2 ## $, val1, val2)
  569. #define CHSuper3(class_type, name1, val1, name2, val2, name3, val3) \
  570. CHSuper_(class_type, @selector(name1:name2:name3:), name1 ## $ ## name2 ## $ ## name3 ## $, val1, val2, val3)
  571. #define CHSuper4(class_type, name1, val1, name2, val2, name3, val3, name4, val4) \
  572. CHSuper_(class_type, @selector(name1:name2:name3:name4:), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $, val1, val2, val3, val4)
  573. #define CHSuper5(class_type, name1, val1, name2, val2, name3, val3, name4, val4, name5, val5) \
  574. CHSuper_(class_type, @selector(name1:name2:name3:name4:name5:), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $, val1, val2, val3, val4, val5)
  575. #define CHSuper6(class_type, name1, val1, name2, val2, name3, val3, name4, val4, name5, val5, name6, val6) \
  576. CHSuper_(class_type, @selector(name1:name2:name3:name4:name5:name6:), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $, val1, val2, val3, val4, val5, val6)
  577. #define CHSuper7(class_type, name1, val1, name2, val2, name3, val3, name4, val4, name5, val5, name6, val6, name7, val7) \
  578. CHSuper_(class_type, @selector(name1:name2:name3:name4:name5:name6:name7:), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $, val1, val2, val3, val4, val5, val6, val7)
  579. #define CHSuper8(class_type, name1, val1, name2, val2, name3, val3, name4, val4, name5, val5, name6, val6, name7, val7, name8, val8) \
  580. CHSuper_(class_type, @selector(name1:name2:name3:name4:name5:name6:name7:name8:), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $, val1, val2, val3, val4, val5, val6, val7, val8)
  581. #define CHSuper9(class_type, name1, val1, name2, val2, name3, val3, name4, val4, name5, val5, name6, val6, name7, val7, name8, val8, name9, val9) \
  582. CHSuper_(class_type, @selector(name1:name2:name3:name4:name5:name6:name7:name8:name9:), name1 ## $ ## name2 ## $ ## name3 ## $ ## name4 ## $ ## name5 ## $ ## name6 ## $ ## name7 ## $ ## name8 ## $ ## name9 ## $, val1, val2, val3, val4, val5, val6, val7, val8, val9)
  583. // Create Class at Runtime (useful for creating subclasses of classes that can't be linked)
  584. #define CHRegisterClass(name, superName) for (int _tmp = ({ CHClass(name) = objc_allocateClassPair(CHClass(superName), #name, 0); CHMetaClass(name) = object_getClass(CHClass(name)); CHSuperClass(name) = class_getSuperclass(CHClass(name)); 1; }); _tmp; _tmp = ({ objc_registerClassPair(CHClass(name)), 0; }))
  585. #define CHAlignmentForSize_(size) ({ \
  586. size_t s = size; \
  587. __builtin_constant_p(s) ? ( \
  588. (s) & (1 << 31) ? 31 : \
  589. (s) & (1 << 30) ? 30 : \
  590. (s) & (1 << 29) ? 29 : \
  591. (s) & (1 << 28) ? 28 : \
  592. (s) & (1 << 27) ? 27 : \
  593. (s) & (1 << 26) ? 26 : \
  594. (s) & (1 << 25) ? 25 : \
  595. (s) & (1 << 24) ? 24 : \
  596. (s) & (1 << 23) ? 23 : \
  597. (s) & (1 << 22) ? 22 : \
  598. (s) & (1 << 21) ? 21 : \
  599. (s) & (1 << 20) ? 20 : \
  600. (s) & (1 << 19) ? 19 : \
  601. (s) & (1 << 18) ? 18 : \
  602. (s) & (1 << 17) ? 17 : \
  603. (s) & (1 << 16) ? 16 : \
  604. (s) & (1 << 15) ? 15 : \
  605. (s) & (1 << 14) ? 14 : \
  606. (s) & (1 << 13) ? 13 : \
  607. (s) & (1 << 12) ? 12 : \
  608. (s) & (1 << 11) ? 11 : \
  609. (s) & (1 << 10) ? 10 : \
  610. (s) & (1 << 9) ? 9 : \
  611. (s) & (1 << 8) ? 8 : \
  612. (s) & (1 << 7) ? 7 : \
  613. (s) & (1 << 6) ? 6 : \
  614. (s) & (1 << 5) ? 5 : \
  615. (s) & (1 << 4) ? 4 : \
  616. (s) & (1 << 3) ? 3 : \
  617. (s) & (1 << 2) ? 2 : \
  618. (s) & (1 << 1) ? 1 : \
  619. (s) & (1 << 0) ? 0 : \
  620. 0 \
  621. ) : (uint32_t)log2f(s); \
  622. })
  623. #define CHAddIvar(targetClass, name, type) \
  624. class_addIvar(targetClass, #name, sizeof(type), CHAlignmentForSize_(sizeof(type)), @encode(type))
  625. // Retrieve reference to an Ivar value (can read and assign)
  626. __attribute__((unused)) CHInline
  627. static void *CHIvar_(id object, const char *name)
  628. {
  629. Ivar ivar = class_getInstanceVariable(object_getClass(object), name);
  630. if (ivar)
  631. #ifdef CHHasARC
  632. return (void *)&((char *)(__bridge void *)object)[ivar_getOffset(ivar)];
  633. #else
  634. return (void *)&((char *)object)[ivar_getOffset(ivar)];
  635. #endif
  636. return NULL;
  637. }
  638. #define CHIvarRef(object, name, type) \
  639. ((type *)CHIvar_(object, #name))
  640. #define CHIvar(object, name, type) \
  641. (*CHIvarRef(object, name, type))
  642. // Warning: Dereferences NULL if object is nil or name isn't found. To avoid this save CHIvarRef(...) and test if != NULL
  643. #define CHDeclareProperty(class, name) static const char k ## class ## _ ## name;
  644. #define CHPropertyGetValue(class, name) objc_getAssociatedObject(self, &k ## class ## _ ## name )
  645. #define CHPropertySetValue(class, name, value, policy) objc_setAssociatedObject(self, &k ## class ## _ ## name , value, policy)
  646. #define CHPropertyGetter(class, getter, type) CHOptimizedMethod0(new, type, class, getter)
  647. #define CHPropertySetter(class, setter, type, value) CHOptimizedMethod1(new, void, class, setter, type, value)
  648. // Obj-C dynamic property declaration (objects)
  649. #define CHProperty(class, type, getter, setter, policy) \
  650. CHDeclareProperty(class, getter) \
  651. CHPropertyGetter(class, getter, type) { \
  652. return CHPropertyGetValue(class, getter); \
  653. } \
  654. CHPropertySetter(class, setter, type, getter) { \
  655. CHPropertySetValue(class, getter, getter, policy); \
  656. }
  657. #define CHPropertyRetain(class, type, getter, setter) CHProperty(class, type, getter, setter, OBJC_ASSOCIATION_RETAIN)
  658. #define CHPropertyRetainNonatomic(class, type, getter, setter) CHProperty(class, type, getter, setter, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
  659. #define CHPropertyCopy(class, type, getter, setter) CHProperty(class, type, getter, setter, OBJC_ASSOCIATION_COPY)
  660. #define CHPropertyCopyNonatomic(class, type, getter, setter) CHProperty(class, type, getter, setter, OBJC_ASSOCIATION_COPY_NONATOMIC)
  661. #define CHPropertyAssign(class, type, getter, setter) CHProperty(class, type, getter, setter, OBJC_ASSOCIATION_ASSIGN)
  662. #define CHPrimitivePropertyGetValue(class, name, type, val, default) \
  663. type val = default; \
  664. do { \
  665. NSNumber * objVal = CHPropertyGetValue(class, name); \
  666. [objVal getValue:& val ]; \
  667. } while(0)
  668. #define CHPrimitivePropertySetValue(class, name, type, val) \
  669. do { \
  670. NSValue *objVal = [NSValue value:& val withObjCType:@encode( type )]; \
  671. CHPropertySetValue(class, name, objVal, OBJC_ASSOCIATION_RETAIN_NONATOMIC); \
  672. } while(0)
  673. // Primitive property equivalent (ie. BOOL, int, structs)
  674. #define CHPrimitiveProperty(class, type, getter, setter, default) \
  675. CHDeclareProperty(class, getter) \
  676. CHOptimizedMethod0(new, type, class, getter) { \
  677. CHPrimitivePropertyGetValue( class , getter , type , val , default ); \
  678. return val; \
  679. } \
  680. CHOptimizedMethod1(new, void, class, setter, type, getter) { \
  681. CHPrimitivePropertySetValue( class , getter, type , getter ); \
  682. }
  683. #define CHHookProperty(class, getter, setter) \
  684. do { \
  685. CHHook0(class, getter); \
  686. CHHook1(class, setter); \
  687. } while(0)
  688. #ifndef CHHasARC
  689. // Scope Autorelease
  690. __attribute__((unused)) CHInline
  691. static void CHScopeReleased(id *sro)
  692. {
  693. [*sro release];
  694. }
  695. #define CHScopeReleased \
  696. __attribute__((cleanup(CHScopeReleased)))
  697. #define CHAutoreleasePoolForScope() \
  698. NSAutoreleasePool *CHAutoreleasePoolForScope __attribute__((unused)) CHScopeReleased = [[NSAutoreleasePool alloc] init]
  699. #endif
  700. // Build Assertion
  701. #define CHBuildAssert(condition) \
  702. ((void)sizeof(char[1 - 2*!!(condition)]))
  703. // Profiling
  704. #ifdef CHEnableProfiling
  705. #import <mach/mach_time.h>
  706. struct CHProfileData
  707. {
  708. NSString *message;
  709. uint64_t startTime;
  710. };
  711. __attribute__((unused)) CHInline
  712. static void CHProfileCalculateDurationAndLog_(struct CHProfileData *profileData)
  713. {
  714. uint64_t duration = mach_absolute_time() - profileData->startTime;
  715. mach_timebase_info_data_t info;
  716. mach_timebase_info(&info);
  717. duration = (duration * info.numer) / info.denom;
  718. CHLog(@"Profile time: %lldns; %@", duration, profileData->message);
  719. }
  720. #define CHProfileScopeWithString(string) \
  721. struct CHProfileData _profileData __attribute__((cleanup(CHProfileCalculateDurationAndLog_))) = ({ struct CHProfileData _tmp; _tmp.message = (string); _tmp.startTime = mach_absolute_time(); _tmp; })
  722. #else
  723. #define CHProfileScopeWithString(string) \
  724. CHNothing()
  725. #endif
  726. #define CHProfileScopeWithFormat(args...) \
  727. CHProfileScopeWithString(([NSString stringWithFormat:args]))
  728. #define CHProfileScope() \
  729. CHProfileScopeWithFormat(@CHStringify(__LINE__) " in %s", __FUNCTION__)