Skip to content
This repository
Browse code

Merging latest changes from CocoaLumberjack project

  • Loading branch information...
commit 428baf81dd666b41a1416bf66f0f4140ceacf868 1 parent 3ac9f8f
Robbie Hanson authored
6 Vendor/CocoaLumberjack/DDAbstractDatabaseLogger.m
@@ -115,6 +115,12 @@ - (void)destroySaveTimer
115 115 if (saveTimer)
116 116 {
117 117 dispatch_source_cancel(saveTimer);
  118 + if (saveTimerSuspended)
  119 + {
  120 + // Must resume a timer before releasing it (or it will crash)
  121 + dispatch_resume(saveTimer);
  122 + saveTimerSuspended = NO;
  123 + }
118 124 dispatch_release(saveTimer);
119 125 saveTimer = NULL;
120 126 }
5 Vendor/CocoaLumberjack/DDFileLogger.m
@@ -82,6 +82,11 @@ - (id)initWithLogsDirectory:(NSString *)aLogsDirectory
82 82 return self;
83 83 }
84 84
  85 +- (void)dealloc
  86 +{
  87 + [self removeObserver:self forKeyPath:@"maximumNumberOfLogFiles"];
  88 +}
  89 +
85 90 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
86 91 #pragma mark Configuration
87 92 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
115 Vendor/CocoaLumberjack/DDLog.h
@@ -39,26 +39,33 @@
39 39 @protocol DDLogFormatter;
40 40
41 41 /**
42   - * Define our big multiline macros so all the other macros will be easy to read.
  42 + * This is the single macro that all other macros below compile into.
  43 + * This big multiline macro makes all the other macros easier to read.
43 44 **/
44 45
45   -#define LOG_MACRO(isAsynchronous, lvl, flg, ctx, fnct, frmt, ...) \
46   - [DDLog log:isAsynchronous \
47   - level:lvl \
48   - flag:flg \
49   - context:ctx \
50   - file:__FILE__ \
51   - function:fnct \
52   - line:__LINE__ \
53   - tag:nil \
  46 +#define LOG_MACRO(isAsynchronous, lvl, flg, ctx, atag, fnct, frmt, ...) \
  47 + [DDLog log:isAsynchronous \
  48 + level:lvl \
  49 + flag:flg \
  50 + context:ctx \
  51 + file:__FILE__ \
  52 + function:fnct \
  53 + line:__LINE__ \
  54 + tag:atag \
54 55 format:(frmt), ##__VA_ARGS__]
55 56
  57 +/**
  58 + * Define the Objective-C and C versions of the macro.
  59 + * These automatically inject the proper function name for either an objective-c method or c function.
  60 + *
  61 + * We also define shorthand versions for asynchronous and synchronous logging.
  62 +**/
56 63
57 64 #define LOG_OBJC_MACRO(async, lvl, flg, ctx, frmt, ...) \
58   - LOG_MACRO(async, lvl, flg, ctx, sel_getName(_cmd), frmt, ##__VA_ARGS__)
  65 + LOG_MACRO(async, lvl, flg, ctx, nil, sel_getName(_cmd), frmt, ##__VA_ARGS__)
59 66
60 67 #define LOG_C_MACRO(async, lvl, flg, ctx, frmt, ...) \
61   - LOG_MACRO(async, lvl, flg, ctx, __FUNCTION__, frmt, ##__VA_ARGS__)
  68 + LOG_MACRO(async, lvl, flg, ctx, nil, __FUNCTION__, frmt, ##__VA_ARGS__)
62 69
63 70 #define SYNC_LOG_OBJC_MACRO(lvl, flg, ctx, frmt, ...) \
64 71 LOG_OBJC_MACRO( NO, lvl, flg, ctx, frmt, ##__VA_ARGS__)
@@ -72,9 +79,26 @@
72 79 #define ASYNC_LOG_C_MACRO(lvl, flg, ctx, frmt, ...) \
73 80 LOG_C_MACRO(YES, lvl, flg, ctx, frmt, ##__VA_ARGS__)
74 81
  82 +/**
  83 + * Define version of the macro that only execute if the logLevel is above the threshold.
  84 + * The compiled versions essentially look like this:
  85 + *
  86 + * if (logFlagForThisLogMsg & ddLogLevel) { execute log message }
  87 + *
  88 + * As shown further below, Lumberjack actually uses a bitmask as opposed to primitive log levels.
  89 + * This allows for a great amount of flexibility and some pretty advanced fine grained logging techniques.
  90 + *
  91 + * Note that when compiler optimizations are enabled (as they are for your release builds),
  92 + * the log messages above your logging threshold will automatically be compiled out.
  93 + *
  94 + * (If the compiler sees ddLogLevel declared as a constant, the compiler simply checks to see if the 'if' statement
  95 + * would execute, and if not it strips it from the binary.)
  96 + *
  97 + * We also define shorthand versions for asynchronous and synchronous logging.
  98 +**/
75 99
76 100 #define LOG_MAYBE(async, lvl, flg, ctx, fnct, frmt, ...) \
77   - do { if(lvl & flg) LOG_MACRO(async, lvl, flg, ctx, fnct, frmt, ##__VA_ARGS__); } while(0)
  101 + do { if(lvl & flg) LOG_MACRO(async, lvl, flg, ctx, nil, fnct, frmt, ##__VA_ARGS__); } while(0)
78 102
79 103 #define LOG_OBJC_MAYBE(async, lvl, flg, ctx, frmt, ...) \
80 104 LOG_MAYBE(async, lvl, flg, ctx, sel_getName(_cmd), frmt, ##__VA_ARGS__)
@@ -95,6 +119,31 @@
95 119 LOG_C_MAYBE(YES, lvl, flg, ctx, frmt, ##__VA_ARGS__)
96 120
97 121 /**
  122 + * Define versions of the macros that also accept tags.
  123 + *
  124 + * The DDLogMessage object includes a 'tag' ivar that may be used for a variety of purposes.
  125 + * It may be used to pass custom information to loggers or formatters.
  126 + * Or it may be used by 3rd party extensions to the framework.
  127 + *
  128 + * Thes macros just make it a little easier to extend logging functionality.
  129 +**/
  130 +
  131 +#define LOG_OBJC_TAG_MACRO(async, lvl, flg, ctx, tag, frmt, ...) \
  132 + LOG_MACRO(async, lvl, flg, ctx, tag, sel_getName(_cmd), frmt, ##__VA_ARGS__)
  133 +
  134 +#define LOG_C_TAG_MACRO(async, lvl, flg, ctx, tag, frmt, ...) \
  135 + LOG_MACRO(async, lvl, flg, ctx, tag, __FUNCTION__, frmt, ##__VA_ARGS__)
  136 +
  137 +#define LOG_TAG_MAYBE(async, lvl, flg, ctx, tag, fnct, frmt, ...) \
  138 + do { if(lvl & flg) LOG_MACRO(async, lvl, flg, ctx, tag, fnct, frmt, ##__VA_ARGS__); } while(0)
  139 +
  140 +#define LOG_OBJC_TAG_MAYBE(async, lvl, flg, ctx, tag, frmt, ...) \
  141 + LOG_TAG_MAYBE(async, lvl, flg, ctx, tag, sel_getName(_cmd), frmt, ##__VA_ARGS__)
  142 +
  143 +#define LOG_C_TAG_MAYBE(async, lvl, flg, ctx, tag, frmt, ...) \
  144 + LOG_TAG_MAYBE(async, lvl, flg, ctx, tag, __FUNCTION__, frmt, ##__VA_ARGS__)
  145 +
  146 +/**
98 147 * Define the standard options.
99 148 *
100 149 * We default to only 4 levels because it makes it easier for beginners
@@ -246,7 +295,8 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
246 295 * Logging Primitive.
247 296 *
248 297 * This method can be used if you have a prepared va_list.
249   - */
  298 +**/
  299 +
250 300 + (void)log:(BOOL)asynchronous
251 301 level:(int)level
252 302 flag:(int)flag
@@ -307,8 +357,9 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
307 357
308 358 /**
309 359 * Formatters may optionally be added to any logger.
310   - * If no formatter is set, the logger simply logs the message as it is given in logMessage.
311   - * Or it may use its own built in formatting style.
  360 + *
  361 + * If no formatter is set, the logger simply logs the message as it is given in logMessage,
  362 + * or it may use its own built in formatting style.
312 363 **/
313 364 - (id <DDLogFormatter>)logFormatter;
314 365 - (void)setLogFormatter:(id <DDLogFormatter>)formatter;
@@ -423,6 +474,12 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
423 474 * If you write custom loggers or formatters, you will be dealing with objects of this class.
424 475 **/
425 476
  477 +enum {
  478 + DDLogMessageCopyFile = 1 << 0,
  479 + DDLogMessageCopyFunction = 1 << 1,
  480 +};
  481 +typedef int DDLogMessageOptions;
  482 +
426 483 @interface DDLogMessage : NSObject
427 484 {
428 485
@@ -435,23 +492,34 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
435 492 int logContext;
436 493 NSString *logMsg;
437 494 NSDate *timestamp;
438   - const char *file;
439   - const char *function;
  495 + char *file;
  496 + char *function;
440 497 int lineNumber;
441 498 mach_port_t machThreadID;
442 499 char *queueLabel;
443 500 NSString *threadName;
444   - id tag; // For 3rd party extensions to the framework, where flags and contexts aren't enough.
  501 +
  502 + // For 3rd party extensions to the framework, where flags and contexts aren't enough.
  503 + id tag;
  504 +
  505 + // For 3rd party extensions that manually create DDLogMessage instances.
  506 + DDLogMessageOptions options;
445 507 }
446 508
447 509 /**
448   - * The initializer is somewhat reserved for internal use.
449   - * However, if you find need to manually create logMessage objects, there is one thing you should be aware of:
  510 + * Standard init method for a log message object.
  511 + * Used by the logging primitives. (And the macros use the logging primitives.)
  512 + *
  513 + * If you find need to manually create logMessage objects, there is one thing you should be aware of:
450 514 *
451   - * The initializer expects the file and function parameters to be string literals.
  515 + * If no flags are passed, the method expects the file and function parameters to be string literals.
452 516 * That is, it expects the given strings to exist for the duration of the object's lifetime,
453 517 * and it expects the given strings to be immutable.
454 518 * In other words, it does not copy these strings, it simply points to them.
  519 + * This is due to the fact that __FILE__ and __FUNCTION__ are usually used to specify these parameters,
  520 + * so it makes sense to optimize and skip the unnecessary allocations.
  521 + * However, if you need them to be copied you may use the options parameter to specify this.
  522 + * Options is a bitmask which supports DDLogMessageCopyFile and DDLogMessageCopyFunction.
455 523 **/
456 524 - (id)initWithLogMsg:(NSString *)logMsg
457 525 level:(int)logLevel
@@ -460,7 +528,8 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
460 528 file:(const char *)file
461 529 function:(const char *)function
462 530 line:(int)line
463   - tag:(id)tag;
  531 + tag:(id)tag
  532 + options:(DDLogMessageOptions)optionsMask;
464 533
465 534 /**
466 535 * Returns the threadID as it appears in NSLog.
50 Vendor/CocoaLumberjack/DDLog.m
@@ -278,7 +278,8 @@ + (void)log:(BOOL)asynchronous
278 278 file:file
279 279 function:function
280 280 line:line
281   - tag:tag];
  281 + tag:tag
  282 + options:0];
282 283
283 284 [self queueLogMessage:logMessage asynchronously:asynchronous];
284 285
@@ -307,7 +308,8 @@ + (void)log:(BOOL)asynchronous
307 308 file:file
308 309 function:function
309 310 line:line
310   - tag:tag];
  311 + tag:tag
  312 + options:0];
311 313
312 314 [self queueLogMessage:logMessage asynchronously:asynchronous];
313 315 }
@@ -793,6 +795,18 @@ - (void)dealloc
793 795
794 796 @implementation DDLogMessage
795 797
  798 +static char *dd_str_copy(const char *str)
  799 +{
  800 + if (str == NULL) return NULL;
  801 +
  802 + size_t length = strlen(str);
  803 + char * result = malloc(length + 1);
  804 + strncpy(result, str, length);
  805 + result[length] = 0;
  806 +
  807 + return result;
  808 +}
  809 +
796 810 - (id)initWithLogMsg:(NSString *)msg
797 811 level:(int)level
798 812 flag:(int)flag
@@ -801,6 +815,7 @@ - (id)initWithLogMsg:(NSString *)msg
801 815 function:(const char *)aFunction
802 816 line:(int)line
803 817 tag:(id)aTag
  818 + options:(DDLogMessageOptions)optionsMask
804 819 {
805 820 if ((self = [super init]))
806 821 {
@@ -808,23 +823,25 @@ - (id)initWithLogMsg:(NSString *)msg
808 823 logLevel = level;
809 824 logFlag = flag;
810 825 logContext = context;
811   - file = aFile;
812   - function = aFunction;
813 826 lineNumber = line;
814 827 tag = aTag;
  828 + options = optionsMask;
  829 +
  830 + if (options & DDLogMessageCopyFile)
  831 + file = dd_str_copy(aFile);
  832 + else
  833 + file = (char *)aFile;
  834 +
  835 + if (options & DDLogMessageCopyFunction)
  836 + file = dd_str_copy(aFunction);
  837 + else
  838 + function = (char *)aFunction;
815 839
816 840 timestamp = [[NSDate alloc] init];
817 841
818 842 machThreadID = pthread_mach_thread_np(pthread_self());
819 843
820   - const char *label = dispatch_queue_get_label(dispatch_get_current_queue());
821   - if (label)
822   - {
823   - size_t labelLength = strlen(label);
824   - queueLabel = malloc(labelLength+1);
825   - strncpy(queueLabel, label, labelLength);
826   - queueLabel[labelLength] = 0;
827   - }
  844 + queueLabel = dd_str_copy(dispatch_queue_get_label(dispatch_get_current_queue()));
828 845
829 846 threadName = [[NSThread currentThread] name];
830 847 }
@@ -851,9 +868,14 @@ - (NSString *)methodName
851 868
852 869 - (void)dealloc
853 870 {
854   - if (queueLabel != NULL) {
  871 + if (file && (options & DDLogMessageCopyFile))
  872 + free(file);
  873 +
  874 + if (function && (options & DDLogMessageCopyFunction))
  875 + free(function);
  876 +
  877 + if (queueLabel)
855 878 free(queueLabel);
856   - }
857 879 }
858 880
859 881 @end
81 Vendor/CocoaLumberjack/DDTTYLogger.h
... ... @@ -1,5 +1,9 @@
1 1 #import <Foundation/Foundation.h>
2 2
  3 +#if !TARGET_OS_IPHONE
  4 +#import <AppKit/NSColor.h>
  5 +#endif
  6 +
3 7 #import "DDLog.h"
4 8
5 9 /**
@@ -40,11 +44,29 @@
40 44 size_t pidLen;
41 45
42 46 BOOL colorsEnabled;
43   - NSMutableArray *colorProfiles;
  47 + NSMutableArray *colorProfilesArray;
  48 + NSMutableDictionary *colorProfilesDict;
44 49 }
45 50
46 51 + (DDTTYLogger *)sharedInstance;
47 52
  53 +/* Inherited from the DDLogger protocol:
  54 + *
  55 + * Formatters may optionally be added to any logger.
  56 + *
  57 + * If no formatter is set, the logger simply logs the message as it is given in logMessage,
  58 + * or it may use its own built in formatting style.
  59 + *
  60 + * More information about formatters can be found here:
  61 + * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomFormatters
  62 + *
  63 + * The actual implementation of these methods is inherited from DDAbstractLogger.
  64 +
  65 +- (id <DDLogFormatter>)logFormatter;
  66 +- (void)setLogFormatter:(id <DDLogFormatter>)formatter;
  67 +
  68 +*/
  69 +
48 70 /**
49 71 * Want to use different colors for different log levels?
50 72 * Enable this property.
@@ -67,9 +89,7 @@
67 89 * - LOG_FLAG_WARN = (orange, nil)
68 90 *
69 91 * You can customize the colors however you see fit.
70   - * There are a few things you may need to be aware of:
71   - *
72   - * You are passing a flag, NOT a level.
  92 + * Please note that you are passing a flag, NOT a level.
73 93 *
74 94 * GOOD : [ttyLogger setForegroundColor:pink backgroundColor:nil forFlag:LOG_FLAG_INFO]; // <- Good :)
75 95 * BAD : [ttyLogger setForegroundColor:pink backgroundColor:nil forFlag:LOG_LEVEL_INFO]; // <- BAD! :(
@@ -79,10 +99,10 @@
79 99 *
80 100 * If you run the application within Xcode, then the XcodeColors plugin is required.
81 101 *
82   - * If you run the application from a shell, then DDTTYLogger will automatically try to map the given color to
  102 + * If you run the application from a shell, then DDTTYLogger will automatically map the given color to
83 103 * the closest available color. (xterm-256color or xterm-color which have 256 and 16 supported colors respectively.)
84 104 *
85   - * This method invokes setForegroundColor:backgroundColor:forFlag:context:, and passes the default context (0).
  105 + * This method invokes setForegroundColor:backgroundColor:forFlag:context: and passes the default context (0).
86 106 **/
87 107 #if TARGET_OS_IPHONE
88 108 - (void)setForegroundColor:(UIColor *)txtColor backgroundColor:(UIColor *)bgColor forFlag:(int)mask;
@@ -91,9 +111,11 @@
91 111 #endif
92 112
93 113 /**
94   - * Allows you to customize the color for a particular flag, within a particular logging context.
  114 + * Just like setForegroundColor:backgroundColor:flag, but allows you to specify a particular logging context.
  115 + *
  116 + * A logging context is often used to identify log messages coming from a 3rd party framework,
  117 + * although logging context's can be used for many different functions.
95 118 *
96   - * A logging context may identify log messages coming from a 3rd party framework.
97 119 * Logging context's are explained in further detail here:
98 120 * https://github.com/robbiehanson/CocoaLumberjack/wiki/CustomContext
99 121 **/
@@ -104,26 +126,41 @@
104 126 #endif
105 127
106 128 /**
107   - * Clears the color profiles for a particular flag.
  129 + * Similar to the methods above, but allows you to map DDLogMessage->tag to a particular color profile.
  130 + * For example, you could do something like this:
  131 + *
  132 + * static NSString *const PurpleTag = @"PurpleTag";
  133 + *
  134 + * #define DDLogPurple(frmt, ...) LOG_OBJC_TAG_MACRO(NO, 0, 0, 0, PurpleTag, frmt, ##__VA_ARGS__)
  135 + *
  136 + * And then in your applicationDidFinishLaunching, or wherever you configure Lumberjack:
  137 + *
  138 + * #if TARGET_OS_IPHONE
  139 + * UIColor *purple = [UIColor colorWithRed:(64/255.0) green:(0/255.0) blue:(128/255.0) alpha:1.0];
  140 + * #else
  141 + * NSColor *purple = [NSColor colorWithCalibratedRed:(64/255.0) green:(0/255.0) blue:(128/255.0) alpha:1.0];
108 142 *
109   - * This method invokes clearColorsForFlag:context:, and passes the default context (0).
  143 + * [[DDTTYLogger sharedInstance] setForegroundColor:purple backgroundColor:nil forTag:PurpleTag];
  144 + * [DDLog addLogger:[DDTTYLogger sharedInstance]];
  145 + *
  146 + * This would essentially give you a straight NSLog replacement that prints in purple:
  147 + *
  148 + * DDLogPurple(@"I'm a purple log message!");
110 149 **/
111   -- (void)clearColorsForFlag:(int)mask;
  150 +#if TARGET_OS_IPHONE
  151 +- (void)setForegroundColor:(UIColor *)txtColor backgroundColor:(UIColor *)bgColor forTag:(id <NSCopying>)tag;
  152 +#else
  153 +- (void)setForegroundColor:(NSColor *)txtColor backgroundColor:(NSColor *)bgColor forTag:(id <NSCopying>)tag;
  154 +#endif
112 155
113 156 /**
114   - * Clears the color profiles for a particular flag, within a particular logging context.
  157 + * Clearing color profiles.
115 158 **/
  159 +- (void)clearColorsForFlag:(int)mask;
116 160 - (void)clearColorsForFlag:(int)mask context:(int)context;
117   -
118   -/**
119   - * Clears all color profiles.
120   -**/
  161 +- (void)clearColorsForTag:(id <NSCopying>)tag;
121 162 - (void)clearColorsForAllFlags;
122   -
123   -
124   -// Inherited from DDAbstractLogger
125   -
126   -// - (id <DDLogFormatter>)logFormatter;
127   -// - (void)setLogFormatter:(id <DDLogFormatter>)formatter;
  163 +- (void)clearColorsForAllTags;
  164 +- (void)clearAllColors;
128 165
129 166 @end
181 Vendor/CocoaLumberjack/DDTTYLogger.m
@@ -55,14 +55,7 @@
55 55 // To reset the foreground and background color (to default values) in one operation:
56 56 // Insert the ESCAPE_SEQ into your string, followed by ";"
57 57
58   -#define XCODE_COLORS_ESCAPE_SEQ_MAC "\033["
59   -#define XCODE_COLORS_ESCAPE_SEQ_IOS "\xC2\xA0["
60   -
61   -#if TARGET_OS_IPHONE
62   - #define XCODE_COLORS_ESCAPE_SEQ XCODE_COLORS_ESCAPE_SEQ_IOS
63   -#else
64   - #define XCODE_COLORS_ESCAPE_SEQ XCODE_COLORS_ESCAPE_SEQ_MAC
65   -#endif
  58 +#define XCODE_COLORS_ESCAPE_SEQ "\033["
66 59
67 60 #define XCODE_COLORS_RESET_FG XCODE_COLORS_ESCAPE_SEQ "fg;" // Clear any foreground color
68 61 #define XCODE_COLORS_RESET_BG XCODE_COLORS_ESCAPE_SEQ "bg;" // Clear any background color
@@ -122,7 +115,6 @@ @interface DDTTYLoggerColorProfile : NSObject {
122 115 size_t resetCodeLen;
123 116 }
124 117
125   -- (id)initWithForegroundColor:(OSColor *)fgColor backgroundColor:(OSColor *)bgColor flag:(int)mask;
126 118 - (id)initWithForegroundColor:(OSColor *)fgColor backgroundColor:(OSColor *)bgColor flag:(int)mask context:(int)ctxt;
127 119
128 120 @end
@@ -863,7 +855,8 @@ - (id)init
863 855 // Initialize color stuff
864 856
865 857 colorsEnabled = NO;
866   - colorProfiles = [[NSMutableArray alloc] init];
  858 + colorProfilesArray = [[NSMutableArray alloc] initWithCapacity:8];
  859 + colorProfilesDict = [[NSMutableDictionary alloc] initWithCapacity:8];
867 860 }
868 861 }
869 862 return self;
@@ -908,7 +901,7 @@ - (void)setColorsEnabled:(BOOL)newColorsEnabled
908 901
909 902 colorsEnabled = newColorsEnabled;
910 903
911   - if ([colorProfiles count] == 0) {
  904 + if ([colorProfilesArray count] == 0) {
912 905 [self loadDefaultColorProfiles];
913 906 }
914 907 }};
@@ -950,7 +943,7 @@ - (void)setForegroundColor:(OSColor *)txtColor backgroundColor:(OSColor *)bgColo
950 943 NSLogInfo(@"DDTTYLogger: newColorProfile: %@", newColorProfile);
951 944
952 945 NSUInteger i = 0;
953   - for (DDTTYLoggerColorProfile *colorProfile in colorProfiles)
  946 + for (DDTTYLoggerColorProfile *colorProfile in colorProfilesArray)
954 947 {
955 948 if ((colorProfile->mask == mask) && (colorProfile->context == ctxt))
956 949 {
@@ -960,10 +953,46 @@ - (void)setForegroundColor:(OSColor *)txtColor backgroundColor:(OSColor *)bgColo
960 953 i++;
961 954 }
962 955
963   - if (i < [colorProfiles count])
964   - [colorProfiles replaceObjectAtIndex:i withObject:newColorProfile];
  956 + if (i < [colorProfilesArray count])
  957 + [colorProfilesArray replaceObjectAtIndex:i withObject:newColorProfile];
965 958 else
966   - [colorProfiles addObject:newColorProfile];
  959 + [colorProfilesArray addObject:newColorProfile];
  960 + }};
  961 +
  962 + // The design of the setter logic below is taken from the DDAbstractLogger implementation.
  963 + // For documentation please refer to the DDAbstractLogger implementation.
  964 +
  965 + dispatch_queue_t currentQueue = dispatch_get_current_queue();
  966 + if (currentQueue == loggerQueue)
  967 + {
  968 + block();
  969 + }
  970 + else
  971 + {
  972 + dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
  973 + NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
  974 +
  975 + dispatch_async(globalLoggingQueue, ^{
  976 + dispatch_async(loggerQueue, block);
  977 + });
  978 + }
  979 +}
  980 +
  981 +- (void)setForegroundColor:(OSColor *)txtColor backgroundColor:(OSColor *)bgColor forTag:(id <NSCopying>)tag
  982 +{
  983 + NSAssert([(id <NSObject>)tag conformsToProtocol:@protocol(NSCopying)], @"Invalid tag");
  984 +
  985 + dispatch_block_t block = ^{ @autoreleasepool {
  986 +
  987 + DDTTYLoggerColorProfile *newColorProfile =
  988 + [[DDTTYLoggerColorProfile alloc] initWithForegroundColor:txtColor
  989 + backgroundColor:bgColor
  990 + flag:0
  991 + context:0];
  992 +
  993 + NSLogInfo(@"DDTTYLogger: newColorProfile: %@", newColorProfile);
  994 +
  995 + [colorProfilesDict setObject:newColorProfile forKey:tag];
967 996 }};
968 997
969 998 // The design of the setter logic below is taken from the DDAbstractLogger implementation.
@@ -995,7 +1024,7 @@ - (void)clearColorsForFlag:(int)mask context:(int)context
995 1024 dispatch_block_t block = ^{ @autoreleasepool {
996 1025
997 1026 NSUInteger i = 0;
998   - for (DDTTYLoggerColorProfile *colorProfile in colorProfiles)
  1027 + for (DDTTYLoggerColorProfile *colorProfile in colorProfilesArray)
999 1028 {
1000 1029 if ((colorProfile->mask == mask) && (colorProfile->context == context))
1001 1030 {
@@ -1005,9 +1034,9 @@ - (void)clearColorsForFlag:(int)mask context:(int)context
1005 1034 i++;
1006 1035 }
1007 1036
1008   - if (i < [colorProfiles count])
  1037 + if (i < [colorProfilesArray count])
1009 1038 {
1010   - [colorProfiles removeObjectAtIndex:i];
  1039 + [colorProfilesArray removeObjectAtIndex:i];
1011 1040 }
1012 1041 }};
1013 1042
@@ -1030,11 +1059,92 @@ - (void)clearColorsForFlag:(int)mask context:(int)context
1030 1059 }
1031 1060 }
1032 1061
  1062 +- (void)clearColorsForTag:(id <NSCopying>)tag
  1063 +{
  1064 + NSAssert([(id <NSObject>)tag conformsToProtocol:@protocol(NSCopying)], @"Invalid tag");
  1065 +
  1066 + dispatch_block_t block = ^{ @autoreleasepool {
  1067 +
  1068 + [colorProfilesDict removeObjectForKey:tag];
  1069 + }};
  1070 +
  1071 + // The design of the setter logic below is taken from the DDAbstractLogger implementation.
  1072 + // For documentation please refer to the DDAbstractLogger implementation.
  1073 +
  1074 + dispatch_queue_t currentQueue = dispatch_get_current_queue();
  1075 + if (currentQueue == loggerQueue)
  1076 + {
  1077 + block();
  1078 + }
  1079 + else
  1080 + {
  1081 + dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
  1082 + NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
  1083 +
  1084 + dispatch_async(globalLoggingQueue, ^{
  1085 + dispatch_async(loggerQueue, block);
  1086 + });
  1087 + }
  1088 +}
  1089 +
1033 1090 - (void)clearColorsForAllFlags
1034 1091 {
1035 1092 dispatch_block_t block = ^{ @autoreleasepool {
1036 1093
1037   - [colorProfiles removeAllObjects];
  1094 + [colorProfilesArray removeAllObjects];
  1095 + }};
  1096 +
  1097 + // The design of the setter logic below is taken from the DDAbstractLogger implementation.
  1098 + // For documentation please refer to the DDAbstractLogger implementation.
  1099 +
  1100 + dispatch_queue_t currentQueue = dispatch_get_current_queue();
  1101 + if (currentQueue == loggerQueue)
  1102 + {
  1103 + block();
  1104 + }
  1105 + else
  1106 + {
  1107 + dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
  1108 + NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
  1109 +
  1110 + dispatch_async(globalLoggingQueue, ^{
  1111 + dispatch_async(loggerQueue, block);
  1112 + });
  1113 + }
  1114 +}
  1115 +
  1116 +- (void)clearColorsForAllTags
  1117 +{
  1118 + dispatch_block_t block = ^{ @autoreleasepool {
  1119 +
  1120 + [colorProfilesDict removeAllObjects];
  1121 + }};
  1122 +
  1123 + // The design of the setter logic below is taken from the DDAbstractLogger implementation.
  1124 + // For documentation please refer to the DDAbstractLogger implementation.
  1125 +
  1126 + dispatch_queue_t currentQueue = dispatch_get_current_queue();
  1127 + if (currentQueue == loggerQueue)
  1128 + {
  1129 + block();
  1130 + }
  1131 + else
  1132 + {
  1133 + dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
  1134 + NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
  1135 +
  1136 + dispatch_async(globalLoggingQueue, ^{
  1137 + dispatch_async(loggerQueue, block);
  1138 + });
  1139 + }
  1140 +}
  1141 +
  1142 +- (void)clearAllColors
  1143 +{
  1144 + dispatch_block_t block = ^{ @autoreleasepool {
  1145 +
  1146 + [colorProfilesArray removeAllObjects];
  1147 + [colorProfilesDict removeAllObjects];
1038 1148 }};
1039 1149
1040 1150 // The design of the setter logic below is taken from the DDAbstractLogger implementation.
@@ -1077,21 +1187,33 @@ - (void)logMessage:(DDLogMessage *)logMessage
1077 1187
1078 1188 if (colorsEnabled)
1079 1189 {
1080   - for (DDTTYLoggerColorProfile *cp in colorProfiles)
  1190 + if (logMessage->tag)
  1191 + {
  1192 + colorProfile = [colorProfilesDict objectForKey:logMessage->tag];
  1193 + }
  1194 + if (colorProfile == nil)
1081 1195 {
1082   - if ((logMessage->logFlag & cp->mask) && (logMessage->logContext == cp->context))
  1196 + for (DDTTYLoggerColorProfile *cp in colorProfilesArray)
1083 1197 {
1084   - colorProfile = cp;
1085   - break;
  1198 + if ((logMessage->logFlag & cp->mask) && (logMessage->logContext == cp->context))
  1199 + {
  1200 + colorProfile = cp;
  1201 + break;
  1202 + }
1086 1203 }
1087 1204 }
1088 1205 }
1089 1206
1090 1207 // Convert log message to C string.
1091   - // The technique below is faster than using the UTF8String method.
  1208 + //
  1209 + // We use the stack instead of the heap for speed if possible.
  1210 + // But we're extra cautious to avoid a stack overflow.
1092 1211
1093 1212 NSUInteger msgLen = [logMsg lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
1094   - char msg[msgLen + 1];
  1213 + const BOOL useStack = msgLen < (1024 * 4);
  1214 +
  1215 + char msgStack[useStack ? (msgLen + 1) : 0];
  1216 + char *msg = useStack ? msgStack : (char *)malloc(msgLen + 1);
1095 1217
1096 1218 [logMsg getCString:msg maxLength:(msgLen + 1) encoding:NSUTF8StringEncoding];
1097 1219
@@ -1219,6 +1341,10 @@ - (void)logMessage:(DDLogMessage *)logMessage
1219 1341
1220 1342 writev(STDERR_FILENO, v, 12);
1221 1343 }
  1344 +
  1345 + if (!useStack) {
  1346 + free(msg);
  1347 + }
1222 1348 }
1223 1349 }
1224 1350
@@ -1233,11 +1359,6 @@ - (NSString *)loggerName
1233 1359
1234 1360 @implementation DDTTYLoggerColorProfile
1235 1361
1236   -- (id)initWithForegroundColor:(OSColor *)fgColor backgroundColor:(OSColor *)bgColor flag:(int)aMask
1237   -{
1238   - return [self initWithForegroundColor:fgColor backgroundColor:bgColor flag:aMask context:0];
1239   -}
1240   -
1241 1362 - (id)initWithForegroundColor:(OSColor *)fgColor backgroundColor:(OSColor *)bgColor flag:(int)aMask context:(int)ctxt
1242 1363 {
1243 1364 if ((self = [super init]))

0 comments on commit 428baf8

Please sign in to comment.
Something went wrong with that request. Please try again.