_RX.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. //
  2. // _RX.h
  3. // RxCocoa
  4. //
  5. // Created by Krunoslav Zaher on 7/12/15.
  6. // Copyright © 2015 Krunoslav Zaher. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. #import <objc/runtime.h>
  10. /**
  11. ################################################################################
  12. This file is part of RX private API
  13. ################################################################################
  14. */
  15. #if TRACE_RESOURCES >= 2
  16. # define DLOG(...) NSLog(__VA_ARGS__)
  17. #else
  18. # define DLOG(...)
  19. #endif
  20. #if DEBUG
  21. # define ABORT_IN_DEBUG abort();
  22. #else
  23. # define ABORT_IN_DEBUG
  24. #endif
  25. #define SEL_VALUE(x) [NSValue valueWithPointer:(x)]
  26. #define CLASS_VALUE(x) [NSValue valueWithNonretainedObject:(x)]
  27. #define IMP_VALUE(x) [NSValue valueWithPointer:(x)]
  28. /**
  29. Checks that the local `error` instance exists before assigning it's value by reference.
  30. This macro exists to work around static analysis warnings — `NSError` is always assumed to be `nullable`, even though we explictly define the method parameter as `nonnull`. See http://www.openradar.me/21766176 for more details.
  31. */
  32. #define RX_SAFE_ERROR(errorValue) if (error != nil) { *error = (errorValue); }
  33. // Inspired by http://p99.gforge.inria.fr
  34. // https://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC26
  35. #define RX_CAT2(_1, _2) _RX_CAT2(_1, _2)
  36. #define RX_ELEMENT_AT(n, ...) RX_CAT2(_RX_ELEMENT_AT_, n)(__VA_ARGS__)
  37. #define RX_COUNT(...) RX_ELEMENT_AT(6, ## __VA_ARGS__, 6, 5, 4, 3, 2, 1, 0)
  38. /**
  39. #define JOIN(context, index, head, tail) head; tail
  40. #define APPLY(context, index, item) item = (context)[index]
  41. RX_FOR(A, JOIN, APPLY, toto, tutu);
  42. toto = (A)[0]; tutu = (A)[1];
  43. */
  44. #define RX_FOR(context, join, generate, ...) RX_CAT2( _RX_FOR_, RX_COUNT(__VA_ARGS__))(context, 0, join, generate, ## __VA_ARGS__)
  45. /**
  46. #define JOIN(context, index, head, tail) head tail
  47. #define APPLY(context, index, item) item = (context)[index]
  48. RX_FOR(A, JOIN, APPLY, toto, tutu);
  49. , toto = (A)[0], tutu = (A)[1]
  50. */
  51. #define RX_FOR_COMMA(context, generate, ...) RX_CAT2( _RX_FOR_COMMA_, RX_COUNT(__VA_ARGS__))(context, 0, generate, ## __VA_ARGS__)
  52. #define RX_INC(x) RX_CAT2(_RX_INC_, x)
  53. // element at
  54. #define _RX_ELEMENT_AT_0(x, ...) x
  55. #define _RX_ELEMENT_AT_1(_0, x, ...) x
  56. #define _RX_ELEMENT_AT_2(_0, _1, x, ...) x
  57. #define _RX_ELEMENT_AT_3(_0, _1, _2, x, ...) x
  58. #define _RX_ELEMENT_AT_4(_0, _1, _2, _3, x, ...) x
  59. #define _RX_ELEMENT_AT_5(_0, _1, _2, _3, _4, x, ...) x
  60. #define _RX_ELEMENT_AT_6(_0, _1, _2, _3, _4, _5, x, ...) x
  61. // rx for
  62. #define _RX_FOR_0(context, index, join, generate)
  63. #define _RX_FOR_1(context, index, join, generate, head) \
  64. generate(context, index, head)
  65. #define _RX_FOR_2(context, index, join, generate, head, ...) \
  66. join(context, index, generate(context, index, head), _RX_FOR_1(context, RX_INC(index), join, generate, __VA_ARGS__))
  67. #define _RX_FOR_3(context, index, join, generate, head, ...) \
  68. join(context, index, generate(context, index, head), _RX_FOR_2(context, RX_INC(index), join, generate, __VA_ARGS__))
  69. #define _RX_FOR_4(context, index, join, generate, head, ...) \
  70. join(context, index, generate(context, index, head), _RX_FOR_3(context, RX_INC(index), join, generate, __VA_ARGS__))
  71. #define _RX_FOR_5(context, index, join, generate, head, ...) \
  72. join(context, index, generate(context, index, head), _RX_FOR_4(context, RX_INC(index), join, generate, __VA_ARGS__))
  73. #define _RX_FOR_6(context, index, join, generate, head, ...) \
  74. join(context, index, generate(context, index, head), _RX_FOR_5(context, RX_INC(index), join, generate, __VA_ARGS__))
  75. // rx for
  76. #define _RX_FOR_COMMA_0(context, index, generate)
  77. #define _RX_FOR_COMMA_1(context, index, generate, head) \
  78. , generate(context, index, head)
  79. #define _RX_FOR_COMMA_2(context, index, generate, head, ...) \
  80. , generate(context, index, head) _RX_FOR_COMMA_1(context, RX_INC(index), generate, __VA_ARGS__)
  81. #define _RX_FOR_COMMA_3(context, index, generate, head, ...) \
  82. , generate(context, index, head) _RX_FOR_COMMA_2(context, RX_INC(index), generate, __VA_ARGS__)
  83. #define _RX_FOR_COMMA_4(context, index, generate, head, ...) \
  84. , generate(context, index, head) _RX_FOR_COMMA_3(context, RX_INC(index), generate, __VA_ARGS__)
  85. #define _RX_FOR_COMMA_5(context, index, generate, head, ...) \
  86. , generate(context, index, head) _RX_FOR_COMMA_4(context, RX_INC(index), generate, __VA_ARGS__)
  87. #define _RX_FOR_COMMA_6(context, index, generate, head, ...) \
  88. , generate(context, index, head) _RX_FOR_COMMA_5(context, RX_INC(index), generate, __VA_ARGS__)
  89. // rx inc
  90. #define _RX_INC_0 1
  91. #define _RX_INC_1 2
  92. #define _RX_INC_2 3
  93. #define _RX_INC_3 4
  94. #define _RX_INC_4 5
  95. #define _RX_INC_5 6
  96. #define _RX_INC_6 7
  97. // rx cat
  98. #define _RX_CAT2(_1, _2) _1 ## _2