motion-yapper 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (294) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +3 -1
  4. data/lib/yapper.rb +3 -3
  5. data/lib/yapper/db.rb +61 -4
  6. data/lib/yapper/document/persistence.rb +4 -0
  7. data/lib/yapper/document/selection.rb +13 -0
  8. data/lib/yapper/version.rb +1 -1
  9. data/motion-yapper.gemspec +1 -1
  10. data/spec/integration/search_spec.rb +111 -0
  11. data/vendor/Podfile.lock +11 -7
  12. data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.bridgesupport +16 -2
  13. data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.h +10 -7
  14. data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.m +20 -2
  15. metadata +19 -297
  16. data/vendor/Pods/.build/libPods-CocoaLumberjack.a +0 -0
  17. data/vendor/Pods/.build/libPods-NSData+MD5Digest.a +0 -0
  18. data/vendor/Pods/.build/libPods-YapDatabase.a +0 -0
  19. data/vendor/Pods/.build/libPods.a +0 -0
  20. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDASLLogger.h +0 -41
  21. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDAbstractDatabaseLogger.h +0 -102
  22. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDContextFilterLogFormatter.h +0 -63
  23. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDDispatchQueueLogFormatter.h +0 -128
  24. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDFileLogger.h +0 -369
  25. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDLog+LOGV.h +0 -99
  26. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDLog.h +0 -634
  27. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDMultiFormatter.h +0 -30
  28. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDTTYLogger.h +0 -181
  29. data/vendor/Pods/BuildHeaders/NSData+MD5Digest/NSData+MD5Digest.h +0 -18
  30. data/vendor/Pods/BuildHeaders/YapDatabase/NSDictionary+YapDatabase.h +0 -8
  31. data/vendor/Pods/BuildHeaders/YapDatabase/YapCache.h +0 -91
  32. data/vendor/Pods/BuildHeaders/YapDatabase/YapCollectionKey.h +0 -23
  33. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabase.h +0 -547
  34. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseConnection.h +0 -449
  35. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseConnectionState.h +0 -29
  36. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseDefaults.h +0 -37
  37. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtension.h +0 -15
  38. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionConnection.h +0 -11
  39. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionPrivate.h +0 -444
  40. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionTransaction.h +0 -11
  41. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredView.h +0 -81
  42. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewConnection.h +0 -12
  43. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewPrivate.h +0 -17
  44. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewTransaction.h +0 -39
  45. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewTypes.h +0 -32
  46. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearch.h +0 -89
  47. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchConnection.h +0 -32
  48. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchPrivate.h +0 -77
  49. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h +0 -79
  50. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchTransaction.h +0 -68
  51. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseLogging.h +0 -158
  52. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseManager.h +0 -17
  53. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabasePrivate.h +0 -446
  54. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseQuery.h +0 -42
  55. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationship.h +0 -35
  56. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipConnection.h +0 -29
  57. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipEdge.h +0 -163
  58. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipEdgePrivate.h +0 -79
  59. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipNode.h +0 -99
  60. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipOptions.h +0 -59
  61. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipPrivate.h +0 -125
  62. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipTransaction.h +0 -384
  63. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndex.h +0 -149
  64. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexConnection.h +0 -33
  65. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexPrivate.h +0 -83
  66. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexSetup.h +0 -33
  67. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexSetupPrivate.h +0 -18
  68. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexTransaction.h +0 -58
  69. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseStatement.h +0 -13
  70. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseString.h +0 -121
  71. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseTransaction.h +0 -651
  72. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseView.h +0 -127
  73. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewChange.h +0 -272
  74. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewChangePrivate.h +0 -94
  75. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewConnection.h +0 -116
  76. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewMappings.h +0 -842
  77. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewMappingsPrivate.h +0 -72
  78. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewOptions.h +0 -63
  79. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPage.h +0 -36
  80. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPageMetadata.h +0 -27
  81. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPrivate.h +0 -170
  82. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewRangeOptions.h +0 -330
  83. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h +0 -17
  84. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewTransaction.h +0 -498
  85. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewTypes.h +0 -99
  86. data/vendor/Pods/BuildHeaders/YapDatabase/YapMemoryTable.h +0 -74
  87. data/vendor/Pods/BuildHeaders/YapDatabase/YapNull.h +0 -17
  88. data/vendor/Pods/BuildHeaders/YapDatabase/YapSet.h +0 -41
  89. data/vendor/Pods/BuildHeaders/YapDatabase/YapTouch.h +0 -15
  90. data/vendor/Pods/CocoaLumberjack/LICENSE.txt +0 -18
  91. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDASLLogger.h +0 -41
  92. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDASLLogger.m +0 -100
  93. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDAbstractDatabaseLogger.h +0 -102
  94. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDAbstractDatabaseLogger.m +0 -727
  95. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDFileLogger.h +0 -369
  96. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDFileLogger.m +0 -1539
  97. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog+LOGV.h +0 -99
  98. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog.h +0 -634
  99. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog.m +0 -1208
  100. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDTTYLogger.h +0 -181
  101. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDTTYLogger.m +0 -1520
  102. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDContextFilterLogFormatter.h +0 -63
  103. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDContextFilterLogFormatter.m +0 -191
  104. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDDispatchQueueLogFormatter.h +0 -128
  105. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDDispatchQueueLogFormatter.m +0 -253
  106. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDMultiFormatter.h +0 -30
  107. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDMultiFormatter.m +0 -127
  108. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/README.txt +0 -7
  109. data/vendor/Pods/CocoaLumberjack/README.markdown +0 -74
  110. data/vendor/Pods/Headers/CocoaLumberjack/DDASLLogger.h +0 -41
  111. data/vendor/Pods/Headers/CocoaLumberjack/DDAbstractDatabaseLogger.h +0 -102
  112. data/vendor/Pods/Headers/CocoaLumberjack/DDContextFilterLogFormatter.h +0 -63
  113. data/vendor/Pods/Headers/CocoaLumberjack/DDDispatchQueueLogFormatter.h +0 -128
  114. data/vendor/Pods/Headers/CocoaLumberjack/DDFileLogger.h +0 -369
  115. data/vendor/Pods/Headers/CocoaLumberjack/DDLog+LOGV.h +0 -99
  116. data/vendor/Pods/Headers/CocoaLumberjack/DDLog.h +0 -634
  117. data/vendor/Pods/Headers/CocoaLumberjack/DDMultiFormatter.h +0 -30
  118. data/vendor/Pods/Headers/CocoaLumberjack/DDTTYLogger.h +0 -181
  119. data/vendor/Pods/Headers/NSData+MD5Digest/NSData+MD5Digest.h +0 -18
  120. data/vendor/Pods/Headers/YapDatabase/YapCollectionKey.h +0 -23
  121. data/vendor/Pods/Headers/YapDatabase/YapDatabase.h +0 -547
  122. data/vendor/Pods/Headers/YapDatabase/YapDatabaseConnection.h +0 -449
  123. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtension.h +0 -15
  124. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionConnection.h +0 -11
  125. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionTransaction.h +0 -11
  126. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredView.h +0 -81
  127. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewConnection.h +0 -12
  128. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewTransaction.h +0 -39
  129. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewTypes.h +0 -32
  130. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearch.h +0 -89
  131. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchConnection.h +0 -32
  132. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h +0 -79
  133. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchTransaction.h +0 -68
  134. data/vendor/Pods/Headers/YapDatabase/YapDatabaseQuery.h +0 -42
  135. data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationship.h +0 -35
  136. data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipConnection.h +0 -29
  137. data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipEdge.h +0 -163
  138. data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipNode.h +0 -99
  139. data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipOptions.h +0 -59
  140. data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipTransaction.h +0 -384
  141. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndex.h +0 -149
  142. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexConnection.h +0 -33
  143. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexSetup.h +0 -33
  144. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexTransaction.h +0 -58
  145. data/vendor/Pods/Headers/YapDatabase/YapDatabaseTransaction.h +0 -651
  146. data/vendor/Pods/Headers/YapDatabase/YapDatabaseView.h +0 -127
  147. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewChange.h +0 -272
  148. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewConnection.h +0 -116
  149. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewMappings.h +0 -842
  150. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewOptions.h +0 -63
  151. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewRangeOptions.h +0 -330
  152. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewTransaction.h +0 -498
  153. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewTypes.h +0 -99
  154. data/vendor/Pods/Headers/YapDatabase/YapSet.h +0 -41
  155. data/vendor/Pods/Headers/____Pods-CocoaLumberjack-prefix.h +0 -7
  156. data/vendor/Pods/Headers/____Pods-NSData+MD5Digest-prefix.h +0 -5
  157. data/vendor/Pods/Headers/____Pods-YapDatabase-prefix.h +0 -5
  158. data/vendor/Pods/Headers/____Pods-environment.h +0 -38
  159. data/vendor/Pods/Manifest.lock +0 -22
  160. data/vendor/Pods/NSData+MD5Digest/NSData+MD5Digest/NSData+MD5Digest.h +0 -18
  161. data/vendor/Pods/NSData+MD5Digest/NSData+MD5Digest/NSData+MD5Digest.m +0 -39
  162. data/vendor/Pods/NSData+MD5Digest/README.md +0 -11
  163. data/vendor/Pods/Pods-CocoaLumberjack-Private.xcconfig +0 -5
  164. data/vendor/Pods/Pods-CocoaLumberjack-dummy.m +0 -5
  165. data/vendor/Pods/Pods-CocoaLumberjack-prefix.pch +0 -7
  166. data/vendor/Pods/Pods-CocoaLumberjack.xcconfig +0 -0
  167. data/vendor/Pods/Pods-NSData+MD5Digest-Private.xcconfig +0 -5
  168. data/vendor/Pods/Pods-NSData+MD5Digest-dummy.m +0 -5
  169. data/vendor/Pods/Pods-NSData+MD5Digest-prefix.pch +0 -5
  170. data/vendor/Pods/Pods-NSData+MD5Digest.xcconfig +0 -0
  171. data/vendor/Pods/Pods-YapDatabase-Private.xcconfig +0 -5
  172. data/vendor/Pods/Pods-YapDatabase-dummy.m +0 -5
  173. data/vendor/Pods/Pods-YapDatabase-prefix.pch +0 -5
  174. data/vendor/Pods/Pods-YapDatabase.xcconfig +0 -1
  175. data/vendor/Pods/Pods-acknowledgements.markdown +0 -59
  176. data/vendor/Pods/Pods-acknowledgements.plist +0 -97
  177. data/vendor/Pods/Pods-dummy.m +0 -5
  178. data/vendor/Pods/Pods-environment.h +0 -38
  179. data/vendor/Pods/Pods-resources.sh +0 -68
  180. data/vendor/Pods/Pods.xcconfig +0 -5
  181. data/vendor/Pods/Pods.xcodeproj/project.pbxproj +0 -4807
  182. data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/Pods-CocoaLumberjack.xcscheme +0 -59
  183. data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/Pods-NSData+MD5Digest.xcscheme +0 -59
  184. data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/Pods-YapDatabase.xcscheme +0 -59
  185. data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/Pods.xcscheme +0 -59
  186. data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/xcschememanagement.plist +0 -31
  187. data/vendor/Pods/YapDatabase/LICENSE.txt +0 -18
  188. data/vendor/Pods/YapDatabase/README.md +0 -32
  189. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/Internal/YapDatabaseFilteredViewPrivate.h +0 -17
  190. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.h +0 -81
  191. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.m +0 -159
  192. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.h +0 -12
  193. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.m +0 -41
  194. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.h +0 -39
  195. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.m +0 -1235
  196. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.h +0 -32
  197. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/Internal/YapDatabaseFullTextSearchPrivate.h +0 -77
  198. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.h +0 -89
  199. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.m +0 -146
  200. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.h +0 -32
  201. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.m +0 -298
  202. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.h +0 -79
  203. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.m +0 -95
  204. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.h +0 -68
  205. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.m +0 -1403
  206. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/Internal/YapDatabaseExtensionPrivate.h +0 -444
  207. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.h +0 -15
  208. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.m +0 -83
  209. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.h +0 -11
  210. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.m +0 -46
  211. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.h +0 -11
  212. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.m +0 -204
  213. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipEdgePrivate.h +0 -79
  214. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipPrivate.h +0 -125
  215. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationship.h +0 -35
  216. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationship.m +0 -129
  217. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.h +0 -29
  218. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.m +0 -802
  219. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.h +0 -163
  220. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.m +0 -408
  221. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipNode.h +0 -99
  222. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.h +0 -59
  223. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.m +0 -29
  224. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.h +0 -384
  225. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.m +0 -5254
  226. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexPrivate.h +0 -83
  227. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexSetupPrivate.h +0 -18
  228. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.h +0 -149
  229. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.m +0 -161
  230. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.h +0 -33
  231. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.m +0 -331
  232. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.h +0 -33
  233. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.m +0 -245
  234. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.h +0 -58
  235. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m +0 -1269
  236. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewChangePrivate.h +0 -94
  237. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewMappingsPrivate.h +0 -72
  238. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.h +0 -36
  239. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.mm +0 -296
  240. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.h +0 -27
  241. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.m +0 -28
  242. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h +0 -170
  243. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewRangeOptionsPrivate.h +0 -17
  244. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.h +0 -272
  245. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.m +0 -2500
  246. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.h +0 -842
  247. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.m +0 -1714
  248. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.h +0 -330
  249. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.m +0 -141
  250. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.h +0 -127
  251. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.m +0 -194
  252. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.h +0 -116
  253. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.m +0 -888
  254. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.h +0 -63
  255. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.m +0 -27
  256. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h +0 -498
  257. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m +0 -4986
  258. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTypes.h +0 -99
  259. data/vendor/Pods/YapDatabase/YapDatabase/Internal/NSDictionary+YapDatabase.h +0 -8
  260. data/vendor/Pods/YapDatabase/YapDatabase/Internal/NSDictionary+YapDatabase.m +0 -19
  261. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapCache.h +0 -91
  262. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapCache.m +0 -465
  263. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseConnectionState.h +0 -29
  264. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseConnectionState.m +0 -48
  265. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseDefaults.h +0 -37
  266. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseDefaults.m +0 -83
  267. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseLogging.h +0 -158
  268. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseLogging.m +0 -73
  269. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseManager.h +0 -17
  270. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseManager.m +0 -56
  271. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabasePrivate.h +0 -446
  272. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseStatement.h +0 -13
  273. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseStatement.m +0 -26
  274. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseString.h +0 -121
  275. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapMemoryTable.h +0 -74
  276. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapMemoryTable.m +0 -603
  277. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapNull.h +0 -17
  278. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapNull.m +0 -35
  279. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapTouch.h +0 -15
  280. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapTouch.m +0 -31
  281. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.h +0 -23
  282. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.m +0 -199
  283. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.h +0 -42
  284. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.m +0 -96
  285. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapSet.h +0 -41
  286. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapSet.m +0 -82
  287. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabase.h +0 -547
  288. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabase.m +0 -2013
  289. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.h +0 -449
  290. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.m +0 -4046
  291. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.h +0 -651
  292. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.m +0 -5602
  293. data/vendor/Pods/build-iPhoneSimulator/Pods.bridgesupport +0 -3172
  294. data/vendor/Pods/build-iPhoneSimulator/libPods.a +0 -0
