motion-yapper 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -2
- data/.travis.yml +2 -0
- data/Gemfile +1 -0
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/lib/motion-yapper.rb +1 -0
- data/lib/yapper.rb +3 -5
- data/lib/yapper/config.rb +2 -0
- data/lib/yapper/db.rb +105 -40
- data/lib/yapper/document.rb +7 -4
- data/lib/yapper/document/callbacks.rb +0 -7
- data/lib/yapper/document/{persistance.rb → persistence.rb} +27 -21
- data/lib/yapper/document/relation.rb +29 -22
- data/lib/yapper/document/selection.rb +122 -54
- data/lib/yapper/extensions.rb +12 -24
- data/lib/yapper/settings.rb +43 -0
- data/lib/yapper/timestamps.rb +2 -0
- data/lib/yapper/version.rb +1 -1
- data/{yapper.gemspec → motion-yapper.gemspec} +0 -0
- data/spec/integration/{where_spec.rb → criteria_spec.rb} +78 -10
- data/spec/integration/db_spec.rb +70 -0
- data/spec/integration/defaults_spec.rb +37 -0
- data/spec/integration/extensions_spec.rb +14 -0
- data/spec/integration/{persistance_spec.rb → persistence_spec.rb} +0 -0
- data/spec/integration/relation_spec.rb +4 -4
- data/vendor/Podfile.lock +9 -11
- data/vendor/Pods/.build/libPods-CocoaLumberjack.a +0 -0
- data/vendor/Pods/.build/libPods-NSData+MD5Digest.a +0 -0
- data/vendor/Pods/.build/libPods-YapDatabase.a +0 -0
- data/vendor/Pods/.build/libPods.a +0 -0
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDASLLogger.h +4 -4
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDAbstractDatabaseLogger.h +14 -14
- data/vendor/Pods/{CocoaLumberjack/Lumberjack/Extensions/ContextFilterLogFormatter.h → BuildHeaders/CocoaLumberjack/DDContextFilterLogFormatter.h} +6 -8
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/{DispatchQueueLogFormatter.h → DDDispatchQueueLogFormatter.h} +18 -6
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDFileLogger.h +67 -32
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDLog+LOGV.h +99 -0
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDLog.h +98 -65
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDMultiFormatter.h +30 -0
- data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDTTYLogger.h +39 -25
- data/vendor/Pods/BuildHeaders/YapDatabase/NSDictionary+YapDatabase.h +8 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapCache.h +1 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapCollectionKey.h +3 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabase.h +4 -4
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseConnection.h +21 -19
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseDefaults.h +1 -1
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionPrivate.h +35 -31
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredView.h +8 -35
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewPrivate.h +0 -2
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewTransaction.h +17 -17
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewTypes.h +32 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchPrivate.h +8 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabasePrivate.h +43 -21
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationship.h +35 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipConnection.h +29 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipEdge.h +163 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipEdgePrivate.h +79 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipNode.h +99 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipOptions.h +59 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipPrivate.h +125 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipTransaction.h +384 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndex.h +49 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexPrivate.h +10 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexSetupPrivate.h +18 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseTransaction.h +131 -21
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseView.h +48 -107
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewChange.h +2 -2
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewConnection.h +1 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewMappings.h +17 -0
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewOptions.h +10 -3
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPrivate.h +18 -1
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewTransaction.h +75 -24
- data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewTypes.h +99 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDASLLogger.h +4 -4
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDASLLogger.m +51 -50
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDAbstractDatabaseLogger.h +14 -14
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDAbstractDatabaseLogger.m +546 -546
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDFileLogger.h +67 -32
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDFileLogger.m +1093 -907
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog+LOGV.h +99 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog.h +98 -65
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog.m +873 -748
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDTTYLogger.h +39 -25
- data/vendor/Pods/CocoaLumberjack/Lumberjack/DDTTYLogger.m +1284 -1243
- data/vendor/Pods/{BuildHeaders/CocoaLumberjack/ContextFilterLogFormatter.h → CocoaLumberjack/Lumberjack/Extensions/DDContextFilterLogFormatter.h} +6 -8
- data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/{ContextFilterLogFormatter.m → DDContextFilterLogFormatter.m} +70 -70
- data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/{DispatchQueueLogFormatter.h → DDDispatchQueueLogFormatter.h} +18 -6
- data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDDispatchQueueLogFormatter.m +253 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDMultiFormatter.h +30 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDMultiFormatter.m +127 -0
- data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/README.txt +1 -1
- data/vendor/Pods/CocoaLumberjack/README.markdown +52 -15
- data/vendor/Pods/Headers/CocoaLumberjack/DDASLLogger.h +4 -4
- data/vendor/Pods/Headers/CocoaLumberjack/DDAbstractDatabaseLogger.h +14 -14
- data/vendor/Pods/Headers/CocoaLumberjack/{ContextFilterLogFormatter.h → DDContextFilterLogFormatter.h} +6 -8
- data/vendor/Pods/Headers/CocoaLumberjack/{DispatchQueueLogFormatter.h → DDDispatchQueueLogFormatter.h} +18 -6
- data/vendor/Pods/Headers/CocoaLumberjack/DDFileLogger.h +67 -32
- data/vendor/Pods/Headers/CocoaLumberjack/DDLog+LOGV.h +99 -0
- data/vendor/Pods/Headers/CocoaLumberjack/DDLog.h +98 -65
- data/vendor/Pods/Headers/CocoaLumberjack/DDMultiFormatter.h +30 -0
- data/vendor/Pods/Headers/CocoaLumberjack/DDTTYLogger.h +39 -25
- data/vendor/Pods/Headers/YapDatabase/YapCollectionKey.h +3 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabase.h +4 -4
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseConnection.h +21 -19
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredView.h +8 -35
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewTransaction.h +17 -17
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewTypes.h +32 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationship.h +35 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipConnection.h +29 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipEdge.h +163 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipNode.h +99 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipOptions.h +59 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipTransaction.h +384 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndex.h +49 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseTransaction.h +131 -21
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseView.h +48 -107
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewChange.h +2 -2
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewConnection.h +1 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewMappings.h +17 -0
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewOptions.h +10 -3
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewTransaction.h +75 -24
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewTypes.h +99 -0
- data/vendor/Pods/Headers/____Pods-CocoaLumberjack-prefix.h +2 -0
- data/vendor/Pods/Headers/____Pods-environment.h +15 -15
- data/vendor/Pods/Manifest.lock +9 -11
- data/vendor/Pods/Pods-CocoaLumberjack-Private.xcconfig +1 -1
- data/vendor/Pods/Pods-CocoaLumberjack-prefix.pch +2 -0
- data/vendor/Pods/Pods-NSData+MD5Digest-Private.xcconfig +1 -1
- data/vendor/Pods/Pods-YapDatabase-Private.xcconfig +1 -1
- data/vendor/Pods/{Pods-Acknowledgements.markdown → Pods-acknowledgements.markdown} +0 -37
- data/vendor/Pods/{Pods-Acknowledgements.plist → Pods-acknowledgements.plist} +0 -45
- data/vendor/Pods/Pods-environment.h +15 -15
- data/vendor/Pods/Pods.xcconfig +3 -3
- data/vendor/Pods/Pods.xcodeproj/project.pbxproj +2426 -3155
- data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/Pods-CocoaLumberjack.xcscheme +59 -0
- data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/Pods-NSData+MD5Digest.xcscheme +59 -0
- data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/Pods-YapDatabase.xcscheme +59 -0
- data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/Pods.xcscheme +59 -0
- data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/xcschememanagement.plist +31 -0
- data/vendor/Pods/YapDatabase/README.md +3 -1
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/Internal/YapDatabaseFilteredViewPrivate.h +0 -2
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.h +8 -35
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.m +25 -41
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.h +17 -17
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.m +403 -134
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.h +32 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/Internal/YapDatabaseFullTextSearchPrivate.h +8 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.m +8 -8
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.m +113 -62
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/Internal/YapDatabaseExtensionPrivate.h +35 -31
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.m +25 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.m +1 -1
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.m +25 -1
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipEdgePrivate.h +79 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipPrivate.h +125 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationship.h +35 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationship.m +129 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.h +29 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.m +802 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.h +163 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.m +408 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipNode.h +99 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.h +59 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.m +29 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.h +384 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.m +5254 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexPrivate.h +10 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexSetupPrivate.h +18 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.h +49 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.m +12 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.m +9 -8
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.m +62 -1
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m +148 -45
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h +18 -1
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.h +2 -2
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.m +15 -9
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.h +17 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.m +211 -64
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.h +48 -107
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.m +10 -7
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.h +1 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.m +13 -22
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.h +10 -3
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h +75 -24
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m +725 -244
- data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTypes.h +99 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/NSDictionary+YapDatabase.h +8 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/NSDictionary+YapDatabase.m +19 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapCache.h +1 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapCache.m +12 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseDefaults.h +1 -1
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseDefaults.m +3 -3
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabasePrivate.h +43 -21
- data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapNull.m +4 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.h +3 -0
- data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.m +5 -0
- data/vendor/Pods/YapDatabase/YapDatabase/YapDatabase.h +4 -4
- data/vendor/Pods/YapDatabase/YapDatabase/YapDatabase.m +84 -93
- data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.h +21 -19
- data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.m +381 -209
- data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.h +131 -21
- data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.m +587 -267
- data/vendor/Pods/{Pods.bridgesupport → build-iPhoneSimulator/Pods.bridgesupport} +633 -2557
- data/vendor/Pods/build-iPhoneSimulator/libPods.a +0 -0
- data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.bridgesupport +2 -1
- data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.h +2 -1
- data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.m +4 -2
- metadata +80 -108
- data/Gemfile.lock +0 -63
- data/lib/yapper/attachment.rb +0 -48
- data/lib/yapper/document/attachment.rb +0 -26
- data/lib/yapper/sync.rb +0 -134
- data/lib/yapper/sync/data.rb +0 -12
- data/lib/yapper/sync/event.rb +0 -194
- data/lib/yapper/sync/queue.rb +0 -164
- data/spec/integration/all_spec.rb +0 -40
- data/spec/integration/sync_spec.rb +0 -42
- data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPClient.h +0 -641
- data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPClient.m +0 -1396
- data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.h +0 -133
- data/vendor/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.m +0 -327
- data/vendor/Pods/AFNetworking/AFNetworking/AFImageRequestOperation.h +0 -113
- data/vendor/Pods/AFNetworking/AFNetworking/AFImageRequestOperation.m +0 -321
- data/vendor/Pods/AFNetworking/AFNetworking/AFJSONRequestOperation.h +0 -71
- data/vendor/Pods/AFNetworking/AFNetworking/AFJSONRequestOperation.m +0 -150
- data/vendor/Pods/AFNetworking/AFNetworking/AFNetworkActivityIndicatorManager.h +0 -75
- data/vendor/Pods/AFNetworking/AFNetworking/AFNetworkActivityIndicatorManager.m +0 -157
- data/vendor/Pods/AFNetworking/AFNetworking/AFNetworking.h +0 -43
- data/vendor/Pods/AFNetworking/AFNetworking/AFPropertyListRequestOperation.h +0 -68
- data/vendor/Pods/AFNetworking/AFNetworking/AFPropertyListRequestOperation.m +0 -143
- data/vendor/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.h +0 -370
- data/vendor/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.m +0 -848
- data/vendor/Pods/AFNetworking/AFNetworking/AFXMLRequestOperation.h +0 -89
- data/vendor/Pods/AFNetworking/AFNetworking/AFXMLRequestOperation.m +0 -167
- data/vendor/Pods/AFNetworking/AFNetworking/UIImageView+AFNetworking.h +0 -78
- data/vendor/Pods/AFNetworking/AFNetworking/UIImageView+AFNetworking.m +0 -191
- data/vendor/Pods/AFNetworking/LICENSE +0 -19
- data/vendor/Pods/AFNetworking/README.md +0 -208
- data/vendor/Pods/BuildHeaders/AFNetworking/AFHTTPClient.h +0 -641
- data/vendor/Pods/BuildHeaders/AFNetworking/AFHTTPRequestOperation.h +0 -133
- data/vendor/Pods/BuildHeaders/AFNetworking/AFImageRequestOperation.h +0 -113
- data/vendor/Pods/BuildHeaders/AFNetworking/AFJSONRequestOperation.h +0 -71
- data/vendor/Pods/BuildHeaders/AFNetworking/AFNetworkActivityIndicatorManager.h +0 -75
- data/vendor/Pods/BuildHeaders/AFNetworking/AFNetworking.h +0 -43
- data/vendor/Pods/BuildHeaders/AFNetworking/AFPropertyListRequestOperation.h +0 -68
- data/vendor/Pods/BuildHeaders/AFNetworking/AFURLConnectionOperation.h +0 -370
- data/vendor/Pods/BuildHeaders/AFNetworking/AFXMLRequestOperation.h +0 -89
- data/vendor/Pods/BuildHeaders/AFNetworking/UIImageView+AFNetworking.h +0 -78
- data/vendor/Pods/BuildHeaders/Reachability/Reachability.h +0 -109
- data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DispatchQueueLogFormatter.m +0 -251
- data/vendor/Pods/Headers/AFNetworking/AFHTTPClient.h +0 -641
- data/vendor/Pods/Headers/AFNetworking/AFHTTPRequestOperation.h +0 -133
- data/vendor/Pods/Headers/AFNetworking/AFImageRequestOperation.h +0 -113
- data/vendor/Pods/Headers/AFNetworking/AFJSONRequestOperation.h +0 -71
- data/vendor/Pods/Headers/AFNetworking/AFNetworkActivityIndicatorManager.h +0 -75
- data/vendor/Pods/Headers/AFNetworking/AFNetworking.h +0 -43
- data/vendor/Pods/Headers/AFNetworking/AFPropertyListRequestOperation.h +0 -68
- data/vendor/Pods/Headers/AFNetworking/AFURLConnectionOperation.h +0 -370
- data/vendor/Pods/Headers/AFNetworking/AFXMLRequestOperation.h +0 -89
- data/vendor/Pods/Headers/AFNetworking/UIImageView+AFNetworking.h +0 -78
- data/vendor/Pods/Headers/Reachability/Reachability.h +0 -109
- data/vendor/Pods/Headers/YapDatabase/YapCache.h +0 -90
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseConnectionState.h +0 -29
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseDefaults.h +0 -37
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionPrivate.h +0 -440
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewPrivate.h +0 -19
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchPrivate.h +0 -69
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseLogging.h +0 -158
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseManager.h +0 -17
- data/vendor/Pods/Headers/YapDatabase/YapDatabasePrivate.h +0 -424
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexPrivate.h +0 -73
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseStatement.h +0 -13
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseString.h +0 -121
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewChangePrivate.h +0 -94
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewMappingsPrivate.h +0 -72
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewPage.h +0 -36
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewPageMetadata.h +0 -27
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewPrivate.h +0 -153
- data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h +0 -17
- data/vendor/Pods/Headers/YapDatabase/YapMemoryTable.h +0 -74
- data/vendor/Pods/Headers/YapDatabase/YapNull.h +0 -17
- data/vendor/Pods/Headers/YapDatabase/YapTouch.h +0 -15
- data/vendor/Pods/Headers/____Pods-AFNetworking-prefix.h +0 -17
- data/vendor/Pods/Headers/____Pods-Reachability-prefix.h +0 -5
- data/vendor/Pods/Pods-AFNetworking-Private.xcconfig +0 -5
- data/vendor/Pods/Pods-AFNetworking-dummy.m +0 -5
- data/vendor/Pods/Pods-AFNetworking-prefix.pch +0 -17
- data/vendor/Pods/Pods-AFNetworking.xcconfig +0 -1
- data/vendor/Pods/Pods-Reachability-Private.xcconfig +0 -5
- data/vendor/Pods/Pods-Reachability-dummy.m +0 -5
- data/vendor/Pods/Pods-Reachability-prefix.pch +0 -5
- data/vendor/Pods/Pods-Reachability.xcconfig +0 -1
- data/vendor/Pods/Reachability/LICENCE.txt +0 -24
- data/vendor/Pods/Reachability/README.md +0 -65
- data/vendor/Pods/Reachability/Reachability.h +0 -109
- data/vendor/Pods/Reachability/Reachability.m +0 -527
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
//
|
|
2
|
+
// DDLog+LOGV.h
|
|
3
|
+
// Lumberjack
|
|
4
|
+
//
|
|
5
|
+
// Created by Mike Pontillo on 11/20/12.
|
|
6
|
+
//
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#ifndef Lumberjack_DDLog_LOGV_h
|
|
10
|
+
#define Lumberjack_DDLog_LOGV_h
|
|
11
|
+
|
|
12
|
+
#import "DDLog.h"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
#define LOGV_MACRO(isAsynchronous, lvl, flg, ctx, atag, fnct, frmt, avalist) \
|
|
16
|
+
[DDLog log:isAsynchronous \
|
|
17
|
+
level:lvl \
|
|
18
|
+
flag:flg \
|
|
19
|
+
context:ctx \
|
|
20
|
+
file:__FILE__ \
|
|
21
|
+
function:fnct \
|
|
22
|
+
line:__LINE__ \
|
|
23
|
+
tag:atag \
|
|
24
|
+
format:frmt \
|
|
25
|
+
args:avalist]
|
|
26
|
+
|
|
27
|
+
#define LOGV_OBJC_MACRO(async, lvl, flg, ctx, frmt, avalist) \
|
|
28
|
+
LOGV_MACRO(async, lvl, flg, ctx, nil, sel_getName(_cmd), frmt, avalist)
|
|
29
|
+
|
|
30
|
+
#define LOGV_C_MACRO(async, lvl, flg, ctx, frmt, avalist) \
|
|
31
|
+
LOGV_MACRO(async, lvl, flg, ctx, nil, __FUNCTION__, frmt, avalist)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
#define SYNC_LOGV_OBJC_MACRO(lvl, flg, ctx, frmt, avalist) \
|
|
36
|
+
LOGV_OBJC_MACRO( NO, lvl, flg, ctx, frmt, avalist)
|
|
37
|
+
|
|
38
|
+
#define ASYNC_LOGV_OBJC_MACRO(lvl, flg, ctx, frmt, avalist) \
|
|
39
|
+
LOGV_OBJC_MACRO(YES, lvl, flg, ctx, frmt, avalist)
|
|
40
|
+
|
|
41
|
+
#define SYNC_LOGV_C_MACRO(lvl, flg, ctx, frmt, avalist) \
|
|
42
|
+
LOGV_C_MACRO( NO, lvl, flg, ctx, frmt, avalist)
|
|
43
|
+
|
|
44
|
+
#define ASYNC_LOGV_C_MACRO(lvl, flg, ctx, frmt, avalist) \
|
|
45
|
+
LOGV_C_MACRO(YES, lvl, flg, ctx, frmt, avalist)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
#define LOGV_MAYBE(async, lvl, flg, ctx, fnct, frmt, avalist) \
|
|
50
|
+
do { if(lvl & flg) LOGV_MACRO(async, lvl, flg, ctx, nil, fnct, frmt, avalist); } while(0)
|
|
51
|
+
|
|
52
|
+
#define LOGV_OBJC_MAYBE(async, lvl, flg, ctx, frmt, avalist) \
|
|
53
|
+
LOGV_MAYBE(async, lvl, flg, ctx, sel_getName(_cmd), frmt, avalist)
|
|
54
|
+
|
|
55
|
+
#define LOGV_C_MAYBE(async, lvl, flg, ctx, frmt, avalist) \
|
|
56
|
+
LOGV_MAYBE(async, lvl, flg, ctx, __FUNCTION__, frmt, avalist)
|
|
57
|
+
|
|
58
|
+
#define SYNC_LOGV_OBJC_MAYBE(lvl, flg, ctx, frmt, avalist) \
|
|
59
|
+
LOGV_OBJC_MAYBE( NO, lvl, flg, ctx, frmt, avalist)
|
|
60
|
+
|
|
61
|
+
#define ASYNC_LOGV_OBJC_MAYBE(lvl, flg, ctx, frmt, avalist) \
|
|
62
|
+
LOGV_OBJC_MAYBE(YES, lvl, flg, ctx, frmt, avalist)
|
|
63
|
+
|
|
64
|
+
#define SYNC_LOGV_C_MAYBE(lvl, flg, ctx, frmt, avalist) \
|
|
65
|
+
LOGV_C_MAYBE( NO, lvl, flg, ctx, frmt, avalist)
|
|
66
|
+
|
|
67
|
+
#define ASYNC_LOGV_C_MAYBE(lvl, flg, ctx, frmt, avalist) \
|
|
68
|
+
LOGV_C_MAYBE(YES, lvl, flg, ctx, frmt, avalist)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
#define LOGV_OBJC_TAG_MACRO(async, lvl, flg, ctx, tag, frmt, avalist) \
|
|
73
|
+
LOGV_MACRO(async, lvl, flg, ctx, tag, sel_getName(_cmd), frmt, avalist)
|
|
74
|
+
|
|
75
|
+
#define LOGV_C_TAG_MACRO(async, lvl, flg, ctx, tag, frmt, avalist) \
|
|
76
|
+
LOGV_MACRO(async, lvl, flg, ctx, tag, __FUNCTION__, frmt, avalist)
|
|
77
|
+
|
|
78
|
+
#define LOGV_TAG_MAYBE(async, lvl, flg, ctx, tag, fnct, frmt, avalist) \
|
|
79
|
+
do { if(lvl & flg) LOGV_MACRO(async, lvl, flg, ctx, tag, fnct, frmt, avalist); } while(0)
|
|
80
|
+
|
|
81
|
+
#define LOGV_OBJC_TAG_MAYBE(async, lvl, flg, ctx, tag, frmt, avalist) \
|
|
82
|
+
LOGV_TAG_MAYBE(async, lvl, flg, ctx, tag, sel_getName(_cmd), frmt, avalist)
|
|
83
|
+
|
|
84
|
+
#define LOGV_C_TAG_MAYBE(async, lvl, flg, ctx, tag, frmt, avalist) \
|
|
85
|
+
LOGV_TAG_MAYBE(async, lvl, flg, ctx, tag, __FUNCTION__, frmt, avalist)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
#define DDLogvError(frmt, avalist) LOGV_OBJC_MAYBE(LOG_ASYNC_ERROR, ddLogLevel, LOG_FLAG_ERROR, 0, frmt, avalist)
|
|
90
|
+
#define DDLogvWarn(frmt, avalist) LOGV_OBJC_MAYBE(LOG_ASYNC_WARN, ddLogLevel, LOG_FLAG_WARN, 0, frmt, avalist)
|
|
91
|
+
#define DDLogvInfo(frmt, avalist) LOGV_OBJC_MAYBE(LOG_ASYNC_INFO, ddLogLevel, LOG_FLAG_INFO, 0, frmt, avalist)
|
|
92
|
+
#define DDLogvVerbose(frmt, avalist) LOGV_OBJC_MAYBE(LOG_ASYNC_VERBOSE, ddLogLevel, LOG_FLAG_VERBOSE, 0, frmt, avalist)
|
|
93
|
+
|
|
94
|
+
#define DDLogvCError(frmt, avalist) LOGV_C_MAYBE(LOG_ASYNC_ERROR, ddLogLevel, LOG_FLAG_ERROR, 0, frmt, avalist)
|
|
95
|
+
#define DDLogvCWarn(frmt, avalist) LOGV_C_MAYBE(LOG_ASYNC_WARN, ddLogLevel, LOG_FLAG_WARN, 0, frmt, avalist)
|
|
96
|
+
#define DDLogvCInfo(frmt, avalist) LOGV_C_MAYBE(LOG_ASYNC_INFO, ddLogLevel, LOG_FLAG_INFO, 0, frmt, avalist)
|
|
97
|
+
#define DDLogvCVerbose(frmt, avalist) LOGV_C_MAYBE(LOG_ASYNC_VERBOSE, ddLogLevel, LOG_FLAG_VERBOSE, 0, frmt, avalist)
|
|
98
|
+
|
|
99
|
+
#endif
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* Welcome to Cocoa Lumberjack!
|
|
5
5
|
*
|
|
6
6
|
* The project page has a wealth of documentation if you have any questions.
|
|
7
|
-
* https://github.com/
|
|
7
|
+
* https://github.com/CocoaLumberjack/CocoaLumberjack
|
|
8
8
|
*
|
|
9
9
|
* If you're new to the project you may wish to read the "Getting Started" wiki.
|
|
10
|
-
* https://github.com/
|
|
10
|
+
* https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted
|
|
11
11
|
*
|
|
12
12
|
* Otherwise, here is a quick refresher.
|
|
13
13
|
* There are three steps to using the macros:
|
|
@@ -23,6 +23,18 @@
|
|
|
23
23
|
* // Log levels: off, error, warn, info, verbose
|
|
24
24
|
* static const int ddLogLevel = LOG_LEVEL_VERBOSE;
|
|
25
25
|
*
|
|
26
|
+
* Step 2 [3rd party frameworks]:
|
|
27
|
+
*
|
|
28
|
+
* Define your LOG_LEVEL_DEF to a different variable/function than ddLogLevel:
|
|
29
|
+
*
|
|
30
|
+
* // #undef LOG_LEVEL_DEF // Undefine first only if needed
|
|
31
|
+
* #define LOG_LEVEL_DEF myLibLogLevel
|
|
32
|
+
*
|
|
33
|
+
* Define your logging level in your implementation file:
|
|
34
|
+
*
|
|
35
|
+
* // Log levels: off, error, warn, info, verbose
|
|
36
|
+
* static const int myLibLogLevel = LOG_LEVEL_VERBOSE;
|
|
37
|
+
*
|
|
26
38
|
* Step 3:
|
|
27
39
|
* Replace your NSLog statements with DDLog statements according to the severity of the message.
|
|
28
40
|
*
|
|
@@ -32,6 +44,9 @@
|
|
|
32
44
|
* This means you can pass it multiple variables just like NSLog.
|
|
33
45
|
**/
|
|
34
46
|
|
|
47
|
+
#ifndef LOG_LEVEL_DEF
|
|
48
|
+
#define LOG_LEVEL_DEF ddLogLevel
|
|
49
|
+
#endif
|
|
35
50
|
|
|
36
51
|
@class DDLogMessage;
|
|
37
52
|
|
|
@@ -85,6 +100,8 @@
|
|
|
85
100
|
*
|
|
86
101
|
* if (logFlagForThisLogMsg & ddLogLevel) { execute log message }
|
|
87
102
|
*
|
|
103
|
+
* When LOG_LEVEL_DEF is defined as ddLogLevel.
|
|
104
|
+
*
|
|
88
105
|
* As shown further below, Lumberjack actually uses a bitmask as opposed to primitive log levels.
|
|
89
106
|
* This allows for a great amount of flexibility and some pretty advanced fine grained logging techniques.
|
|
90
107
|
*
|
|
@@ -151,11 +168,11 @@
|
|
|
151
168
|
*
|
|
152
169
|
* More advanced users may choose to completely customize the levels (and level names) to suite their needs.
|
|
153
170
|
* For more information on this see the "Custom Log Levels" page:
|
|
154
|
-
* https://github.com/
|
|
171
|
+
* https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomLogLevels
|
|
155
172
|
*
|
|
156
173
|
* Advanced users may also notice that we're using a bitmask.
|
|
157
174
|
* This is to allow for custom fine grained logging:
|
|
158
|
-
* https://github.com/
|
|
175
|
+
* https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/FineGrainedLogging
|
|
159
176
|
*
|
|
160
177
|
* -- Flags --
|
|
161
178
|
*
|
|
@@ -166,6 +183,8 @@
|
|
|
166
183
|
*
|
|
167
184
|
* static const int ddLogLevel = LOG_FLAG_ERROR | LOG_FLAG_INFO;
|
|
168
185
|
*
|
|
186
|
+
* When LOG_LEVEL_DEF is defined as ddLogLevel.
|
|
187
|
+
*
|
|
169
188
|
* Flags may also be consulted when writing custom log formatters,
|
|
170
189
|
* as the DDLogMessage class captures the individual flag that caused the log message to fire.
|
|
171
190
|
*
|
|
@@ -202,41 +221,47 @@
|
|
|
202
221
|
* Instead, create your own MyLogging.h or ApplicationNameLogging.h or CompanyLogging.h
|
|
203
222
|
*
|
|
204
223
|
* For an example of customizing your logging experience, see the "Custom Log Levels" page:
|
|
205
|
-
* https://github.com/
|
|
224
|
+
* https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomLogLevels
|
|
206
225
|
**/
|
|
207
226
|
|
|
208
|
-
#define LOG_FLAG_ERROR (1 << 0) // 0...
|
|
209
|
-
#define LOG_FLAG_WARN (1 << 1) // 0...
|
|
210
|
-
#define LOG_FLAG_INFO (1 << 2) // 0...
|
|
211
|
-
#define
|
|
227
|
+
#define LOG_FLAG_ERROR (1 << 0) // 0...00001
|
|
228
|
+
#define LOG_FLAG_WARN (1 << 1) // 0...00010
|
|
229
|
+
#define LOG_FLAG_INFO (1 << 2) // 0...00100
|
|
230
|
+
#define LOG_FLAG_DEBUG (1 << 3) // 0...01000
|
|
231
|
+
#define LOG_FLAG_VERBOSE (1 << 4) // 0...10000
|
|
212
232
|
|
|
213
233
|
#define LOG_LEVEL_OFF 0
|
|
214
|
-
#define LOG_LEVEL_ERROR (LOG_FLAG_ERROR)
|
|
215
|
-
#define LOG_LEVEL_WARN (LOG_FLAG_ERROR | LOG_FLAG_WARN)
|
|
216
|
-
#define LOG_LEVEL_INFO (LOG_FLAG_ERROR | LOG_FLAG_WARN | LOG_FLAG_INFO)
|
|
217
|
-
#define
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
#define
|
|
221
|
-
#define
|
|
222
|
-
#define
|
|
234
|
+
#define LOG_LEVEL_ERROR (LOG_FLAG_ERROR) // 0...00001
|
|
235
|
+
#define LOG_LEVEL_WARN (LOG_FLAG_ERROR | LOG_FLAG_WARN) // 0...00011
|
|
236
|
+
#define LOG_LEVEL_INFO (LOG_FLAG_ERROR | LOG_FLAG_WARN | LOG_FLAG_INFO) // 0...00111
|
|
237
|
+
#define LOG_LEVEL_DEBUG (LOG_FLAG_ERROR | LOG_FLAG_WARN | LOG_FLAG_INFO | LOG_FLAG_DEBUG) // 0...01111
|
|
238
|
+
#define LOG_LEVEL_VERBOSE (LOG_FLAG_ERROR | LOG_FLAG_WARN | LOG_FLAG_INFO | LOG_FLAG_DEBUG | LOG_FLAG_VERBOSE) // 0...11111
|
|
239
|
+
|
|
240
|
+
#define LOG_ERROR (LOG_LEVEL_DEF & LOG_FLAG_ERROR)
|
|
241
|
+
#define LOG_WARN (LOG_LEVEL_DEF & LOG_FLAG_WARN)
|
|
242
|
+
#define LOG_INFO (LOG_LEVEL_DEF & LOG_FLAG_INFO)
|
|
243
|
+
#define LOG_DEBUG (LOG_LEVEL_DEF & LOG_FLAG_DEBUG)
|
|
244
|
+
#define LOG_VERBOSE (LOG_LEVEL_DEF & LOG_FLAG_VERBOSE)
|
|
223
245
|
|
|
224
246
|
#define LOG_ASYNC_ENABLED YES
|
|
225
247
|
|
|
226
|
-
#define LOG_ASYNC_ERROR
|
|
227
|
-
#define LOG_ASYNC_WARN
|
|
228
|
-
#define LOG_ASYNC_INFO
|
|
229
|
-
#define
|
|
248
|
+
#define LOG_ASYNC_ERROR ( NO && LOG_ASYNC_ENABLED)
|
|
249
|
+
#define LOG_ASYNC_WARN (YES && LOG_ASYNC_ENABLED)
|
|
250
|
+
#define LOG_ASYNC_INFO (YES && LOG_ASYNC_ENABLED)
|
|
251
|
+
#define LOG_ASYNC_DEBUG (YES && LOG_ASYNC_ENABLED)
|
|
252
|
+
#define LOG_ASYNC_VERBOSE (YES && LOG_ASYNC_ENABLED)
|
|
230
253
|
|
|
231
|
-
#define DDLogError(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_ERROR,
|
|
232
|
-
#define DDLogWarn(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_WARN,
|
|
233
|
-
#define DDLogInfo(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_INFO,
|
|
234
|
-
#define
|
|
254
|
+
#define DDLogError(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_ERROR, LOG_LEVEL_DEF, LOG_FLAG_ERROR, 0, frmt, ##__VA_ARGS__)
|
|
255
|
+
#define DDLogWarn(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_WARN, LOG_LEVEL_DEF, LOG_FLAG_WARN, 0, frmt, ##__VA_ARGS__)
|
|
256
|
+
#define DDLogInfo(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_INFO, LOG_LEVEL_DEF, LOG_FLAG_INFO, 0, frmt, ##__VA_ARGS__)
|
|
257
|
+
#define DDLogDebug(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_DEBUG, LOG_LEVEL_DEF, LOG_FLAG_DEBUG, 0, frmt, ##__VA_ARGS__)
|
|
258
|
+
#define DDLogVerbose(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_VERBOSE, LOG_LEVEL_DEF, LOG_FLAG_VERBOSE, 0, frmt, ##__VA_ARGS__)
|
|
235
259
|
|
|
236
|
-
#define DDLogCError(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_ERROR,
|
|
237
|
-
#define DDLogCWarn(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_WARN,
|
|
238
|
-
#define DDLogCInfo(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_INFO,
|
|
239
|
-
#define
|
|
260
|
+
#define DDLogCError(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_ERROR, LOG_LEVEL_DEF, LOG_FLAG_ERROR, 0, frmt, ##__VA_ARGS__)
|
|
261
|
+
#define DDLogCWarn(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_WARN, LOG_LEVEL_DEF, LOG_FLAG_WARN, 0, frmt, ##__VA_ARGS__)
|
|
262
|
+
#define DDLogCInfo(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_INFO, LOG_LEVEL_DEF, LOG_FLAG_INFO, 0, frmt, ##__VA_ARGS__)
|
|
263
|
+
#define DDLogCDebug(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_DEBUG, LOG_LEVEL_DEF, LOG_FLAG_DEBUG, 0, frmt, ##__VA_ARGS__)
|
|
264
|
+
#define DDLogCVerbose(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_VERBOSE, LOG_LEVEL_DEF, LOG_FLAG_VERBOSE, 0, frmt, ##__VA_ARGS__)
|
|
240
265
|
|
|
241
266
|
/**
|
|
242
267
|
* The THIS_FILE macro gives you an NSString of the file name.
|
|
@@ -323,11 +348,19 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
|
|
|
323
348
|
* you should create and add a logger.
|
|
324
349
|
**/
|
|
325
350
|
|
|
326
|
-
+ (void)addLogger:(id <DDLogger>)logger;
|
|
327
|
-
|
|
351
|
+
+ (void)addLogger:(id <DDLogger>)logger; // adds the logger using maximum log level (LOG_LEVEL_VERBOSE)
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Please use as logLevels the LOG_LEVEL_* macros
|
|
355
|
+
*
|
|
356
|
+
**/
|
|
357
|
+
+ (void)addLogger:(id <DDLogger>)logger withLogLevel:(int)logLevel;
|
|
328
358
|
|
|
359
|
+
+ (void)removeLogger:(id <DDLogger>)logger;
|
|
329
360
|
+ (void)removeAllLoggers;
|
|
330
361
|
|
|
362
|
+
+ (NSArray *)allLoggers;
|
|
363
|
+
|
|
331
364
|
/**
|
|
332
365
|
* Registered Dynamic Logging
|
|
333
366
|
*
|
|
@@ -422,7 +455,7 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
|
|
|
422
455
|
* For example, log messages for log files may be formatted differently than log messages for the console.
|
|
423
456
|
*
|
|
424
457
|
* For more information about formatters, see the "Custom Formatters" page:
|
|
425
|
-
* https://github.com/
|
|
458
|
+
* https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomFormatters
|
|
426
459
|
*
|
|
427
460
|
* The formatter may also optionally filter the log message by returning nil,
|
|
428
461
|
* in which case the logger will not log the message.
|
|
@@ -488,35 +521,35 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
|
|
|
488
521
|
**/
|
|
489
522
|
|
|
490
523
|
enum {
|
|
491
|
-
|
|
492
|
-
|
|
524
|
+
DDLogMessageCopyFile = 1 << 0,
|
|
525
|
+
DDLogMessageCopyFunction = 1 << 1
|
|
493
526
|
};
|
|
494
527
|
typedef int DDLogMessageOptions;
|
|
495
528
|
|
|
496
|
-
@interface DDLogMessage : NSObject
|
|
529
|
+
@interface DDLogMessage : NSObject <NSCopying>
|
|
497
530
|
{
|
|
498
531
|
|
|
499
532
|
// The public variables below can be accessed directly (for speed).
|
|
500
533
|
// For example: logMessage->logLevel
|
|
501
|
-
|
|
534
|
+
|
|
502
535
|
@public
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
536
|
+
int logLevel;
|
|
537
|
+
int logFlag;
|
|
538
|
+
int logContext;
|
|
539
|
+
NSString *logMsg;
|
|
540
|
+
NSDate *timestamp;
|
|
541
|
+
char *file;
|
|
542
|
+
char *function;
|
|
543
|
+
int lineNumber;
|
|
544
|
+
mach_port_t machThreadID;
|
|
512
545
|
char *queueLabel;
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
546
|
+
NSString *threadName;
|
|
547
|
+
|
|
548
|
+
// For 3rd party extensions to the framework, where flags and contexts aren't enough.
|
|
549
|
+
id tag;
|
|
550
|
+
|
|
551
|
+
// For 3rd party extensions that manually create DDLogMessage instances.
|
|
552
|
+
DDLogMessageOptions options;
|
|
520
553
|
}
|
|
521
554
|
|
|
522
555
|
/**
|
|
@@ -534,15 +567,15 @@ typedef int DDLogMessageOptions;
|
|
|
534
567
|
* However, if you need them to be copied you may use the options parameter to specify this.
|
|
535
568
|
* Options is a bitmask which supports DDLogMessageCopyFile and DDLogMessageCopyFunction.
|
|
536
569
|
**/
|
|
537
|
-
- (
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
570
|
+
- (instancetype)initWithLogMsg:(NSString *)logMsg
|
|
571
|
+
level:(int)logLevel
|
|
572
|
+
flag:(int)logFlag
|
|
573
|
+
context:(int)logContext
|
|
574
|
+
file:(const char *)file
|
|
575
|
+
function:(const char *)function
|
|
576
|
+
line:(int)line
|
|
577
|
+
tag:(id)tag
|
|
578
|
+
options:(DDLogMessageOptions)optionsMask;
|
|
546
579
|
|
|
547
580
|
/**
|
|
548
581
|
* Returns the threadID as it appears in NSLog.
|
|
@@ -586,9 +619,9 @@ typedef int DDLogMessageOptions;
|
|
|
586
619
|
|
|
587
620
|
@interface DDAbstractLogger : NSObject <DDLogger>
|
|
588
621
|
{
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
622
|
+
id <DDLogFormatter> formatter;
|
|
623
|
+
|
|
624
|
+
dispatch_queue_t loggerQueue;
|
|
592
625
|
}
|
|
593
626
|
|
|
594
627
|
- (id <DDLogFormatter>)logFormatter;
|
|
@@ -5,16 +5,19 @@
|
|
|
5
5
|
#import <mach/mach_host.h>
|
|
6
6
|
#import <mach/host_info.h>
|
|
7
7
|
#import <libkern/OSAtomic.h>
|
|
8
|
-
|
|
8
|
+
#import <Availability.h>
|
|
9
|
+
#if TARGET_OS_IPHONE
|
|
10
|
+
#import <UIKit/UIDevice.h>
|
|
11
|
+
#endif
|
|
9
12
|
|
|
10
13
|
/**
|
|
11
14
|
* Welcome to Cocoa Lumberjack!
|
|
12
15
|
*
|
|
13
16
|
* The project page has a wealth of documentation if you have any questions.
|
|
14
|
-
* https://github.com/
|
|
17
|
+
* https://github.com/CocoaLumberjack/CocoaLumberjack
|
|
15
18
|
*
|
|
16
19
|
* If you're new to the project you may wish to read the "Getting Started" wiki.
|
|
17
|
-
* https://github.com/
|
|
20
|
+
* https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted
|
|
18
21
|
*
|
|
19
22
|
**/
|
|
20
23
|
|
|
@@ -57,20 +60,24 @@ static void *const GlobalLoggingQueueIdentityKey = (void *)&GlobalLoggingQueueId
|
|
|
57
60
|
|
|
58
61
|
@interface DDLoggerNode : NSObject {
|
|
59
62
|
@public
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
id <DDLogger> logger;
|
|
64
|
+
dispatch_queue_t loggerQueue;
|
|
65
|
+
int logLevel;
|
|
62
66
|
}
|
|
63
67
|
|
|
64
|
-
|
|
68
|
+
@property (nonatomic, assign, readonly) int logLevel;
|
|
69
|
+
|
|
70
|
+
+ (DDLoggerNode *)nodeWithLogger:(id <DDLogger>)logger loggerQueue:(dispatch_queue_t)loggerQueue logLevel:(int)logLevel;
|
|
65
71
|
|
|
66
72
|
@end
|
|
67
73
|
|
|
68
74
|
|
|
69
75
|
@interface DDLog (PrivateAPI)
|
|
70
76
|
|
|
71
|
-
+ (void)lt_addLogger:(id <DDLogger>)logger;
|
|
77
|
+
+ (void)lt_addLogger:(id <DDLogger>)logger logLevel:(int)logLevel;
|
|
72
78
|
+ (void)lt_removeLogger:(id <DDLogger>)logger;
|
|
73
79
|
+ (void)lt_removeAllLoggers;
|
|
80
|
+
+ (NSArray *)lt_allLoggers;
|
|
74
81
|
+ (void)lt_log:(DDLogMessage *)logMessage;
|
|
75
82
|
+ (void)lt_flush;
|
|
76
83
|
|
|
@@ -110,51 +117,66 @@ static unsigned int numProcessors;
|
|
|
110
117
|
**/
|
|
111
118
|
+ (void)initialize
|
|
112
119
|
{
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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
|
+
}
|
|
158
180
|
}
|
|
159
181
|
|
|
160
182
|
/**
|
|
@@ -162,7 +184,7 @@ static unsigned int numProcessors;
|
|
|
162
184
|
**/
|
|
163
185
|
+ (dispatch_queue_t)loggingQueue
|
|
164
186
|
{
|
|
165
|
-
|
|
187
|
+
return loggingQueue;
|
|
166
188
|
}
|
|
167
189
|
|
|
168
190
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
@@ -171,7 +193,7 @@ static unsigned int numProcessors;
|
|
|
171
193
|
|
|
172
194
|
+ (void)applicationWillTerminate:(NSNotification *)notification
|
|
173
195
|
{
|
|
174
|
-
|
|
196
|
+
[self flushLog];
|
|
175
197
|
}
|
|
176
198
|
|
|
177
199
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
@@ -180,30 +202,46 @@ static unsigned int numProcessors;
|
|
|
180
202
|
|
|
181
203
|
+ (void)addLogger:(id <DDLogger>)logger
|
|
182
204
|
{
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
+
}});
|
|
189
216
|
}
|
|
190
217
|
|
|
191
218
|
+ (void)removeLogger:(id <DDLogger>)logger
|
|
192
219
|
{
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
220
|
+
if (logger == nil) return;
|
|
221
|
+
|
|
222
|
+
dispatch_async(loggingQueue, ^{ @autoreleasepool {
|
|
223
|
+
|
|
224
|
+
[self lt_removeLogger:logger];
|
|
225
|
+
}});
|
|
199
226
|
}
|
|
200
227
|
|
|
201
228
|
+ (void)removeAllLoggers
|
|
202
229
|
{
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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;
|
|
207
245
|
}
|
|
208
246
|
|
|
209
247
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
@@ -212,58 +250,58 @@ static unsigned int numProcessors;
|
|
|
212
250
|
|
|
213
251
|
+ (void)queueLogMessage:(DDLogMessage *)logMessage asynchronously:(BOOL)asyncFlag
|
|
214
252
|
{
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
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);
|
|
267
305
|
}
|
|
268
306
|
|
|
269
307
|
+ (void)log:(BOOL)asynchronous
|
|
@@ -276,26 +314,26 @@ static unsigned int numProcessors;
|
|
|
276
314
|
tag:(id)tag
|
|
277
315
|
format:(NSString *)format, ...
|
|
278
316
|
{
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
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
|
+
}
|
|
299
337
|
}
|
|
300
338
|
|
|
301
339
|
+ (void)log:(BOOL)asynchronous
|
|
@@ -309,29 +347,29 @@ static unsigned int numProcessors;
|
|
|
309
347
|
format:(NSString *)format
|
|
310
348
|
args:(va_list)args
|
|
311
349
|
{
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
+
}
|
|
327
365
|
}
|
|
328
366
|
|
|
329
367
|
+ (void)flushLog
|
|
330
368
|
{
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
369
|
+
dispatch_sync(loggingQueue, ^{ @autoreleasepool {
|
|
370
|
+
|
|
371
|
+
[self lt_flush];
|
|
372
|
+
}});
|
|
335
373
|
}
|
|
336
374
|
|
|
337
375
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
@@ -340,352 +378,378 @@ static unsigned int numProcessors;
|
|
|
340
378
|
|
|
341
379
|
+ (BOOL)isRegisteredClass:(Class)class
|
|
342
380
|
{
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
381
|
+
SEL getterSel = @selector(ddLogLevel);
|
|
382
|
+
SEL setterSel = @selector(ddSetLogLevel:);
|
|
383
|
+
|
|
346
384
|
#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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
|
+
|
|
391
429
|
#else
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
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
|
+
|
|
408
446
|
#endif
|
|
409
447
|
}
|
|
410
448
|
|
|
411
449
|
+ (NSArray *)registeredClasses
|
|
412
450
|
{
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
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;
|
|
452
491
|
}
|
|
453
492
|
|
|
454
493
|
+ (NSArray *)registeredClassNames
|
|
455
494
|
{
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
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;
|
|
465
504
|
}
|
|
466
505
|
|
|
467
506
|
+ (int)logLevelForClass:(Class)aClass
|
|
468
507
|
{
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
508
|
+
if ([self isRegisteredClass:aClass])
|
|
509
|
+
{
|
|
510
|
+
return [aClass ddLogLevel];
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
return -1;
|
|
475
514
|
}
|
|
476
515
|
|
|
477
516
|
+ (int)logLevelForClassWithName:(NSString *)aClassName
|
|
478
517
|
{
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
518
|
+
Class aClass = NSClassFromString(aClassName);
|
|
519
|
+
|
|
520
|
+
return [self logLevelForClass:aClass];
|
|
482
521
|
}
|
|
483
522
|
|
|
484
523
|
+ (void)setLogLevel:(int)logLevel forClass:(Class)aClass
|
|
485
524
|
{
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
525
|
+
if ([self isRegisteredClass:aClass])
|
|
526
|
+
{
|
|
527
|
+
[aClass ddSetLogLevel:logLevel];
|
|
528
|
+
}
|
|
490
529
|
}
|
|
491
530
|
|
|
492
531
|
+ (void)setLogLevel:(int)logLevel forClassWithName:(NSString *)aClassName
|
|
493
532
|
{
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
533
|
+
Class aClass = NSClassFromString(aClassName);
|
|
534
|
+
|
|
535
|
+
[self setLogLevel:logLevel forClass:aClass];
|
|
497
536
|
}
|
|
498
537
|
|
|
499
538
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
500
539
|
#pragma mark Logging Thread
|
|
501
540
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
502
541
|
|
|
503
|
-
|
|
504
|
-
* This method should only be run on the logging thread/queue.
|
|
505
|
-
**/
|
|
506
|
-
+ (void)lt_addLogger:(id <DDLogger>)logger
|
|
542
|
+
+ (void)lt_addLogger:(id <DDLogger>)logger logLevel:(int)logLevel
|
|
507
543
|
{
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
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
|
+
}
|
|
544
583
|
}
|
|
545
584
|
|
|
546
|
-
/**
|
|
547
|
-
* This method should only be run on the logging thread/queue.
|
|
548
|
-
**/
|
|
549
585
|
+ (void)lt_removeLogger:(id <DDLogger>)logger
|
|
550
586
|
{
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
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];
|
|
583
622
|
}
|
|
584
623
|
|
|
585
|
-
/**
|
|
586
|
-
* This method should only be run on the logging thread/queue.
|
|
587
|
-
**/
|
|
588
624
|
+ (void)lt_removeAllLoggers
|
|
589
625
|
{
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
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];
|
|
606
660
|
}
|
|
607
661
|
|
|
608
|
-
/**
|
|
609
|
-
* This method should only be run on the logging thread/queue.
|
|
610
|
-
**/
|
|
611
662
|
+ (void)lt_log:(DDLogMessage *)logMessage
|
|
612
663
|
{
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
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);
|
|
664
728
|
}
|
|
665
729
|
|
|
666
|
-
/**
|
|
667
|
-
* This method should only be run on the background logging thread.
|
|
668
|
-
**/
|
|
669
730
|
+ (void)lt_flush
|
|
670
731
|
{
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
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);
|
|
689
753
|
}
|
|
690
754
|
|
|
691
755
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
@@ -694,74 +758,74 @@ static unsigned int numProcessors;
|
|
|
694
758
|
|
|
695
759
|
NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy)
|
|
696
760
|
{
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
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
|
+
}
|
|
765
829
|
}
|
|
766
830
|
|
|
767
831
|
@end
|
|
@@ -772,32 +836,35 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy)
|
|
|
772
836
|
|
|
773
837
|
@implementation DDLoggerNode
|
|
774
838
|
|
|
775
|
-
|
|
839
|
+
@synthesize logLevel;
|
|
840
|
+
|
|
841
|
+
- (instancetype)initWithLogger:(id <DDLogger>)aLogger loggerQueue:(dispatch_queue_t)aLoggerQueue logLevel:(int)aLogLevel
|
|
776
842
|
{
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
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;
|
|
789
856
|
}
|
|
790
857
|
|
|
791
|
-
+ (DDLoggerNode *)nodeWithLogger:(id <DDLogger>)logger loggerQueue:(dispatch_queue_t)loggerQueue
|
|
858
|
+
+ (DDLoggerNode *)nodeWithLogger:(id <DDLogger>)logger loggerQueue:(dispatch_queue_t)loggerQueue logLevel:(int)logLevel
|
|
792
859
|
{
|
|
793
|
-
|
|
860
|
+
return [[DDLoggerNode alloc] initWithLogger:logger loggerQueue:loggerQueue logLevel:logLevel];
|
|
794
861
|
}
|
|
795
862
|
|
|
796
863
|
- (void)dealloc
|
|
797
864
|
{
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
865
|
+
#if !OS_OBJECT_USE_OBJC
|
|
866
|
+
if (loggerQueue) dispatch_release(loggerQueue);
|
|
867
|
+
#endif
|
|
801
868
|
}
|
|
802
869
|
|
|
803
870
|
@end
|
|
@@ -810,102 +877,160 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy)
|
|
|
810
877
|
|
|
811
878
|
static char *dd_str_copy(const char *str)
|
|
812
879
|
{
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
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;
|
|
821
889
|
}
|
|
822
890
|
|
|
823
|
-
- (
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
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
|
|
832
900
|
{
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
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;
|
|
879
975
|
}
|
|
880
976
|
|
|
881
977
|
- (NSString *)threadID
|
|
882
978
|
{
|
|
883
|
-
|
|
979
|
+
return [[NSString alloc] initWithFormat:@"%x", machThreadID];
|
|
884
980
|
}
|
|
885
981
|
|
|
886
982
|
- (NSString *)fileName
|
|
887
983
|
{
|
|
888
|
-
|
|
984
|
+
return DDExtractFileNameWithoutExtension(file, NO);
|
|
889
985
|
}
|
|
890
986
|
|
|
891
987
|
- (NSString *)methodName
|
|
892
988
|
{
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
989
|
+
if (function == NULL)
|
|
990
|
+
return nil;
|
|
991
|
+
else
|
|
992
|
+
return [[NSString alloc] initWithUTF8String:function];
|
|
897
993
|
}
|
|
898
994
|
|
|
899
995
|
- (void)dealloc
|
|
900
996
|
{
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
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;
|
|
909
1034
|
}
|
|
910
1035
|
|
|
911
1036
|
@end
|
|
@@ -918,166 +1043,166 @@ static char *dd_str_copy(const char *str)
|
|
|
918
1043
|
|
|
919
1044
|
- (id)init
|
|
920
1045
|
{
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
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;
|
|
951
1076
|
}
|
|
952
1077
|
|
|
953
1078
|
- (void)dealloc
|
|
954
1079
|
{
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1080
|
+
#if !OS_OBJECT_USE_OBJC
|
|
1081
|
+
if (loggerQueue) dispatch_release(loggerQueue);
|
|
1082
|
+
#endif
|
|
958
1083
|
}
|
|
959
1084
|
|
|
960
1085
|
- (void)logMessage:(DDLogMessage *)logMessage
|
|
961
1086
|
{
|
|
962
|
-
|
|
1087
|
+
// Override me
|
|
963
1088
|
}
|
|
964
1089
|
|
|
965
1090
|
- (id <DDLogFormatter>)logFormatter
|
|
966
1091
|
{
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
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;
|
|
1030
1155
|
}
|
|
1031
1156
|
|
|
1032
1157
|
- (void)setLogFormatter:(id <DDLogFormatter>)logFormatter
|
|
1033
1158
|
{
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
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
|
+
});
|
|
1060
1185
|
}
|
|
1061
1186
|
|
|
1062
1187
|
- (dispatch_queue_t)loggerQueue
|
|
1063
1188
|
{
|
|
1064
|
-
|
|
1189
|
+
return loggerQueue;
|
|
1065
1190
|
}
|
|
1066
1191
|
|
|
1067
1192
|
- (NSString *)loggerName
|
|
1068
1193
|
{
|
|
1069
|
-
|
|
1194
|
+
return NSStringFromClass([self class]);
|
|
1070
1195
|
}
|
|
1071
1196
|
|
|
1072
1197
|
- (BOOL)isOnGlobalLoggingQueue
|
|
1073
1198
|
{
|
|
1074
|
-
|
|
1199
|
+
return (dispatch_get_specific(GlobalLoggingQueueIdentityKey) != NULL);
|
|
1075
1200
|
}
|
|
1076
1201
|
|
|
1077
1202
|
- (BOOL)isOnInternalLoggerQueue
|
|
1078
1203
|
{
|
|
1079
|
-
|
|
1080
|
-
|
|
1204
|
+
void *key = (__bridge void *)self;
|
|
1205
|
+
return (dispatch_get_specific(key) != NULL);
|
|
1081
1206
|
}
|
|
1082
1207
|
|
|
1083
1208
|
@end
|