motion-yapper 0.0.1

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