@@ -1,1208 +0,0 @@
1
- #import "DDLog.h"
2
-
3
- #import <pthread.h>
4
- #import <objc/runtime.h>
5
- #import <mach/mach_host.h>
6
- #import <mach/host_info.h>
7
- #import <libkern/OSAtomic.h>
8
- #import <Availability.h>
9
- #if TARGET_OS_IPHONE
10
- #import <UIKit/UIDevice.h>
11
- #endif
12
-
13
- /**
14
- * Welcome to Cocoa Lumberjack!
15
- *
16
- * The project page has a wealth of documentation if you have any questions.
17
- * https://github.com/CocoaLumberjack/CocoaLumberjack
18
- *
19
- * If you're new to the project you may wish to read the "Getting Started" wiki.
20
- * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted
21
- *
22
- **/
23
-
24
- #if ! __has_feature(objc_arc)
25
- #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
26
- #endif
27
-
28
- // We probably shouldn't be using DDLog() statements within the DDLog implementation.
29
- // But we still want to leave our log statements for any future debugging,
30
- // and to allow other developers to trace the implementation (which is a great learning tool).
31
- //
32
- // So we use a primitive logging macro around NSLog.
33
- // We maintain the NS prefix on the macros to be explicit about the fact that we're using NSLog.
34
-
35
- #define DD_DEBUG NO
36
-
37
- #define NSLogDebug(frmt, ...) do{ if(DD_DEBUG) NSLog((frmt), ##__VA_ARGS__); } while(0)
38
-
39
- // Specifies the maximum queue size of the logging thread.
40
- //
41
- // Since most logging is asynchronous, its possible for rogue threads to flood the logging queue.
42
- // That is, to issue an abundance of log statements faster than the logging thread can keepup.
43
- // Typically such a scenario occurs when log statements are added haphazardly within large loops,
44
- // but may also be possible if relatively slow loggers are being used.
45
- //
46
- // This property caps the queue size at a given number of outstanding log statements.
47
- // If a thread attempts to issue a log statement when the queue is already maxed out,
48
- // the issuing thread will block until the queue size drops below the max again.
49
-
50
- #define LOG_MAX_QUEUE_SIZE 1000 // Should not exceed INT32_MAX
51
-
52
- // The "global logging queue" refers to [DDLog loggingQueue].
53
- // It is the queue that all log statements go through.
54
- //
55
- // The logging queue sets a flag via dispatch_queue_set_specific using this key.
56
- // We can check for this key via dispatch_get_specific() to see if we're on the "global logging queue".
57
-
58
- static void *const GlobalLoggingQueueIdentityKey = (void *)&GlobalLoggingQueueIdentityKey;
59
-
60
-
61
- @interface DDLoggerNode : NSObject {
62
- @public
63
- id <DDLogger> logger;
64
- dispatch_queue_t loggerQueue;
65
- int logLevel;
66
- }
67
-
68
- @property (nonatomic, assign, readonly) int logLevel;
69
-
70
- + (DDLoggerNode *)nodeWithLogger:(id <DDLogger>)logger loggerQueue:(dispatch_queue_t)loggerQueue logLevel:(int)logLevel;
71
-
72
- @end
73
-
74
-
75
- @interface DDLog (PrivateAPI)
76
-
77
- + (void)lt_addLogger:(id <DDLogger>)logger logLevel:(int)logLevel;
78
- + (void)lt_removeLogger:(id <DDLogger>)logger;
79
- + (void)lt_removeAllLoggers;
80
- + (NSArray *)lt_allLoggers;
81
- + (void)lt_log:(DDLogMessage *)logMessage;
82
- + (void)lt_flush;
83
-
84
- @end
85
-
86
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
87
- #pragma mark -
88
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
89
-
90
- @implementation DDLog
91
-
92
- // An array used to manage all the individual loggers.
93
- // The array is only modified on the loggingQueue/loggingThread.
94
- static NSMutableArray *loggers;
95
-
96
- // All logging statements are added to the same queue to ensure FIFO operation.
97
- static dispatch_queue_t loggingQueue;
98
-
99
- // Individual loggers are executed concurrently per log statement.
100
- // Each logger has it's own associated queue, and a dispatch group is used for synchrnoization.
101
- static dispatch_group_t loggingGroup;
102
-
103
- // In order to prevent to queue from growing infinitely large,
104
- // a maximum size is enforced (LOG_MAX_QUEUE_SIZE).
105
- static dispatch_semaphore_t queueSemaphore;
106
-
107
- // Minor optimization for uniprocessor machines
108
- static unsigned int numProcessors;
109
-
110
- /**
111
- * The runtime sends initialize to each class in a program exactly one time just before the class,
112
- * or any class that inherits from it, is sent its first message from within the program. (Thus the
113
- * method may never be invoked if the class is not used.) The runtime sends the initialize message to
114
- * classes in a thread-safe manner. Superclasses receive this message before their subclasses.
115
- *
116
- * This method may also be called directly (assumably by accident), hence the safety mechanism.
117
- **/
118
- + (void)initialize
119
- {
120
- static BOOL initialized = NO;
121
- if (!initialized)
122
- {
123
- initialized = YES;
124
-
125
- loggers = [[NSMutableArray alloc] initWithCapacity:4];
126
-
127
- NSLogDebug(@"DDLog: Using grand central dispatch");
128
-
129
- loggingQueue = dispatch_queue_create("cocoa.lumberjack", NULL);
130
- loggingGroup = dispatch_group_create();
131
-
132
- void *nonNullValue = GlobalLoggingQueueIdentityKey; // Whatever, just not null
133
- dispatch_queue_set_specific(loggingQueue, GlobalLoggingQueueIdentityKey, nonNullValue, NULL);
134
-
135
- queueSemaphore = dispatch_semaphore_create(LOG_MAX_QUEUE_SIZE);
136
-
137
- // Figure out how many processors are available.
138
- // This may be used later for an optimization on uniprocessor machines.
139
-
140
- host_basic_info_data_t hostInfo;
141
- mach_msg_type_number_t infoCount;
142
-
143
- infoCount = HOST_BASIC_INFO_COUNT;
144
- host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount);
145
-
146
- unsigned int result = (unsigned int)(hostInfo.max_cpus);
147
- unsigned int one = (unsigned int)(1);
148
-
149
- numProcessors = MAX(result, one);
150
-
151
- NSLogDebug(@"DDLog: numProcessors = %u", numProcessors);
152
-
153
-
154
- #if TARGET_OS_IPHONE
155
- NSString *notificationName = @"UIApplicationWillTerminateNotification";
156
- #else
157
- NSString *notificationName = nil;
158
-
159
- if (NSClassFromString(@"NSApplication"))
160
- {
161
- notificationName = @"NSApplicationWillTerminateNotification";
162
- }
163
- else
164
- {
165
- // If there is no NSApp -> we are running Command Line Tool app.
166
- // In this case terminate notification wouldn't be fired, so we use workaround.
167
- atexit_b(^{
168
- [self applicationWillTerminate:nil];
169
- });
170
- }
171
- #endif
172
-
173
- if (notificationName) {
174
- [[NSNotificationCenter defaultCenter] addObserver:self
175
- selector:@selector(applicationWillTerminate:)
176
- name:notificationName
177
- object:nil];
178
- }
179
- }
180
- }
181
-
182
- /**
183
- * Provides access to the logging queue.
184
- **/
185
- + (dispatch_queue_t)loggingQueue
186
- {
187
- return loggingQueue;
188
- }
189
-
190
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
191
- #pragma mark Notifications
192
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
193
-
194
- + (void)applicationWillTerminate:(NSNotification *)notification
195
- {
196
- [self flushLog];
197
- }
198
-
199
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
200
- #pragma mark Logger Management
201
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
202
-
203
- + (void)addLogger:(id <DDLogger>)logger
204
- {
205
- [self addLogger:logger withLogLevel:LOG_LEVEL_VERBOSE];
206
- }
207
-
208
- + (void)addLogger:(id <DDLogger>)logger withLogLevel:(int)logLevel
209
- {
210
- if (logger == nil) return;
211
-
212
- dispatch_async(loggingQueue, ^{ @autoreleasepool {
213
-
214
- [self lt_addLogger:logger logLevel:logLevel];
215
- }});
216
- }
217
-
218
- + (void)removeLogger:(id <DDLogger>)logger
219
- {
220
- if (logger == nil) return;
221
-
222
- dispatch_async(loggingQueue, ^{ @autoreleasepool {
223
-
224
- [self lt_removeLogger:logger];
225
- }});
226
- }
227
-
228
- + (void)removeAllLoggers
229
- {
230
- dispatch_async(loggingQueue, ^{ @autoreleasepool {
231
-
232
- [self lt_removeAllLoggers];
233
- }});
234
- }
235
-
236
- + (NSArray *)allLoggers
237
- {
238
- __block NSArray *theLoggers;
239
-
240
- dispatch_sync(loggingQueue, ^{ @autoreleasepool {
241
- theLoggers = [self lt_allLoggers];
242
- }});
243
-
244
- return theLoggers;
245
- }
246
-
247
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
248
- #pragma mark Master Logging
249
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
250
-
251
- + (void)queueLogMessage:(DDLogMessage *)logMessage asynchronously:(BOOL)asyncFlag
252
- {
253
- // We have a tricky situation here...
254
- //
255
- // In the common case, when the queueSize is below the maximumQueueSize,
256
- // we want to simply enqueue the logMessage. And we want to do this as fast as possible,
257
- // which means we don't want to block and we don't want to use any locks.
258
- //
259
- // However, if the queueSize gets too big, we want to block.
260
- // But we have very strict requirements as to when we block, and how long we block.
261
- //
262
- // The following example should help illustrate our requirements:
263
- //
264
- // Imagine that the maximum queue size is configured to be 5,
265
- // and that there are already 5 log messages queued.
266
- // Let us call these 5 queued log messages A, B, C, D, and E. (A is next to be executed)
267
- //
268
- // Now if our thread issues a log statement (let us call the log message F),
269
- // it should block before the message is added to the queue.
270
- // Furthermore, it should be unblocked immediately after A has been unqueued.
271
- //
272
- // The requirements are strict in this manner so that we block only as long as necessary,
273
- // and so that blocked threads are unblocked in the order in which they were blocked.
274
- //
275
- // Returning to our previous example, let us assume that log messages A through E are still queued.
276
- // Our aforementioned thread is blocked attempting to queue log message F.
277
- // Now assume we have another separate thread that attempts to issue log message G.
278
- // It should block until log messages A and B have been unqueued.
279
-
280
-
281
- // We are using a counting semaphore provided by GCD.
282
- // The semaphore is initialized with our LOG_MAX_QUEUE_SIZE value.
283
- // Everytime we want to queue a log message we decrement this value.
284
- // If the resulting value is less than zero,
285
- // the semaphore function waits in FIFO order for a signal to occur before returning.
286
- //
287
- // A dispatch semaphore is an efficient implementation of a traditional counting semaphore.
288
- // Dispatch semaphores call down to the kernel only when the calling thread needs to be blocked.
289
- // If the calling semaphore does not need to block, no kernel call is made.
290
-
291
- dispatch_semaphore_wait(queueSemaphore, DISPATCH_TIME_FOREVER);
292
-
293
- // We've now sure we won't overflow the queue.
294
- // It is time to queue our log message.
295
-
296
- dispatch_block_t logBlock = ^{ @autoreleasepool {
297
-
298
- [self lt_log:logMessage];
299
- }};
300
-
301
- if (asyncFlag)
302
- dispatch_async(loggingQueue, logBlock);
303
- else
304
- dispatch_sync(loggingQueue, logBlock);
305
- }
306
-
307
- + (void)log:(BOOL)asynchronous
308
- level:(int)level
309
- flag:(int)flag
310
- context:(int)context
311
- file:(const char *)file
312
- function:(const char *)function
313
- line:(int)line
314
- tag:(id)tag
315
- format:(NSString *)format, ...
316
- {
317
- va_list args;
318
- if (format)
319
- {
320
- va_start(args, format);
321
-
322
- NSString *logMsg = [[NSString alloc] initWithFormat:format arguments:args];
323
- DDLogMessage *logMessage = [[DDLogMessage alloc] initWithLogMsg:logMsg
324
- level:level
325
- flag:flag
326
- context:context
327
- file:file
328
- function:function
329
- line:line
330
- tag:tag
331
- options:0];
332
-
333
- [self queueLogMessage:logMessage asynchronously:asynchronous];
334
-
335
- va_end(args);
336
- }
337
- }
338
-
339
- + (void)log:(BOOL)asynchronous
340
- level:(int)level
341
- flag:(int)flag
342
- context:(int)context
343
- file:(const char *)file
344
- function:(const char *)function
345
- line:(int)line
346
- tag:(id)tag
347
- format:(NSString *)format
348
- args:(va_list)args
349
- {
350
- if (format)
351
- {
352
- NSString *logMsg = [[NSString alloc] initWithFormat:format arguments:args];
353
- DDLogMessage *logMessage = [[DDLogMessage alloc] initWithLogMsg:logMsg
354
- level:level
355
- flag:flag
356
- context:context
357
- file:file
358
- function:function
359
- line:line
360
- tag:tag
361
- options:0];
362
-
363
- [self queueLogMessage:logMessage asynchronously:asynchronous];
364
- }
365
- }
366
-
367
- + (void)flushLog
368
- {
369
- dispatch_sync(loggingQueue, ^{ @autoreleasepool {
370
-
371
- [self lt_flush];
372
- }});
373
- }
374
-
375
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
376
- #pragma mark Registered Dynamic Logging
377
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
378
-
379
- + (BOOL)isRegisteredClass:(Class)class
380
- {
381
- SEL getterSel = @selector(ddLogLevel);
382
- SEL setterSel = @selector(ddSetLogLevel:);
383
-
384
- #if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
385
-
386
- // Issue #6 (GoogleCode) - Crashes on iOS 4.2.1 and iPhone 4
387
- //
388
- // Crash caused by class_getClassMethod(2).
389
- //
390
- // "It's a bug with UIAccessibilitySafeCategory__NSObject so it didn't pop up until
391
- // users had VoiceOver enabled [...]. I was able to work around it by searching the
392
- // result of class_copyMethodList() instead of calling class_getClassMethod()"
393
-
394
- BOOL result = NO;
395
-
396
- unsigned int methodCount, i;
397
- Method *methodList = class_copyMethodList(object_getClass(class), &methodCount);
398
-
399
- if (methodList != NULL)
400
- {
401
- BOOL getterFound = NO;
402
- BOOL setterFound = NO;
403
-
404
- for (i = 0; i < methodCount; ++i)
405
- {
406
- SEL currentSel = method_getName(methodList[i]);
407
-
408
- if (currentSel == getterSel)
409
- {
410
- getterFound = YES;
411
- }
412
- else if (currentSel == setterSel)
413
- {
414
- setterFound = YES;
415
- }
416
-
417
- if (getterFound && setterFound)
418
- {
419
- result = YES;
420
- break;
421
- }
422
- }
423
-
424
- free(methodList);
425
- }
426
-
427
- return result;
428
-
429
- #else
430
-
431
- // Issue #24 (GitHub) - Crashing in in ARC+Simulator
432
- //
433
- // The method +[DDLog isRegisteredClass] will crash a project when using it with ARC + Simulator.
434
- // For running in the Simulator, it needs to execute the non-iOS code.
435
-
436
- Method getter = class_getClassMethod(class, getterSel);
437
- Method setter = class_getClassMethod(class, setterSel);
438
-
439
- if ((getter != NULL) && (setter != NULL))
440
- {
441
- return YES;
442
- }
443
-
444
- return NO;
445
-
446
- #endif
447
- }
448
-
449
- + (NSArray *)registeredClasses
450
- {
451
- int numClasses, i;
452
-
453
- // We're going to get the list of all registered classes.
454
- // The Objective-C runtime library automatically registers all the classes defined in your source code.
455
- //
456
- // To do this we use the following method (documented in the Objective-C Runtime Reference):
457
- //
458
- // int objc_getClassList(Class *buffer, int bufferLen)
459
- //
460
- // We can pass (NULL, 0) to obtain the total number of
461
- // registered class definitions without actually retrieving any class definitions.
462
- // This allows us to allocate the minimum amount of memory needed for the application.
463
-
464
- numClasses = objc_getClassList(NULL, 0);
465
-
466
- // The numClasses method now tells us how many classes we have.
467
- // So we can allocate our buffer, and get pointers to all the class definitions.
468
-
469
- Class *classes = (Class *)malloc(sizeof(Class) * numClasses);
470
- if (classes == NULL) return nil;
471
-
472
- numClasses = objc_getClassList(classes, numClasses);
473
-
474
- // We can now loop through the classes, and test each one to see if it is a DDLogging class.
475
-
476
- NSMutableArray *result = [NSMutableArray arrayWithCapacity:numClasses];
477
-
478
- for (i = 0; i < numClasses; i++)
479
- {
480
- Class class = classes[i];
481
-
482
- if ([self isRegisteredClass:class])
483
- {
484
- [result addObject:class];
485
- }
486
- }
487
-
488
- free(classes);
489
-
490
- return result;
491
- }
492
-
493
- + (NSArray *)registeredClassNames
494
- {
495
- NSArray *registeredClasses = [self registeredClasses];
496
- NSMutableArray *result = [NSMutableArray arrayWithCapacity:[registeredClasses count]];
497
-
498
- for (Class class in registeredClasses)
499
- {
500
- [result addObject:NSStringFromClass(class)];
501
- }
502
-
503
- return result;
504
- }
505
-
506
- + (int)logLevelForClass:(Class)aClass
507
- {
508
- if ([self isRegisteredClass:aClass])
509
- {
510
- return [aClass ddLogLevel];
511
- }
512
-
513
- return -1;
514
- }
515
-
516
- + (int)logLevelForClassWithName:(NSString *)aClassName
517
- {
518
- Class aClass = NSClassFromString(aClassName);
519
-
520
- return [self logLevelForClass:aClass];
521
- }
522
-
523
- + (void)setLogLevel:(int)logLevel forClass:(Class)aClass
524
- {
525
- if ([self isRegisteredClass:aClass])
526
- {
527
- [aClass ddSetLogLevel:logLevel];
528
- }
529
- }
530
-
531
- + (void)setLogLevel:(int)logLevel forClassWithName:(NSString *)aClassName
532
- {
533
- Class aClass = NSClassFromString(aClassName);
534
-
535
- [self setLogLevel:logLevel forClass:aClass];
536
- }
537
-
538
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
539
- #pragma mark Logging Thread
540
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
541
-
542
- + (void)lt_addLogger:(id <DDLogger>)logger logLevel:(int)logLevel
543
- {
544
- // Add to loggers array.
545
- // Need to create loggerQueue if loggerNode doesn't provide one.
546
-
547
- NSAssert(dispatch_get_specific(GlobalLoggingQueueIdentityKey),
548
- @"This method should only be run on the logging thread/queue");
549
-
550
- dispatch_queue_t loggerQueue = NULL;
551
-
552
- if ([logger respondsToSelector:@selector(loggerQueue)])
553
- {
554
- // Logger may be providing its own queue
555
-
556
- loggerQueue = [logger loggerQueue];
557
- }
558
-
559
- if (loggerQueue == nil)
560
- {
561
- // Automatically create queue for the logger.
562
- // Use the logger name as the queue name if possible.
563
-
564
- const char *loggerQueueName = NULL;
565
- if ([logger respondsToSelector:@selector(loggerName)])
566
- {
567
- loggerQueueName = [[logger loggerName] UTF8String];
568
- }
569
-
570
- loggerQueue = dispatch_queue_create(loggerQueueName, NULL);
571
- }
572
-
573
- DDLoggerNode *loggerNode = [DDLoggerNode nodeWithLogger:logger loggerQueue:loggerQueue logLevel:logLevel];
574
- [loggers addObject:loggerNode];
575
-
576
- if ([logger respondsToSelector:@selector(didAddLogger)])
577
- {
578
- dispatch_async(loggerNode->loggerQueue, ^{ @autoreleasepool {
579
-
580
- [logger didAddLogger];
581
- }});
582
- }
583
- }
584
-
585
- + (void)lt_removeLogger:(id <DDLogger>)logger
586
- {
587
- // Find associated loggerNode in list of added loggers
588
-
589
- NSAssert(dispatch_get_specific(GlobalLoggingQueueIdentityKey),
590
- @"This method should only be run on the logging thread/queue");
591
-
592
- DDLoggerNode *loggerNode = nil;
593
-
594
- for (DDLoggerNode *node in loggers)
595
- {
596
- if (node->logger == logger)
597
- {
598
- loggerNode = node;
599
- break;
600
- }
601
- }
602
-
603
- if (loggerNode == nil)
604
- {
605
- NSLogDebug(@"DDLog: Request to remove logger which wasn't added");
606
- return;
607
- }
608
-
609
- // Notify logger
610
-
611
- if ([logger respondsToSelector:@selector(willRemoveLogger)])
612
- {
613
- dispatch_async(loggerNode->loggerQueue, ^{ @autoreleasepool {
614
-
615
- [logger willRemoveLogger];
616
- }});
617
- }
618
-
619
- // Remove from loggers array
620
-
621
- [loggers removeObject:loggerNode];
622
- }
623
-
624
- + (void)lt_removeAllLoggers
625
- {
626
- // Notify all loggers
627
-
628
- NSAssert(dispatch_get_specific(GlobalLoggingQueueIdentityKey),
629
- @"This method should only be run on the logging thread/queue");
630
-
631
- for (DDLoggerNode *loggerNode in loggers)
632
- {
633
- if ([loggerNode->logger respondsToSelector:@selector(willRemoveLogger)])
634
- {
635
- dispatch_async(loggerNode->loggerQueue, ^{ @autoreleasepool {
636
-
637
- [loggerNode->logger willRemoveLogger];
638
- }});
639
- }
640
- }
641
-
642
- // Remove all loggers from array
643
-
644
- [loggers removeAllObjects];
645
- }
646
-
647
- + (NSArray *)lt_allLoggers
648
- {
649
- NSAssert(dispatch_get_specific(GlobalLoggingQueueIdentityKey),
650
- @"This method should only be run on the logging thread/queue");
651
-
652
- NSMutableArray *theLoggers = [NSMutableArray new];
653
-
654
- for (DDLoggerNode *loggerNode in loggers)
655
- {
656
- [theLoggers addObject:loggerNode->logger];
657
- }
658
-
659
- return [theLoggers copy];
660
- }
661
-
662
- + (void)lt_log:(DDLogMessage *)logMessage
663
- {
664
- // Execute the given log message on each of our loggers.
665
-
666
- NSAssert(dispatch_get_specific(GlobalLoggingQueueIdentityKey),
667
- @"This method should only be run on the logging thread/queue");
668
-
669
- if (numProcessors > 1)
670
- {
671
- // Execute each logger concurrently, each within its own queue.
672
- // All blocks are added to same group.
673
- // After each block has been queued, wait on group.
674
- //
675
- // The waiting ensures that a slow logger doesn't end up with a large queue of pending log messages.
676
- // This would defeat the purpose of the efforts we made earlier to restrict the max queue size.
677
-
678
- for (DDLoggerNode *loggerNode in loggers)
679
- {
680
- // skip the loggers that shouldn't write this message based on the logLevel
681
-
682
- if (!(logMessage->logFlag & loggerNode.logLevel))
683
- continue;
684
-
685
- dispatch_group_async(loggingGroup, loggerNode->loggerQueue, ^{ @autoreleasepool {
686
-
687
- [loggerNode->logger logMessage:logMessage];
688
-
689
- }});
690
- }
691
-
692
- dispatch_group_wait(loggingGroup, DISPATCH_TIME_FOREVER);
693
- }
694
- else
695
- {
696
- // Execute each logger serialy, each within its own queue.
697
-
698
- for (DDLoggerNode *loggerNode in loggers)
699
- {
700
- // skip the loggers that shouldn't write this message based on the logLevel
701
-
702
- if (!(logMessage->logFlag & loggerNode.logLevel))
703
- continue;
704
-
705
- dispatch_sync(loggerNode->loggerQueue, ^{ @autoreleasepool {
706
-
707
- [loggerNode->logger logMessage:logMessage];
708
-
709
- }});
710
- }
711
- }
712
-
713
- // If our queue got too big, there may be blocked threads waiting to add log messages to the queue.
714
- // Since we've now dequeued an item from the log, we may need to unblock the next thread.
715
-
716
- // We are using a counting semaphore provided by GCD.
717
- // The semaphore is initialized with our LOG_MAX_QUEUE_SIZE value.
718
- // When a log message is queued this value is decremented.
719
- // When a log message is dequeued this value is incremented.
720
- // If the value ever drops below zero,
721
- // the queueing thread blocks and waits in FIFO order for us to signal it.
722
- //
723
- // A dispatch semaphore is an efficient implementation of a traditional counting semaphore.
724
- // Dispatch semaphores call down to the kernel only when the calling thread needs to be blocked.
725
- // If the calling semaphore does not need to block, no kernel call is made.
726
-
727
- dispatch_semaphore_signal(queueSemaphore);
728
- }
729
-
730
- + (void)lt_flush
731
- {
732
- // All log statements issued before the flush method was invoked have now been executed.
733
- //
734
- // Now we need to propogate the flush request to any loggers that implement the flush method.
735
- // This is designed for loggers that buffer IO.
736
-
737
- NSAssert(dispatch_get_specific(GlobalLoggingQueueIdentityKey),
738
- @"This method should only be run on the logging thread/queue");
739
-
740
- for (DDLoggerNode *loggerNode in loggers)
741
- {
742
- if ([loggerNode->logger respondsToSelector:@selector(flush)])
743
- {
744
- dispatch_group_async(loggingGroup, loggerNode->loggerQueue, ^{ @autoreleasepool {
745
-
746
- [loggerNode->logger flush];
747
-
748
- }});
749
- }
750
- }
751
-
752
- dispatch_group_wait(loggingGroup, DISPATCH_TIME_FOREVER);
753
- }
754
-
755
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
756
- #pragma mark Utilities
757
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
758
-
759
- NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy)
760
- {
761
- if (filePath == NULL) return nil;
762
-
763
- char *lastSlash = NULL;
764
- char *lastDot = NULL;
765
-
766
- char *p = (char *)filePath;
767
-
768
- while (*p != '\0')
769
- {
770
- if (*p == '/')
771
- lastSlash = p;
772
- else if (*p == '.')
773
- lastDot = p;
774
-
775
- p++;
776
- }
777
-
778
- char *subStr;
779
- NSUInteger subLen;
780
-
781
- if (lastSlash)
782
- {
783
- if (lastDot)
784
- {
785
- // lastSlash -> lastDot
786
- subStr = lastSlash + 1;
787
- subLen = lastDot - subStr;
788
- }
789
- else
790
- {
791
- // lastSlash -> endOfString
792
- subStr = lastSlash + 1;
793
- subLen = p - subStr;
794
- }
795
- }
796
- else
797
- {
798
- if (lastDot)
799
- {
800
- // startOfString -> lastDot
801
- subStr = (char *)filePath;
802
- subLen = lastDot - subStr;
803
- }
804
- else
805
- {
806
- // startOfString -> endOfString
807
- subStr = (char *)filePath;
808
- subLen = p - subStr;
809
- }
810
- }
811
-
812
- if (copy)
813
- {
814
- return [[NSString alloc] initWithBytes:subStr
815
- length:subLen
816
- encoding:NSUTF8StringEncoding];
817
- }
818
- else
819
- {
820
- // We can take advantage of the fact that __FILE__ is a string literal.
821
- // Specifically, we don't need to waste time copying the string.
822
- // We can just tell NSString to point to a range within the string literal.
823
-
824
- return [[NSString alloc] initWithBytesNoCopy:subStr
825
- length:subLen
826
- encoding:NSUTF8StringEncoding
827
- freeWhenDone:NO];
828
- }
829
- }
830
-
831
- @end
832
-
833
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
834
- #pragma mark -
835
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
836
-
837
- @implementation DDLoggerNode
838
-
839
- @synthesize logLevel;
840
-
841
- - (instancetype)initWithLogger:(id <DDLogger>)aLogger loggerQueue:(dispatch_queue_t)aLoggerQueue logLevel:(int)aLogLevel
842
- {
843
- if ((self = [super init]))
844
- {
845
- logger = aLogger;
846
-
847
- if (aLoggerQueue) {
848
- loggerQueue = aLoggerQueue;
849
- #if !OS_OBJECT_USE_OBJC
850
- dispatch_retain(loggerQueue);
851
- #endif
852
- }
853
- logLevel = aLogLevel;
854
- }
855
- return self;
856
- }
857
-
858
- + (DDLoggerNode *)nodeWithLogger:(id <DDLogger>)logger loggerQueue:(dispatch_queue_t)loggerQueue logLevel:(int)logLevel
859
- {
860
- return [[DDLoggerNode alloc] initWithLogger:logger loggerQueue:loggerQueue logLevel:logLevel];
861
- }
862
-
863
- - (void)dealloc
864
- {
865
- #if !OS_OBJECT_USE_OBJC
866
- if (loggerQueue) dispatch_release(loggerQueue);
867
- #endif
868
- }
869
-
870
- @end
871
-
872
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
873
- #pragma mark -
874
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
875
-
876
- @implementation DDLogMessage
877
-
878
- static char *dd_str_copy(const char *str)
879
- {
880
- if (str == NULL) return NULL;
881
-
882
- size_t length = strlen(str);
883
- char * result = malloc(length + 1);
884
- if (result == NULL) return NULL;
885
- strncpy(result, str, length);
886
- result[length] = 0;
887
-
888
- return result;
889
- }
890
-
891
- - (instancetype)initWithLogMsg:(NSString *)msg
892
- level:(int)level
893
- flag:(int)flag
894
- context:(int)context
895
- file:(const char *)aFile
896
- function:(const char *)aFunction
897
- line:(int)line
898
- tag:(id)aTag
899
- options:(DDLogMessageOptions)optionsMask
900
- {
901
- if ((self = [super init]))
902
- {
903
- logMsg = msg;
904
- logLevel = level;
905
- logFlag = flag;
906
- logContext = context;
907
- lineNumber = line;
908
- tag = aTag;
909
- options = optionsMask;
910
-
911
- if (options & DDLogMessageCopyFile)
912
- file = dd_str_copy(aFile);
913
- else
914
- file = (char *)aFile;
915
-
916
- if (options & DDLogMessageCopyFunction)
917
- function = dd_str_copy(aFunction);
918
- else
919
- function = (char *)aFunction;
920
-
921
- timestamp = [[NSDate alloc] init];
922
-
923
- machThreadID = pthread_mach_thread_np(pthread_self());
924
-
925
- // Try to get the current queue's label
926
-
927
- // a) Compiling against newer SDK's (iOS 7+/OS X 10.9+) where DISPATCH_CURRENT_QUEUE_LABEL is defined
928
- // on a (iOS 7.0+/OS X 10.9+) runtime version
929
- BOOL gotLabel = NO;
930
- #ifdef DISPATCH_CURRENT_QUEUE_LABEL
931
- if (
932
- #if TARGET_OS_IPHONE
933
- #ifndef NSFoundationVersionNumber_iOS_6_1
934
- #define NSFoundationVersionNumber_iOS_6_1 993.00
935
- #endif
936
- floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1 // iOS 7+ (> iOS 6.1)
937
- #else
938
- [NSTimer instancesRespondToSelector:@selector(tolerance)] // OS X 10.9+
939
- #endif
940
- ) {
941
- queueLabel = dd_str_copy(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL));
942
- gotLabel = YES;
943
- }
944
- #endif
945
-
946
- // b) Systems where dispatch_get_current_queue is not yet deprecated and won't crash (< iOS 6.0/OS X 10.9)
947
- // dispatch_get_current_queue(void); __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_6,__MAC_10_9,__IPHONE_4_0,__IPHONE_6_0)
948
- if (!gotLabel &&
949
- #if TARGET_OS_IPHONE
950
- #ifndef NSFoundationVersionNumber_iOS_6_0
951
- #define NSFoundationVersionNumber_iOS_6_0 993.00
952
- #endif
953
- floor(NSFoundationVersionNumber) < NSFoundationVersionNumber_iOS_6_0 // < iOS 6.0
954
- #else
955
- ![NSTimer instancesRespondToSelector:@selector(tolerance)] // < OS X 10.9
956
- #endif
957
- ) {
958
- #pragma clang diagnostic push
959
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
960
- dispatch_queue_t currentQueue = dispatch_get_current_queue();
961
- #pragma clang diagnostic pop
962
-
963
- queueLabel = dd_str_copy(dispatch_queue_get_label(currentQueue));
964
- gotLabel = YES;
965
- }
966
-
967
- // c) Give up
968
- if (!gotLabel) {
969
- queueLabel = dd_str_copy(""); // iOS 6.x only
970
- }
971
-
972
- threadName = [[NSThread currentThread] name];
973
- }
974
- return self;
975
- }
976
-
977
- - (NSString *)threadID
978
- {
979
- return [[NSString alloc] initWithFormat:@"%x", machThreadID];
980
- }
981
-
982
- - (NSString *)fileName
983
- {
984
- return DDExtractFileNameWithoutExtension(file, NO);
985
- }
986
-
987
- - (NSString *)methodName
988
- {
989
- if (function == NULL)
990
- return nil;
991
- else
992
- return [[NSString alloc] initWithUTF8String:function];
993
- }
994
-
995
- - (void)dealloc
996
- {
997
- if (file && (options & DDLogMessageCopyFile))
998
- free(file);
999
-
1000
- if (function && (options & DDLogMessageCopyFunction))
1001
- free(function);
1002
-
1003
- if (queueLabel)
1004
- free(queueLabel);
1005
- }
1006
-
1007
-
1008
- - (id)copyWithZone:(NSZone *)zone {
1009
- DDLogMessage *newMessage = [[DDLogMessage alloc] init];
1010
-
1011
- newMessage->logLevel = self->logLevel;
1012
- newMessage->logFlag = self->logFlag;
1013
- newMessage->logContext = self->logContext;
1014
- newMessage->logMsg = self->logMsg;
1015
- newMessage->timestamp = self->timestamp;
1016
-
1017
- if (self->options & DDLogMessageCopyFile) {
1018
- newMessage->file = dd_str_copy(self->file);
1019
- newMessage->function = dd_str_copy(self->function);
1020
- } else {
1021
- newMessage->file = self->file;
1022
- newMessage->function = self->function;
1023
- }
1024
-
1025
- newMessage->lineNumber = self->lineNumber;
1026
-
1027
- newMessage->machThreadID = self->machThreadID;
1028
- newMessage->queueLabel = dd_str_copy(self->queueLabel);
1029
- newMessage->threadName = self->threadName;
1030
- newMessage->tag = self->tag;
1031
- newMessage->options = self->options;
1032
-
1033
- return newMessage;
1034
- }
1035
-
1036
- @end
1037
-
1038
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1039
- #pragma mark -
1040
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1041
-
1042
- @implementation DDAbstractLogger
1043
-
1044
- - (id)init
1045
- {
1046
- if ((self = [super init]))
1047
- {
1048
- const char *loggerQueueName = NULL;
1049
- if ([self respondsToSelector:@selector(loggerName)])
1050
- {
1051
- loggerQueueName = [[self loggerName] UTF8String];
1052
- }
1053
-
1054
- loggerQueue = dispatch_queue_create(loggerQueueName, NULL);
1055
-
1056
- // We're going to use dispatch_queue_set_specific() to "mark" our loggerQueue.
1057
- // Later we can use dispatch_get_specific() to determine if we're executing on our loggerQueue.
1058
- // The documentation states:
1059
- //
1060
- // > Keys are only compared as pointers and are never dereferenced.
1061
- // > Thus, you can use a pointer to a static variable for a specific subsystem or
1062
- // > any other value that allows you to identify the value uniquely.
1063
- // > Specifying a pointer to a string constant is not recommended.
1064
- //
1065
- // So we're going to use the very convenient key of "self",
1066
- // which also works when multiple logger classes extend this class, as each will have a different "self" key.
1067
- //
1068
- // This is used primarily for thread-safety assertions (via the isOnInternalLoggerQueue method below).
1069
-
1070
- void *key = (__bridge void *)self;
1071
- void *nonNullValue = (__bridge void *)self;
1072
-
1073
- dispatch_queue_set_specific(loggerQueue, key, nonNullValue, NULL);
1074
- }
1075
- return self;
1076
- }
1077
-
1078
- - (void)dealloc
1079
- {
1080
- #if !OS_OBJECT_USE_OBJC
1081
- if (loggerQueue) dispatch_release(loggerQueue);
1082
- #endif
1083
- }
1084
-
1085
- - (void)logMessage:(DDLogMessage *)logMessage
1086
- {
1087
- // Override me
1088
- }
1089
-
1090
- - (id <DDLogFormatter>)logFormatter
1091
- {
1092
- // This method must be thread safe and intuitive.
1093
- // Therefore if somebody executes the following code:
1094
- //
1095
- // [logger setLogFormatter:myFormatter];
1096
- // formatter = [logger logFormatter];
1097
- //
1098
- // They would expect formatter to equal myFormatter.
1099
- // This functionality must be ensured by the getter and setter method.
1100
- //
1101
- // The thread safety must not come at a cost to the performance of the logMessage method.
1102
- // This method is likely called sporadically, while the logMessage method is called repeatedly.
1103
- // This means, the implementation of this method:
1104
- // - Must NOT require the logMessage method to acquire a lock.
1105
- // - Must NOT require the logMessage method to access an atomic property (also a lock of sorts).
1106
- //
1107
- // Thread safety is ensured by executing access to the formatter variable on the loggerQueue.
1108
- // This is the same queue that the logMessage method operates on.
1109
- //
1110
- // Note: The last time I benchmarked the performance of direct access vs atomic property access,
1111
- // direct access was over twice as fast on the desktop and over 6 times as fast on the iPhone.
1112
- //
1113
- // Furthermore, consider the following code:
1114
- //
1115
- // DDLogVerbose(@"log msg 1");
1116
- // DDLogVerbose(@"log msg 2");
1117
- // [logger setFormatter:myFormatter];
1118
- // DDLogVerbose(@"log msg 3");
1119
- //
1120
- // Our intuitive requirement means that the new formatter will only apply to the 3rd log message.
1121
- // This must remain true even when using asynchronous logging.
1122
- // We must keep in mind the various queue's that are in play here:
1123
- //
1124
- // loggerQueue : Our own private internal queue that the logMessage method runs on.
1125
- // Operations are added to this queue from the global loggingQueue.
1126
- //
1127
- // globalLoggingQueue : The queue that all log messages go through before they arrive in our loggerQueue.
1128
- //
1129
- // All log statements go through the serial gloabalLoggingQueue before they arrive at our loggerQueue.
1130
- // Thus this method also goes through the serial globalLoggingQueue to ensure intuitive operation.
1131
-
1132
- // IMPORTANT NOTE:
1133
- //
1134
- // Methods within the DDLogger implementation MUST access the formatter ivar directly.
1135
- // This method is designed explicitly for external access.
1136
- //
1137
- // Using "self." syntax to go through this method will cause immediate deadlock.
1138
- // This is the intended result. Fix it by accessing the ivar directly.
1139
- // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
1140
-
1141
- NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
1142
- NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
1143
-
1144
- dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
1145
-
1146
- __block id <DDLogFormatter> result;
1147
-
1148
- dispatch_sync(globalLoggingQueue, ^{
1149
- dispatch_sync(loggerQueue, ^{
1150
- result = formatter;
1151
- });
1152
- });
1153
-
1154
- return result;
1155
- }
1156
-
1157
- - (void)setLogFormatter:(id <DDLogFormatter>)logFormatter
1158
- {
1159
- // The design of this method is documented extensively in the logFormatter message (above in code).
1160
-
1161
- NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
1162
- NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
1163
-
1164
- dispatch_block_t block = ^{ @autoreleasepool {
1165
-
1166
- if (formatter != logFormatter)
1167
- {
1168
- if ([formatter respondsToSelector:@selector(willRemoveFromLogger:)]) {
1169
- [formatter willRemoveFromLogger:self];
1170
- }
1171
-
1172
- formatter = logFormatter;
1173
-
1174
- if ([formatter respondsToSelector:@selector(didAddToLogger:)]) {
1175
- [formatter didAddToLogger:self];
1176
- }
1177
- }
1178
- }};
1179
-
1180
- dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
1181
-
1182
- dispatch_async(globalLoggingQueue, ^{
1183
- dispatch_async(loggerQueue, block);
1184
- });
1185
- }
1186
-
1187
- - (dispatch_queue_t)loggerQueue
1188
- {
1189
- return loggerQueue;
1190
- }
1191
-
1192
- - (NSString *)loggerName
1193
- {
1194
- return NSStringFromClass([self class]);
1195
- }
1196
-
1197
- - (BOOL)isOnGlobalLoggingQueue
1198
- {
1199
- return (dispatch_get_specific(GlobalLoggingQueueIdentityKey) != NULL);
1200
- }
1201
-
1202
- - (BOOL)isOnInternalLoggerQueue
1203
- {
1204
- void *key = (__bridge void *)self;
1205
- return (dispatch_get_specific(key) != NULL);
1206
- }
1207
-
1208
- @end