Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Removed Cocoa Lumberjack and patched the project to work. Addresses #200

.

**IMPORTANT:** Logging is only patched so that it works at this point - only to have it work on 10.8! Missing is ability to specify different log formats, including Xcode, so if you're targeting Xcode, it wont be as nicely integrated. I plan to bring full support back in next major update (unless it will be substantially delayed and great demand for 10.8 support).
  • Loading branch information...
commit fde2ac179c7106cc5880d5240530130555a1173c 1 parent e19b1b7
@tomaz tomaz authored
View
7 Application/GBAppledocApplication.m
@@ -7,6 +7,7 @@
//
#import "timing.h"
+#import "GBExitCodes.h"
#import "DDCliUtil.h"
#import "DDGetoptLongParser.h"
#import "GBStore.h"
@@ -324,11 +325,7 @@ - (void)application:(DDCliApplication *)app willParseOptions:(DDGetoptLongParser
#pragma mark Application handling
- (void)initializeLoggingSystem {
- id formatter = [GBLog logFormatterForLogFormat:self.logformat];
- [[GBConsoleLogger sharedInstance] setLogFormatter:formatter];
- [DDLog addLogger:[GBConsoleLogger sharedInstance]];
- [GBLog setLogLevelFromVerbose:self.verbose];
- [formatter release];
+ initialize_logging();
}
- (void)deleteContentsOfOutputPath {
View
167 Common/GBLog.h
@@ -6,79 +6,63 @@
// Copyright (C) 2010, Gentle Bytes. All rights reserved.
//
-#import "DDLog.h"
-#import "DDTTYLogger.h"
-#import "DDFileLogger.h"
+#import <Foundation/Foundation.h>
+#import "GBExitCodes.h"
#import "DDCliUtil.h"
-// Undefine defaults
+#pragma mark - Logger setup
-#undef LOG_FLAG_ERROR
-#undef LOG_FLAG_WARN
-#undef LOG_FLAG_INFO
-#undef LOG_FLAG_VERBOSE
-
-#undef LOG_LEVEL_ERROR
-#undef LOG_LEVEL_WARN
-#undef LOG_LEVEL_INFO
-#undef LOG_LEVEL_VERBOSE
-
-#undef LOG_ERROR
-#undef LOG_WARN
-#undef LOG_INFO
-#undef LOG_VERBOSE
-
-#undef DDLogError
-#undef DDLogWarn
-#undef DDLogInfo
-#undef DDLogVerbose
+typedef void(*logger_function_t)(int flag, const char *file, const char *function, int line, NSString *message);
+extern void initialize_logging();
+extern logger_function_t log_function;
+extern NSUInteger log_level;
+extern NSInteger kGBLogBasedResult;
-#undef DDLogCError
-#undef DDLogCWarn
-#undef DDLogCInfo
-#undef DDLogCVerbose
+#pragma mark - Low level logging flags
-#undef SYNC_LOG_OBJC_MAYBE
+#define LOG_FLAG_ERROR (1 << 0) // 0...000001
+#define LOG_FLAG_WARN (1 << 1) // 0...000010
+#define LOG_FLAG_NORMAL (1 << 2) // 0...000100
+#define LOG_FLAG_INFO (1 << 3) // 0...001000
+#define LOG_FLAG_VERBOSE (1 << 4) // 0...010000
+#define LOG_FLAG_DEBUG (1 << 5) // 0...100000
-// Now define everything the way we want it...
+#define LOG_LEVEL_ERROR (LOG_FLAG_ERROR) // 0...000001
+#define LOG_LEVEL_WARN (LOG_FLAG_WARN | LOG_LEVEL_ERROR) // 0...000011
+#define LOG_LEVEL_NORMAL (LOG_FLAG_NORMAL | LOG_LEVEL_WARN) // 0...000111
+#define LOG_LEVEL_INFO (LOG_FLAG_INFO | LOG_LEVEL_NORMAL) // 0...001111
+#define LOG_LEVEL_VERBOSE (LOG_FLAG_VERBOSE | LOG_LEVEL_INFO) // 0...011111
+#define LOG_LEVEL_DEBUG (LOG_FLAG_DEBUG | LOG_LEVEL_VERBOSE) // 0...111111
-extern NSUInteger kGBLogLevel;
-extern NSInteger kGBLogBasedResult;
-void GBLogUpdateResult(NSInteger result);
+#pragma mark - Determine whether certain log levels are enabled
-#define LOG_FLAG_FATAL (1 << 0) // 0...0000001
-#define LOG_FLAG_ERROR (1 << 1) // 0...0000010
-#define LOG_FLAG_WARN (1 << 2) // 0...0000100
-#define LOG_FLAG_NORMAL (1 << 3) // 0...0001000
-#define LOG_FLAG_INFO (1 << 4) // 0...0010000
-#define LOG_FLAG_VERBOSE (1 << 5) // 0...0100000
-#define LOG_FLAG_DEBUG (1 << 6) // 0...1000000
+#define LOG_ERROR_ENABLED (log_level & LOG_FLAG_ERROR)
+#define LOG_WARN_ENABLED (log_level & LOG_FLAG_WARN)
+#define LOG_NORMAL_ENABLED (log_level & LOG_FLAG_NORMAL)
+#define LOG_INFO_ENABLED (log_level & LOG_FLAG_INFO)
+#define LOG_VERBOSE_ENABLED (log_level & LOG_FLAG_VERBOSE)
+#define LOG_DEBUG_ENABLED (log_level & LOG_FLAG_DEBUG)
-#define LOG_LEVEL_FATAL (LOG_FLAG_FATAL) // 0...0000001
-#define LOG_LEVEL_ERROR (LOG_FLAG_ERROR | LOG_LEVEL_FATAL) // 0...0000011
-#define LOG_LEVEL_WARN (LOG_FLAG_WARN | LOG_LEVEL_ERROR) // 0...0000111
-#define LOG_LEVEL_NORMAL (LOG_FLAG_NORMAL | LOG_LEVEL_WARN) // 0...0001111
-#define LOG_LEVEL_INFO (LOG_FLAG_INFO | LOG_LEVEL_NORMAL) // 0...0011111
-#define LOG_LEVEL_VERBOSE (LOG_FLAG_VERBOSE | LOG_LEVEL_INFO) // 0...0111111
-#define LOG_LEVEL_DEBUG (LOG_FLAG_DEBUG | LOG_LEVEL_VERBOSE) // 0...1111111
+#pragma mark - Logging macros & functions
-#define SYNC_LOG_OBJC_MAYBE(lvl, flg, frmt, ...) LOG_MAYBE(YES, lvl, flg, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
+#define LOG_MACRO(flg, frmt, ...) { \
+ NSString *message = [NSString stringWithFormat:frmt, ##__VA_ARGS__]; \
+ log_function(flg, __FILE__, __PRETTY_FUNCTION__, __LINE__, message); \
+}
+#define LOG_MAYBE(lvl, flg, frmt, ...) do { if ((lvl & flg)) LOG_MACRO(flg, frmt, ##__VA_ARGS__); } while(0)
-#define GBLogFatal(frmt, ...) { GBLogUpdateResult(GBEXIT_LOG_FATAL); SYNC_LOG_OBJC_MAYBE(kGBLogLevel, LOG_FLAG_FATAL, frmt, ##__VA_ARGS__); }
-#define GBLogError(frmt, ...) { GBLogUpdateResult(GBEXIT_LOG_ERROR); SYNC_LOG_OBJC_MAYBE(kGBLogLevel, LOG_FLAG_ERROR, frmt, ##__VA_ARGS__); }
-#define GBLogWarn(frmt, ...) { GBLogUpdateResult(GBEXIT_LOG_WARNING); SYNC_LOG_OBJC_MAYBE(kGBLogLevel, LOG_FLAG_WARN, frmt, ##__VA_ARGS__); }
-#define GBLogNormal(frmt, ...) SYNC_LOG_OBJC_MAYBE(kGBLogLevel, LOG_FLAG_NORMAL, frmt, ##__VA_ARGS__)
-#define GBLogInfo(frmt, ...) SYNC_LOG_OBJC_MAYBE(kGBLogLevel, LOG_FLAG_INFO, frmt, ##__VA_ARGS__)
-#define GBLogVerbose(frmt, ...) SYNC_LOG_OBJC_MAYBE(kGBLogLevel, LOG_FLAG_VERBOSE, frmt, ##__VA_ARGS__)
-#define GBLogDebug(frmt, ...) SYNC_LOG_OBJC_MAYBE(kGBLogLevel, LOG_FLAG_DEBUG, frmt, ##__VA_ARGS__)
-#define GBLogIsEnabled(level) ((kGBLogLevel & level) > 0)
+#define GBLogError(frmt, ...) LOG_MAYBE(log_level, LOG_FLAG_ERROR, frmt, ##__VA_ARGS__)
+#define GBLogWarn(frmt, ...) LOG_MAYBE(log_level, LOG_FLAG_WARN, frmt, ##__VA_ARGS__)
+#define GBLogNormal(frmt, ...) LOG_MAYBE(log_level, LOG_FLAG_NORMAL, frmt, ##__VA_ARGS__)
+#define GBLogInfo(frmt, ...) LOG_MAYBE(log_level, LOG_FLAG_INFO, frmt, ##__VA_ARGS__)
+#define GBLogVerbose(frmt, ...) LOG_MAYBE(log_level, LOG_FLAG_VERBOSE, frmt, ##__VA_ARGS__)
+#define GBLogDebug(frmt, ...) LOG_MAYBE(log_level, LOG_FLAG_DEBUG, frmt, ##__VA_ARGS__)
-// Macros that store given file/line info. Mostly used for better Xcode integration!
-#define GBLogXError(source,frmt,...) { [DDLog storeFilename:[source fullpath] line:[source lineNumber]]; GBLogError(frmt, ##__VA_ARGS__); }
-#define GBLogXWarn(source,frmt,...) { [DDLog storeFilename:[source fullpath] line:[source lineNumber]]; GBLogWarn(frmt, ##__VA_ARGS__); }
+// Macros that log source info.
+#define GBLogXError(source,frmt,...) { GBLogError(frmt, ##__VA_ARGS__); }
+#define GBLogXWarn(source,frmt,...) { GBLogWarn(frmt, ##__VA_ARGS__); }
-// Helper macros for logging exceptions. Note that we don't use formatting here as it would make the output unreadable
-// in higher level log formats. The information is already verbose enough!
+// Custom macros for logging complex objects.
#define GBLogExceptionLine(frmt,...) { ddprintf(frmt, ##__VA_ARGS__); ddprintf(@"\n"); }
#define GBLogExceptionNoStack(exception,frmt,...) { \
if (frmt) GBLogExceptionLine(frmt, ##__VA_ARGS__); \
@@ -95,65 +79,4 @@ void GBLogUpdateResult(NSInteger result);
if (frmt) GBLogExceptionLine(frmt, ##__VA_ARGS__); \
if ([error localizedDescription]) GBLogExceptionLine(@"%@", [error localizedDescription]); \
if ([error localizedFailureReason]) GBLogExceptionLine(@"%@", [error localizedFailureReason]); \
-}
-
-#pragma mark Application wide logging helpers
-
-/** Logging helper class with common log-related functionality.
- */
-@interface GBLog : NSObject
-
-/** Sets logging level to the given value.
-
- Sending this message has the same effect as setting the value of `kGBLogLevel` directly.
-
- @param value The new application-wide log level.
- @see setLogLevelFromVerbose:
- */
-+ (void)setLogLevel:(NSUInteger)value;
-
-/** Sets logging level from the given verbose command line argument value.
-
- The method converts the given command line argument value to a proper log level and sends it to @c setLogLevel:
- method. The value is forced into a valid range beforehand.
-
- @param verbosity Verbose command line argument value to use.
- */
-+ (void)setLogLevelFromVerbose:(NSString *)verbosity;
-
-/** Returns proper log formatter based on the given log format command line argument value.
-
- The method returns `GBLogFormat0Formatter`, `GBLogFormat1Formatter`, `GBLogFormat2Formatter`, `GBLogFormat3Formatter`
- or `GBLogFormat4Formatter` instance, based on the given value. The value is forced into a valid range beforehand.
-
- @param level Log format command line argument value to use.
- @return Returns the log formatter corresponding to the given value.
- */
-+ (id<DDLogFormatter>)logFormatterForLogFormat:(NSString *)level;
-
-@end
-
-#pragma mark Our custom loggers
-
-@interface GBConsoleLogger : DDAbstractLogger <DDLogger>
-
-+ (GBConsoleLogger *)sharedInstance;
-
-@end
-
-#pragma mark Log formatters
-
-@interface GBLogFormat0Formatter : NSObject <DDLogFormatter>
-@end
-
-@interface GBLogFormat1Formatter : NSObject <DDLogFormatter>
-@end
-
-@interface GBLogFormat2Formatter : NSObject <DDLogFormatter>
-@end
-
-@interface GBLogFormat3Formatter : NSObject <DDLogFormatter>
-@end
-
-@interface GBLogFormatXcodeFormatter : NSObject <DDLogFormatter>
-@end
+}
View
206 Common/GBLog.m
@@ -6,176 +6,86 @@
// Copyright (C) 2010, Gentle Bytes. All rights reserved.
//
+#include <sys/timeb.h>
#import "GBLog.h"
-#pragma mark Log level handling
+// NOTE: All functions here are purposely using C interface to keep as little overhead as possible.
-NSUInteger kGBLogLevel = LOG_LEVEL_NORMAL;
-NSInteger kGBLogBasedResult = GBEXIT_SUCCESS;
+#pragma mark - Definitions of external symbols
-void GBLogUpdateResult(NSInteger result) {
- // This code relies on exit codes being larger for more serious errors.
- if (result > kGBLogBasedResult) kGBLogBasedResult = result;
-}
+logger_function_t log_function = NULL;
+NSUInteger log_level = LOG_LEVEL_NORMAL;
+NSInteger kGBLogBasedResult = GBEXIT_SUCCESS;
-@implementation GBLog
+#pragma mark - Common formatting functions
-+ (void)setLogLevel:(NSUInteger)value {
- kGBLogLevel = value;
-}
-
-+ (void)setLogLevelFromVerbose:(NSString *)verbosity {
- NSInteger value = [verbosity integerValue];
- if (value < 0) value = 0;
- if (value > 6) value = 6;
- switch (value) {
- case 0:
- [self setLogLevel:LOG_LEVEL_FATAL];
- break;
- case 1:
- [self setLogLevel:LOG_LEVEL_ERROR];
- break;
- case 2:
- [self setLogLevel:LOG_LEVEL_WARN];
- break;
- case 3:
- [self setLogLevel:LOG_LEVEL_NORMAL];
- break;
- case 4:
- [self setLogLevel:LOG_LEVEL_INFO];
- break;
- case 5:
- [self setLogLevel:LOG_LEVEL_VERBOSE];
- break;
- case 6:
- [self setLogLevel:LOG_LEVEL_DEBUG];
- break;
+static FILE *log_output_for_flag(int flag) {
+ switch (flag) {
+ case LOG_FLAG_ERROR:
+ case LOG_FLAG_WARN:
+ return stderr;
}
+ return stdout;
}
-+ (id<DDLogFormatter>)logFormatterForLogFormat:(NSString *)level {
- if ([level isKindOfClass:[NSString class]]) {
- level = [level lowercaseString];
- if ([level isEqualToString:@"xcode"]) return [[[GBLogFormatXcodeFormatter alloc] init] autorelease];
- }
+static inline char *log_current_time() {
+ static char formatted[50];
+ static char result[50];
- NSInteger value = [level integerValue];
- if (value < 0) value = 0;
- if (value > 3) value = 3;
- switch (value) {
- case 0: return [[[GBLogFormat0Formatter alloc] init] autorelease];
- case 1: return [[[GBLogFormat1Formatter alloc] init] autorelease];
- case 2: return [[[GBLogFormat2Formatter alloc] init] autorelease];
- case 3: return [[[GBLogFormat3Formatter alloc] init] autorelease];
- }
- return nil;
-}
-
-@end
-
-#pragma mark Custom loggers
-
-@implementation GBConsoleLogger
-
-static GBConsoleLogger *sharedConsoleLogger;
-
-+ (void)initialize {
- static BOOL initialized = NO;
- if (!initialized) {
- initialized = YES;
- sharedConsoleLogger = [[GBConsoleLogger alloc] init];
- }
-}
-
-+ (GBConsoleLogger *)sharedInstance {
- return sharedConsoleLogger;
-}
-
-- (void)logMessage:(DDLogMessage *)logMessage {
- // Note that we asume formatter is always attached - this is not a generic logger, so this will work for our case! It should still work in case log message is nil by doing nothing...
- NSString *logMsg = logMessage->logMsg;
- if (formatter) logMsg = [formatter formatLogMessage:logMessage];
- if (logMsg) {
- switch (logMessage->logFlag) {
- case LOG_FLAG_FATAL:
- case LOG_FLAG_ERROR:
- case LOG_FLAG_WARN:
- ddfprintf(stderr, @"%@\n", logMsg);
- break;
- default:
- ddfprintf(stdout, @"%@\n", logMsg);
- break;
- }
- }
+ // Get time with milliseconds precision.
+ struct timeb now;
+ ftime(&now);
+
+ // Convert time since epoch to struct and format
+ struct tm *tm = localtime(&now.time);
+ strftime(formatted, 50, "%H:%M:%S", tm);
+
+ // Use formatted time and append milliseconds.
+ sprintf(result, "%s.%03d", formatted, now.millitm);
+ return result;
}
-- (NSString *)loggerName {
- return @"cocoa.lumberjack.gbconsolelogger";
+static char *log_file_name(const char *path) {
+ return strrchr(path, '/') ? strrchr(path, '/') + 1 : path;
}
-@end
-
-#pragma mark Log formatting handling
-
-static NSString *GBLogLevel(DDLogMessage *msg) {
- switch (msg->logFlag) {
- case LOG_FLAG_FATAL: return @"FATAL";
- case LOG_FLAG_ERROR: return @"ERROR";
- case LOG_FLAG_WARN: return @"WARN";
- case LOG_FLAG_NORMAL: return @"NORMAL";
- case LOG_FLAG_INFO: return @"INFO";
- case LOG_FLAG_VERBOSE: return @"VERBOSE";
- case LOG_FLAG_DEBUG: return @"DEBUG";
+static char *log_flag_description(int flag) {
+ switch (flag) {
+ case LOG_FLAG_ERROR: return "ERROR";
+ case LOG_FLAG_WARN: return "WARN";
+ case LOG_FLAG_NORMAL: return "NORMAL";
+ case LOG_FLAG_INFO: return "INFO";
+ case LOG_FLAG_VERBOSE: return "VERBOSE";
+ case LOG_FLAG_DEBUG: return "DEBUG";
}
- return @"UNKNOWN";
+ return "UNKNOWN";
}
-#define GBLogFile(msg) [msg fileName]
-#define GBLogFileExt(msg) [msg fileNameExt]
-#define GBLogMessage(msg) msg->logMsg
-#define GBLogMethod(msg) [msg methodName]
-#define GBLogLine(msg) msg->lineNumber
+#pragma mark - Logging implementation
-@implementation GBLogFormat0Formatter
-- (NSString *)formatLogMessage:(DDLogMessage *)m {
- return [NSString stringWithFormat:@"%@", GBLogMessage(m)];
+static void log_function_1(int flag, const char *path, const char *function, int line, NSString *message) {
+ FILE *output = log_output_for_flag(flag);
+ char *time = log_current_time();
+ char *level = log_flag_description(flag);
+ fprintf(output, "%s %s > %s\n", time, level, [message UTF8String]);
}
-@end
-@implementation GBLogFormat1Formatter
-- (NSString *)formatLogMessage:(DDLogMessage *)m {
- return [NSString stringWithFormat:@"%@ | %@", GBLogLevel(m), GBLogMessage(m)];
+static void log_function_2(int flag, const char *path, const char *function, int line, NSString *message) {
+ FILE *output = log_output_for_flag(flag);
+ char *time = log_current_time();
+ char *file = log_file_name(path);
+ char *level = log_flag_description(flag);
+ fprintf(output, "%s: %s:%d %s > %s\n", time, file, line, level, [message UTF8String]);
}
-@end
-@implementation GBLogFormat2Formatter
-- (NSString *)formatLogMessage:(DDLogMessage *)m {
- return [NSString stringWithFormat:@"%@ | %@ > %@", GBLogLevel(m), GBLogMethod(m), GBLogMessage(m)];
+static void log_function_3(int flag, const char *path, const char *function, int line, NSString *message) {
+ FILE *output = log_output_for_flag(flag);
+ char *time = log_current_time();
+ char *level = log_flag_description(flag);
+ fprintf(output, "%s: %s (line %d) %s > %s\n", time, function, line, level, [message UTF8String]);
}
-@end
-@implementation GBLogFormat3Formatter
-- (NSString *)formatLogMessage:(DDLogMessage *)m {
- return [NSString stringWithFormat:@"%@ | %@ ln %i > %@", GBLogLevel(m), GBLogFile(m), GBLogLine(m), GBLogMessage(m)];
-}
-@end
-
-@implementation GBLogFormatXcodeFormatter
-- (NSString *)formatLogMessage:(DDLogMessage *)m {
- if (m->originalFilename) {
- NSString *level = nil;
- switch (m->logFlag) {
- case LOG_FLAG_FATAL: level = @"fatal"; break;
- case LOG_FLAG_ERROR: level = @"error"; break;
- case LOG_FLAG_WARN: level = @"warning"; break;
- case LOG_FLAG_NORMAL: level = @"normal"; break;
- case LOG_FLAG_INFO: level = @"info"; break;
- case LOG_FLAG_VERBOSE: level = @"verbose"; break;
- case LOG_FLAG_DEBUG: level = @"debug"; break;
- default: level = @"unknown"; break;
- }
- return [NSString stringWithFormat:@"%@:%u: %@: %@", m->originalFilename, m->originalLine, level, GBLogMessage(m)];
- }
- return GBLogMessage(m);
+void initialize_logging() {
+ log_level = LOG_LEVEL_NORMAL;
+ log_function = log_function_2;
}
-@end
View
41 Common/ThirdParty/CocoaLumberjack/DDASLLogger.h
@@ -1,41 +0,0 @@
-#import <Foundation/Foundation.h>
-#import <asl.h>
-
-#import "DDLog.h"
-
-/**
- * Welcome to Cocoa Lumberjack!
- *
- * The Google Code page has a wealth of documentation if you have any questions.
- * http://code.google.com/p/cocoalumberjack/
- *
- * If you're new to the project you may wish to read the "Getting Started" page.
- * http://code.google.com/p/cocoalumberjack/wiki/GettingStarted
- *
- *
- * This class provides a logger for the Apple System Log facility.
- *
- * As described in the "Getting Started" page,
- * the traditional NSLog() function directs it's output to two places:
- *
- * - Apple System Log
- * - StdErr (if stderr is a TTY) so log statements show up in Xcode console
- *
- * To duplicate NSLog() functionality you can simply add this logger and a tty logger.
- * However, if you instead choose to use file logging (for faster performance),
- * you may choose to use a file logger and a tty logger.
-**/
-
-@interface DDASLLogger : DDAbstractLogger <DDLogger>
-{
- aslclient client;
-}
-
-+ (DDASLLogger *)sharedInstance;
-
-// Inherited from DDAbstractLogger
-
-// - (id <DDLogFormatter>)logFormatter;
-// - (void)setLogFormatter:(id <DDLogFormatter>)formatter;
-
-@end
View
86 Common/ThirdParty/CocoaLumberjack/DDASLLogger.m
@@ -1,86 +0,0 @@
-#import "DDASLLogger.h"
-
-#import <libkern/OSAtomic.h>
-
-
-@implementation DDASLLogger
-
-static DDASLLogger *sharedInstance;
-
-/**
- * The runtime sends initialize to each class in a program exactly one time just before the class,
- * or any class that inherits from it, is sent its first message from within the program. (Thus the
- * method may never be invoked if the class is not used.) The runtime sends the initialize message to
- * classes in a thread-safe manner. Superclasses receive this message before their subclasses.
- *
- * This method may also be called directly (assumably by accident), hence the safety mechanism.
-**/
-+ (void)initialize
-{
- static BOOL initialized = NO;
- if (!initialized)
- {
- initialized = YES;
-
- sharedInstance = [[DDASLLogger alloc] init];
- }
-}
-
-+ (DDASLLogger *)sharedInstance
-{
- return sharedInstance;
-}
-
-- (id)init
-{
- if (sharedInstance != nil)
- {
- [self release];
- return nil;
- }
-
- if ((self = [super init]))
- {
- // A default asl client is provided for the main thread,
- // but background threads need to create their own client.
-
- client = asl_open(NULL, "com.apple.console", 0);
- }
- return self;
-}
-
-- (void)logMessage:(DDLogMessage *)logMessage
-{
- NSString *logMsg = logMessage->logMsg;
-
- if (formatter)
- {
- logMsg = [formatter formatLogMessage:logMessage];
- }
-
- if (logMsg)
- {
- const char *msg = [logMsg UTF8String];
-
- int aslLogLevel;
- switch (logMessage->logLevel)
- {
- // Note: By default ASL will filter anything above level 5 (Notice).
- // So our mappings shouldn't go above that level.
-
- case 1 : aslLogLevel = ASL_LEVEL_CRIT; break;
- case 2 : aslLogLevel = ASL_LEVEL_ERR; break;
- case 3 : aslLogLevel = ASL_LEVEL_WARNING; break;
- default : aslLogLevel = ASL_LEVEL_NOTICE; break;
- }
-
- asl_log(client, NULL, aslLogLevel, "%s", msg);
- }
-}
-
-- (NSString *)loggerName
-{
- return @"cocoa.lumberjack.aslLogger";
-}
-
-@end
View
275 Common/ThirdParty/CocoaLumberjack/DDFileLogger.h
@@ -1,275 +0,0 @@
-#import <Foundation/Foundation.h>
-#import "DDLog.h"
-
-@class DDLogFileInfo;
-
-
-// Default configuration and safety/sanity values.
-//
-// maximumFileSize -> DEFAULT_LOG_MAX_FILE_SIZE
-// rollingFrequency -> DEFAULT_LOG_ROLLING_FREQUENCY
-// maximumNumberOfLogFiles -> DEFAULT_LOG_MAX_NUM_LOG_FILES
-//
-// You should carefully consider the proper configuration values for your application.
-
-#define DEFAULT_LOG_MAX_FILE_SIZE (1024 * 1024) // 1 MB
-#define DEFAULT_LOG_ROLLING_FREQUENCY (60 * 60 * 24) // 24 Hours
-#define DEFAULT_LOG_MAX_NUM_LOG_FILES (5) // 5 Files
-
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// The LogFileManager protocol is designed to allow you to control all aspects of your log files.
-//
-// The primary purpose of this is to allow you to do something with the log files after they have been rolled.
-// Perhaps you want to compress them to save disk space.
-// Perhaps you want to upload them to an FTP server.
-// Perhaps you want to run some analytics on the file.
-//
-// A default LogFileManager is, of course, provided.
-// The default LogFileManager simply deletes old log files according to the maximumNumberOfLogFiles property.
-//
-// This protocol provides various methods to fetch the list of log files.
-//
-// There are two variants: sorted and unsorted.
-// If sorting is not necessary, the unsorted variant is obviously faster.
-// The sorted variant will return an array sorted by when the log files were created,
-// with the most recently created log file at index 0, and the oldest log file at the end of the array.
-//
-// You can fetch only the log file paths (full path including name), log file names (name only),
-// or an array of DDLogFileInfo objects.
-// The DDLogFileInfo class is documented below, and provides a handy wrapper that
-// gives you easy access to various file attributes such as the creation date or the file size.
-
-@protocol DDLogFileManager <NSObject>
-@required
-
-// Public properties
-
-@property (readwrite, assign) NSUInteger maximumNumberOfLogFiles;
-
-// Public methods
-
-- (NSString *)logsDirectory;
-
-- (NSArray *)unsortedLogFilePaths;
-- (NSArray *)unsortedLogFileNames;
-- (NSArray *)unsortedLogFileInfos;
-
-- (NSArray *)sortedLogFilePaths;
-- (NSArray *)sortedLogFileNames;
-- (NSArray *)sortedLogFileInfos;
-
-// Private methods (only to be used by DDFileLogger)
-
-- (NSString *)createNewLogFile;
-
-@optional
-
-// Notifications from DDFileLogger
-
-- (void)didArchiveLogFile:(NSString *)logFilePath;
-- (void)didRollAndArchiveLogFile:(NSString *)logFilePath;
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Default log file manager.
-//
-// All log files are placed inside the logsDirectory.
-// On Mac, this is in ~/Library/Application Support/<Application Name>/Logs.
-// On iPhone, this is in ~/Documents/Logs.
-//
-// Log files are named "log-<uuid>.txt",
-// where uuid is a 6 character hexadecimal consisting of the set [0123456789ABCDEF].
-//
-// Archived log files are automatically deleted according to the maximumNumberOfLogFiles property.
-
-@interface DDLogFileManagerDefault : NSObject <DDLogFileManager>
-{
- NSUInteger maximumNumberOfLogFiles;
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Most users will want file log messages to be prepended with the date and time.
-// Rather than forcing the majority of users to write their own formatter,
-// we will supply a logical default formatter.
-// Users can easily replace this formatter with their own by invoking the setLogFormatter method.
-// It can also be removed by calling setLogFormatter, and passing a nil parameter.
-//
-// In addition to the convenience of having a logical default formatter,
-// it will also provide a template that makes it easy for developers to copy and change.
-
-@interface DDLogFileFormatterDefault : NSObject <DDLogFormatter>
-{
- NSDateFormatter *dateFormatter;
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@interface DDFileLogger : DDAbstractLogger <DDLogger>
-{
- id <DDLogFileManager> logFileManager;
-
- DDLogFileInfo *currentLogFileInfo;
- NSFileHandle *currentLogFileHandle;
-
- NSTimer *rollingTimer;
-
- unsigned long long maximumFileSize;
- NSTimeInterval rollingFrequency;
-}
-
-- (id)init;
-- (id)initWithLogFileManager:(id <DDLogFileManager>)logFileManager;
-
-// Configuration
-//
-// maximumFileSize:
-// The approximate maximum size to allow log files to grow.
-// If a log file is larger than this value after a write,
-// then the log file is rolled.
-//
-// rollingFrequency
-// How often to roll the log file.
-// The frequency is given as an NSTimeInterval, which is a double that specifies the interval in seconds.
-// Once the log file gets to be this old, it is rolled.
-//
-// Both the maximumFileSize and the rollingFrequency are used to manage rolling.
-// Whichever occurs first will cause the log file to be rolled.
-//
-// For example:
-// The rollingFrequency is 24 hours,
-// but the log file surpasses the maximumFileSize after only 20 hours.
-// The log file will be rolled at that 20 hour mark.
-// A new log file will be created, and the 24 hour timer will be restarted.
-//
-// logFileManager
-// Allows you to retrieve the list of log files,
-// and configure the maximum number of archived log files to keep.
-
-@property (readwrite, assign) unsigned long long maximumFileSize;
-
-@property (readwrite, assign) NSTimeInterval rollingFrequency;
-
-@property (nonatomic, readonly) id <DDLogFileManager> logFileManager;
-
-
-// You can optionally force the current log file to be rolled with this method.
-
-- (void)rollLogFile;
-
-// Inherited from DDAbstractLogger
-
-// - (id <DDLogFormatter>)logFormatter;
-// - (void)setLogFormatter:(id <DDLogFormatter>)formatter;
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// DDLogFileInfo is a simple class that provides access to various file attributes.
-// It provides good performance as it only fetches the information if requested,
-// and it caches the information to prevent duplicate fetches.
-//
-// It was designed to provide quick snapshots of the current state of log files,
-// and to help sort log files in an array.
-//
-// This class does not monitor the files, or update it's cached attribute values if the file changes on disk.
-// This is not what the class was designed for.
-//
-// If you absolutely must get updated values,
-// you can invoke the reset method which will clear the cache.
-
-@interface DDLogFileInfo : NSObject
-{
- NSString *filePath;
- NSString *fileName;
-
- NSDictionary *fileAttributes;
-
- NSDate *creationDate;
- NSDate *modificationDate;
-
- unsigned long long fileSize;
-}
-
-@property (nonatomic, readonly) NSString *filePath;
-@property (nonatomic, readonly) NSString *fileName;
-
-@property (nonatomic, readonly) NSDictionary *fileAttributes;
-
-@property (nonatomic, readonly) NSDate *creationDate;
-@property (nonatomic, readonly) NSDate *modificationDate;
-
-@property (nonatomic, readonly) unsigned long long fileSize;
-
-@property (nonatomic, readonly) NSTimeInterval age;
-
-@property (nonatomic, readwrite) BOOL isArchived;
-
-+ (id)logFileWithPath:(NSString *)filePath;
-
-- (id)initWithFilePath:(NSString *)filePath;
-
-- (void)reset;
-- (void)renameFile:(NSString *)newFileName;
-
-#if TARGET_IPHONE_SIMULATOR
-
-// So here's the situation.
-// Extended attributes are perfect for what we're trying to do here (marking files as archived).
-// This is exactly what extended attributes were designed for.
-//
-// But Apple screws us over on the simulator.
-// Everytime you build-and-go, they copy the application into a new folder on the hard drive,
-// and as part of the process they strip extended attributes from our log files.
-// Normally, a copy of a file preserves extended attributes.
-// So obviously Apple has gone to great lengths to piss us off.
-//
-// Thus we use a slightly different tactic for marking log files as archived in the simulator.
-// That way it "just works" and there's no confusion when testing.
-//
-// The difference in method names is indicative of the difference in functionality.
-// On the simulator we add an attribute by appending a filename extension.
-//
-// For example:
-// log-ABC123.txt -> log-ABC123.archived.txt
-
-- (BOOL)hasExtensionAttributeWithName:(NSString *)attrName;
-
-- (void)addExtensionAttributeWithName:(NSString *)attrName;
-- (void)removeExtensionAttributeWithName:(NSString *)attrName;
-
-#else
-
-// Normal use of extended attributes used everywhere else,
-// such as on Macs and on iPhone devices.
-
-- (BOOL)hasExtendedAttributeWithName:(NSString *)attrName;
-
-- (void)addExtendedAttributeWithName:(NSString *)attrName;
-- (void)removeExtendedAttributeWithName:(NSString *)attrName;
-
-#endif
-
-- (NSComparisonResult)reverseCompareByCreationDate:(DDLogFileInfo *)another;
-- (NSComparisonResult)reverseCompareByModificationDate:(DDLogFileInfo *)another;
-
-@end
View
1,469 Common/ThirdParty/CocoaLumberjack/DDFileLogger.m
@@ -1,1469 +0,0 @@
-#import "DDFileLogger.h"
-
-#import <unistd.h>
-#import <sys/attr.h>
-#import <sys/xattr.h>
-#import <libkern/OSAtomic.h>
-
-// We probably shouldn't be using DDLog() statements within the DDLog implementation.
-// But we still want to leave our log statements for any future debugging,
-// and to allow other developers to trace the implementation (which is a great learning tool).
-//
-// So we use primitive logging macros around NSLog.
-// We maintain the NS prefix on the macros to be explicit about the fact that we're using NSLog.
-
-#define LOG_LEVEL 2
-
-#define NSLogError(frmt, ...) do{ if(LOG_LEVEL >= 1) NSLog((frmt), ##__VA_ARGS__); } while(0)
-#define NSLogWarn(frmt, ...) do{ if(LOG_LEVEL >= 2) NSLog((frmt), ##__VA_ARGS__); } while(0)
-#define NSLogInfo(frmt, ...) do{ if(LOG_LEVEL >= 3) NSLog((frmt), ##__VA_ARGS__); } while(0)
-#define NSLogVerbose(frmt, ...) do{ if(LOG_LEVEL >= 4) NSLog((frmt), ##__VA_ARGS__); } while(0)
-
-@interface DDLogFileManagerDefault (PrivateAPI)
-
-- (void)deleteOldLogFiles;
-
-@end
-
-@interface DDFileLogger (PrivateAPI)
-
-#if GCD_MAYBE_UNAVAILABLE
-
-- (void)lt_getMaximumFileSize:(NSMutableArray *)resultHolder;
-- (void)lt_setMaximumFileSize:(NSNumber *)maximumFileSizeWrapper;
-
-- (void)lt_getRollingFrequency:(NSMutableArray *)resultHolder;
-- (void)lt_setRollingFrequency:(NSNumber *)rollingFrequencyWrapper;
-
-#endif
-
-- (void)rollLogFileNow;
-- (void)maybeRollLogFileDueToAge:(NSTimer *)aTimer;
-- (void)maybeRollLogFileDueToSize;
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation DDLogFileManagerDefault
-
-@synthesize maximumNumberOfLogFiles;
-
-
-- (id)init
-{
- if ((self = [super init]))
- {
- maximumNumberOfLogFiles = DEFAULT_LOG_MAX_NUM_LOG_FILES;
-
- NSKeyValueObservingOptions kvoOptions = NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew;
-
- [self addObserver:self forKeyPath:@"maximumNumberOfLogFiles" options:kvoOptions context:nil];
-
- NSLogVerbose(@"DDFileLogManagerDefault: logsDir:\n%@", [self logsDirectory]);
- NSLogVerbose(@"DDFileLogManagerDefault: sortedLogFileNames:\n%@", [self sortedLogFileNames]);
- }
- return self;
-}
-
-- (void)dealloc
-{
- [super dealloc];
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark Configuration
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-- (void)observeValueForKeyPath:(NSString *)keyPath
- ofObject:(id)object
- change:(NSDictionary *)change
- context:(void *)context
-{
- NSNumber *old = [change objectForKey:NSKeyValueChangeOldKey];
- NSNumber *new = [change objectForKey:NSKeyValueChangeNewKey];
-
- if ([old isEqual:new])
- {
- // No change in value - don't bother with any processing.
- return;
- }
-
- if ([keyPath isEqualToString:@"maximumNumberOfLogFiles"])
- {
- NSLogInfo(@"DDFileLogManagerDefault: Responding to configuration change: maximumNumberOfLogFiles");
-
- if (IS_GCD_AVAILABLE)
- {
- #if GCD_MAYBE_AVAILABLE
-
- dispatch_block_t block = ^{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- [self deleteOldLogFiles];
-
- [pool release];
- };
-
- dispatch_async([DDLog loggingQueue], block);
-
- #endif
- }
- else
- {
- #if GCD_MAYBE_UNAVAILABLE
-
- [self performSelector:@selector(deleteOldLogFiles)
- onThread:[DDLog loggingThread]
- withObject:nil
- waitUntilDone:NO];
-
- #endif
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark File Deleting
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Deletes archived log files that exceed the maximumNumberOfLogFiles configuration value.
-**/
-- (void)deleteOldLogFiles
-{
- NSLogVerbose(@"DDLogFileManagerDefault: deleteOldLogFiles");
-
- NSArray *sortedLogFileInfos = [self sortedLogFileInfos];
-
- NSUInteger maxNumLogFiles = self.maximumNumberOfLogFiles;
-
- // Do we consider the first file?
- // We are only supposed to be deleting archived files.
- // In most cases, the first file is likely the log file that is currently being written to.
- // So in most cases, we do not want to consider this file for deletion.
-
- NSUInteger count = [sortedLogFileInfos count];
- BOOL excludeFirstFile = NO;
-
- if (count > 0)
- {
- DDLogFileInfo *logFileInfo = [sortedLogFileInfos objectAtIndex:0];
-
- if (!logFileInfo.isArchived)
- {
- excludeFirstFile = YES;
- }
- }
-
- NSArray *sortedArchivedLogFileInfos;
- if (excludeFirstFile)
- {
- count--;
- sortedArchivedLogFileInfos = [sortedLogFileInfos subarrayWithRange:NSMakeRange(1, count)];
- }
- else
- {
- sortedArchivedLogFileInfos = sortedLogFileInfos;
- }
-
- for (NSUInteger i = 0; i < count; i++)
- {
- if (i >= maxNumLogFiles)
- {
- DDLogFileInfo *logFileInfo = [sortedArchivedLogFileInfos objectAtIndex:i];
-
- NSLogInfo(@"DDLogFileManagerDefault: Deleting file: %@", logFileInfo.fileName);
-
- [[NSFileManager defaultManager] removeItemAtPath:logFileInfo.filePath error:nil];
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark Log Files
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Returns the path to the logs directory.
- * If the logs directory doesn't exist, this method automatically creates it.
-**/
-- (NSString *)logsDirectory
-{
-#if TARGET_OS_IPHONE
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *baseDir = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
-#else
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
- NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory();
-
- NSString *appName = [[NSProcessInfo processInfo] processName];
-
- NSString *baseDir = [basePath stringByAppendingPathComponent:appName];
-#endif
-
- NSString *logsDir = [baseDir stringByAppendingPathComponent:@"Logs"];
-
- if(![[NSFileManager defaultManager] fileExistsAtPath:logsDir])
- {
- NSError *err = nil;
- if(![[NSFileManager defaultManager] createDirectoryAtPath:logsDir
- withIntermediateDirectories:YES attributes:nil error:&err])
- {
- NSLogError(@"DDFileLogManagerDefault: Error creating logsDirectory: %@", err);
- }
- }
-
- return logsDir;
-}
-
-- (BOOL)isLogFile:(NSString *)fileName
-{
- // A log file has a name like "log-<uuid>.txt", where <uuid> is a HEX-string of 6 characters.
- //
- // For example: log-DFFE99.txt
-
- BOOL hasProperPrefix = [fileName hasPrefix:@"log-"];
-
- BOOL hasProperLength = [fileName length] >= 10;
-
-
- if (hasProperPrefix && hasProperLength)
- {
- NSCharacterSet *hexSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEF"];
-
- NSString *hex = [fileName substringWithRange:NSMakeRange(4, 6)];
- NSString *nohex = [hex stringByTrimmingCharactersInSet:hexSet];
-
- if ([nohex length] == 0)
- {
- return YES;
- }
- }
-
- return NO;
-}
-
-/**
- * Returns an array of NSString objects,
- * each of which is the filePath to an existing log file on disk.
-**/
-- (NSArray *)unsortedLogFilePaths
-{
- NSString *logsDirectory = [self logsDirectory];
-
- NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:logsDirectory error:nil];
-
- NSMutableArray *unsortedLogFilePaths = [NSMutableArray arrayWithCapacity:[fileNames count]];
-
- for (NSString *fileName in fileNames)
- {
- // Filter out any files that aren't log files. (Just for extra safety)
-
- if ([self isLogFile:fileName])
- {
- NSString *filePath = [logsDirectory stringByAppendingPathComponent:fileName];
-
- [unsortedLogFilePaths addObject:filePath];
- }
- }
-
- return unsortedLogFilePaths;
-}
-
-/**
- * Returns an array of NSString objects,
- * each of which is the fileName of an existing log file on disk.
-**/
-- (NSArray *)unsortedLogFileNames
-{
- NSArray *unsortedLogFilePaths = [self unsortedLogFilePaths];
-
- NSMutableArray *unsortedLogFileNames = [NSMutableArray arrayWithCapacity:[unsortedLogFilePaths count]];
-
- for (NSString *filePath in unsortedLogFilePaths)
- {
- [unsortedLogFileNames addObject:[filePath lastPathComponent]];
- }
-
- return unsortedLogFileNames;
-}
-
-/**
- * Returns an array of DDLogFileInfo objects,
- * each representing an existing log file on disk,
- * and containing important information about the log file such as it's modification date and size.
-**/
-- (NSArray *)unsortedLogFileInfos
-{
- NSArray *unsortedLogFilePaths = [self unsortedLogFilePaths];
-
- NSMutableArray *unsortedLogFileInfos = [NSMutableArray arrayWithCapacity:[unsortedLogFilePaths count]];
-
- for (NSString *filePath in unsortedLogFilePaths)
- {
- DDLogFileInfo *logFileInfo = [[DDLogFileInfo alloc] initWithFilePath:filePath];
-
- [unsortedLogFileInfos addObject:logFileInfo];
- [logFileInfo release];
- }
-
- return unsortedLogFileInfos;
-}
-
-/**
- * Just like the unsortedLogFilePaths method, but sorts the array.
- * The items in the array are sorted by modification date.
- * The first item in the array will be the most recently modified log file.
-**/
-- (NSArray *)sortedLogFilePaths
-{
- NSArray *sortedLogFileInfos = [self sortedLogFileInfos];
-
- NSMutableArray *sortedLogFilePaths = [NSMutableArray arrayWithCapacity:[sortedLogFileInfos count]];
-
- for (DDLogFileInfo *logFileInfo in sortedLogFileInfos)
- {
- [sortedLogFilePaths addObject:[logFileInfo filePath]];
- }
-
- return sortedLogFilePaths;
-}
-
-/**
- * Just like the unsortedLogFileNames method, but sorts the array.
- * The items in the array are sorted by modification date.
- * The first item in the array will be the most recently modified log file.
-**/
-- (NSArray *)sortedLogFileNames
-{
- NSArray *sortedLogFileInfos = [self sortedLogFileInfos];
-
- NSMutableArray *sortedLogFileNames = [NSMutableArray arrayWithCapacity:[sortedLogFileInfos count]];
-
- for (DDLogFileInfo *logFileInfo in sortedLogFileInfos)
- {
- [sortedLogFileNames addObject:[logFileInfo fileName]];
- }
-
- return sortedLogFileNames;
-}
-
-/**
- * Just like the unsortedLogFileInfos method, but sorts the array.
- * The items in the array are sorted by modification date.
- * The first item in the array will be the most recently modified log file.
-**/
-- (NSArray *)sortedLogFileInfos
-{
- return [[self unsortedLogFileInfos] sortedArrayUsingSelector:@selector(reverseCompareByCreationDate:)];
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark Creation
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Generates a short UUID suitable for use in the log file's name.
- * The result will have six characters, all in the hexadecimal set [0123456789ABCDEF].
-**/
-- (NSString *)generateShortUUID
-{
- CFUUIDRef uuid = CFUUIDCreate(NULL);
-
- CFStringRef fullStr = CFUUIDCreateString(NULL, uuid);
- CFStringRef shortStr = CFStringCreateWithSubstring(NULL, fullStr, CFRangeMake(0, 6));
-
- CFRelease(fullStr);
- CFRelease(uuid);
-
- return [NSMakeCollectable(shortStr) autorelease];
-}
-
-/**
- * Generates a new unique log file path, and creates the corresponding log file.
-**/
-- (NSString *)createNewLogFile
-{
- // Generate a random log file name, and create the file (if there isn't a collision)
-
- NSString *logsDirectory = [self logsDirectory];
- do
- {
- NSString *fileName = [NSString stringWithFormat:@"log-%@.txt", [self generateShortUUID]];
-
- NSString *filePath = [logsDirectory stringByAppendingPathComponent:fileName];
-
- if (![[NSFileManager defaultManager] fileExistsAtPath:filePath])
- {
- NSLogVerbose(@"DDLogFileManagerDefault: Creating new log file: %@", fileName);
-
- [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
-
- // Since we just created a new log file, we may need to delete some old log files
- [self deleteOldLogFiles];
-
- return filePath;
- }
-
- } while(YES);
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation DDLogFileFormatterDefault
-
-- (id)init
-{
- if((self = [super init]))
- {
- dateFormatter = [[NSDateFormatter alloc] init];
- [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
- [dateFormatter setDateFormat:@"yyyy/MM/dd HH:mm:ss:SSS"];
- }
- return self;
-}
-
-- (NSString *)formatLogMessage:(DDLogMessage *)logMessage
-{
- NSString *dateAndTime = [dateFormatter stringFromDate:(logMessage->timestamp)];
-
- return [NSString stringWithFormat:@"%@ %@", dateAndTime, logMessage->logMsg];
-}
-
-- (void)dealloc
-{
- [dateFormatter release];
- [super dealloc];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation DDFileLogger
-
-@synthesize maximumFileSize;
-@synthesize rollingFrequency;
-@synthesize logFileManager;
-
-- (id)init
-{
- DDLogFileManagerDefault *defaultLogFileManager = [[[DDLogFileManagerDefault alloc] init] autorelease];
-
- return [self initWithLogFileManager:defaultLogFileManager];
-}
-
-- (id)initWithLogFileManager:(id <DDLogFileManager>)aLogFileManager
-{
- if ((self = [super init]))
- {
- maximumFileSize = DEFAULT_LOG_MAX_FILE_SIZE;
- rollingFrequency = DEFAULT_LOG_ROLLING_FREQUENCY;
-
- logFileManager = [aLogFileManager retain];
-
- formatter = [[DDLogFileFormatterDefault alloc] init];
- }
- return self;
-}
-
-- (void)dealloc
-{
- [formatter release];
- [logFileManager release];
-
- [currentLogFileInfo release];
-
- [currentLogFileHandle synchronizeFile];
- [currentLogFileHandle closeFile];
- [currentLogFileHandle release];
-
- [rollingTimer invalidate];
- [rollingTimer release];
-
- [super dealloc];
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark Configuration
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-- (unsigned long long)maximumFileSize
-{
- // The design of this method is taken from the DDAbstractLogger implementation.
- // For documentation please refer to the DDAbstractLogger implementation.
-
- // Note: The internal implementation should access the maximumFileSize variable directly,
- // but if we forget to do this, then this method should at least work properly.
-
- if (IS_GCD_AVAILABLE)
- {
- #if GCD_MAYBE_AVAILABLE
-
- if (dispatch_get_current_queue() == loggerQueue)
- {
- return maximumFileSize;
- }
-
- __block unsigned long long result;
-
- dispatch_block_t block = ^{
- result = maximumFileSize;
- };
- dispatch_sync([DDLog loggingQueue], block);
-
- return result;
-
- #endif
- }
- else
- {
- #if GCD_MAYBE_UNAVAILABLE
-
- NSThread *loggingThread = [DDLog loggingThread];
-
- if ([NSThread currentThread] == loggingThread)
- {
- return maximumFileSize;
- }
-
- unsigned long long result;
- NSMutableArray *resultHolder = [[NSMutableArray alloc] init];
-
- [self performSelector:@selector(lt_getMaximumFileSize:)
- onThread:loggingThread
- withObject:resultHolder
- waitUntilDone:YES];
-
- OSMemoryBarrier();
-
- result = [[resultHolder objectAtIndex:0] unsignedLongLongValue];
- [resultHolder release];
-
- return result;
-
- #endif
- }
-}
-
-- (void)setMaximumFileSize:(unsigned long long)newMaximumFileSize
-{
- // The design of this method is taken from the DDAbstractLogger implementation.
- // For documentation please refer to the DDAbstractLogger implementation.
-
- if (IS_GCD_AVAILABLE)
- {
- #if GCD_MAYBE_AVAILABLE
-
- dispatch_block_t block = ^{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- maximumFileSize = newMaximumFileSize;
- [self maybeRollLogFileDueToSize];
-
- [pool release];
- };
-
- if (dispatch_get_current_queue() == loggerQueue)
- block();
- else
- dispatch_async([DDLog loggingQueue], block);
-
- #endif
- }
- else
- {
- #if GCD_MAYBE_UNAVAILABLE
-
- NSThread *loggingThread = [DDLog loggingThread];
- NSNumber *newMaximumFileSizeWrapper = [NSNumber numberWithUnsignedLongLong:newMaximumFileSize];
-
- if ([NSThread currentThread] == loggingThread)
- {
- [self lt_setMaximumFileSize:newMaximumFileSizeWrapper];
- }
- else
- {
- [self performSelector:@selector(lt_setMaximumFileSize:)
- onThread:loggingThread
- withObject:newMaximumFileSizeWrapper
- waitUntilDone:NO];
- }
-
- #endif
- }
-}
-
-- (NSTimeInterval)rollingFrequency
-{
- // The design of this method is taken from the DDAbstractLogger implementation.
- // For documentation please refer to the DDAbstractLogger implementation.
-
- // Note: The internal implementation should access the rollingFrequency variable directly,
- // but if we forget to do this, then this method should at least work properly.
-
- if (IS_GCD_AVAILABLE)
- {
- #if GCD_MAYBE_AVAILABLE
-
- if (dispatch_get_current_queue() == loggerQueue)
- {
- return rollingFrequency;
- }
-
- __block NSTimeInterval result;
-
- dispatch_block_t block = ^{
- result = rollingFrequency;
- };
- dispatch_sync([DDLog loggingQueue], block);
-
- return result;
-
- #endif
- }
- else
- {
- #if GCD_MAYBE_UNAVAILABLE
-
- NSThread *loggingThread = [DDLog loggingThread];
-
- if ([NSThread currentThread] == loggingThread)
- {
- return rollingFrequency;
- }
-
- NSTimeInterval result;
- NSMutableArray *resultHolder = [[NSMutableArray alloc] init];
-
- [self performSelector:@selector(lt_getRollingFrequency:)
- onThread:loggingThread
- withObject:resultHolder
- waitUntilDone:YES];
-
- OSMemoryBarrier();
-
- result = [[resultHolder objectAtIndex:0] doubleValue];
- [resultHolder release];
-
- return result;
-
- #endif
- }
-}
-
-- (void)setRollingFrequency:(NSTimeInterval)newRollingFrequency
-{
- // The design of this method is taken from the DDAbstractLogger implementation.
- // For documentation please refer to the DDAbstractLogger implementation.
-
- if (IS_GCD_AVAILABLE)
- {
- #if GCD_MAYBE_AVAILABLE
-
- dispatch_block_t block = ^{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- rollingFrequency = newRollingFrequency;
- [self maybeRollLogFileDueToAge:nil];
-
- [pool release];
- };
-
- if (dispatch_get_current_queue() == loggerQueue)
- block();
- else
- dispatch_async([DDLog loggingQueue], block);
-
- #endif
- }
- else
- {
- #if GCD_MAYBE_UNAVAILABLE
-
- NSThread *loggingThread = [DDLog loggingThread];
- NSNumber *newMaximumRollingFrequencyWrapper = [NSNumber numberWithDouble:newRollingFrequency];
-
- if ([NSThread currentThread] == loggingThread)
- {
- [self lt_setRollingFrequency:newMaximumRollingFrequencyWrapper];
- }
- else
- {
- [self performSelector:@selector(lt_setRollingFrequency:)
- onThread:loggingThread
- withObject:newMaximumRollingFrequencyWrapper
- waitUntilDone:NO];
- }
-
- #endif
- }
-}
-
-#if GCD_MAYBE_UNAVAILABLE
-
-- (void)lt_getMaximumFileSize:(NSMutableArray *)resultHolder
-{
- // This method is executed on the logging thread.
-
- [resultHolder addObject:[NSNumber numberWithUnsignedLongLong:maximumFileSize]];
- OSMemoryBarrier();
-}
-
-- (void)lt_setMaximumFileSize:(NSNumber *)maximumFileSizeWrapper
-{
- // This method is executed on the logging thread.
-
- maximumFileSize = [maximumFileSizeWrapper unsignedLongLongValue];
-
- [self maybeRollLogFileDueToSize];
-}
-
-- (void)lt_getRollingFrequency:(NSMutableArray *)resultHolder
-{
- // This method is executed on the logging thread.
-
- [resultHolder addObject:[NSNumber numberWithDouble:rollingFrequency]];
- OSMemoryBarrier();
-}
-
-- (void)lt_setRollingFrequency:(NSNumber *)rollingFrequencyWrapper
-{
- // This method is executed on the logging thread.
-
- rollingFrequency = [rollingFrequencyWrapper doubleValue];
-
- [self maybeRollLogFileDueToAge:nil];
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark File Rolling
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-- (void)scheduleTimerToRollLogFileDueToAge
-{
- if (rollingTimer)
- {
- [rollingTimer invalidate];
- [rollingTimer release];
- rollingTimer = nil;
- }
-
- if (currentLogFileInfo == nil)
- {
- return;
- }
-
- NSDate *logFileCreationDate = [currentLogFileInfo creationDate];
-
- NSTimeInterval ti = [logFileCreationDate timeIntervalSinceReferenceDate];
- ti += rollingFrequency;
-
- NSDate *logFileRollingDate = [NSDate dateWithTimeIntervalSinceReferenceDate:ti];
-
- NSLogVerbose(@"DDFileLogger: scheduleTimerToRollLogFileDueToAge");
-
- NSLogVerbose(@"DDFileLogger: logFileCreationDate: %@", logFileCreationDate);
- NSLogVerbose(@"DDFileLogger: logFileRollingDate : %@", logFileRollingDate);
-
- rollingTimer = [[NSTimer scheduledTimerWithTimeInterval:[logFileRollingDate timeIntervalSinceNow]
- target:self
- selector:@selector(maybeRollLogFileDueToAge:)
- userInfo:nil
- repeats:NO] retain];
-}
-
-- (void)rollLogFile
-{
- // This method is public.
- // We need to execute the rolling on our logging thread/queue.
-
- if (IS_GCD_AVAILABLE)
- {
- #if GCD_MAYBE_AVAILABLE
-
- dispatch_block_t block = ^{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [self rollLogFileNow];
- [pool release];
- };
- dispatch_async([DDLog loggingQueue], block);
-
- #endif
- }
- else
- {
- #if GCD_MAYBE_UNAVAILABLE
-
- [self performSelector:@selector(rollLogFileNow)
- onThread:[DDLog loggingThread]
- withObject:nil
- waitUntilDone:NO];
-
- #endif
- }
-}
-
-- (void)rollLogFileNow
-{
- NSLogVerbose(@"DDFileLogger: rollLogFileNow");
-
- [currentLogFileHandle synchronizeFile];
- [currentLogFileHandle closeFile];
- [currentLogFileHandle release];
- currentLogFileHandle = nil;
-
- currentLogFileInfo.isArchived = YES;
-
- if ([logFileManager respondsToSelector:@selector(didRollAndArchiveLogFile:)])
- {
- [logFileManager didRollAndArchiveLogFile:(currentLogFileInfo.filePath)];
- }
-
- [currentLogFileInfo release];
- currentLogFileInfo = nil;
-}
-
-- (void)maybeRollLogFileDueToAge:(NSTimer *)aTimer
-{
- if (currentLogFileInfo.age >= rollingFrequency)
- {
- NSLogVerbose(@"DDFileLogger: Rolling log file due to age...");
-
- [self rollLogFileNow];
- }
- else
- {
- [self scheduleTimerToRollLogFileDueToAge];
- }
-}
-
-- (void)maybeRollLogFileDueToSize
-{
- // This method is called from logMessage.
- // Keep it FAST.
-
- unsigned long long fileSize = [currentLogFileHandle offsetInFile];
-
- // Note: Use direct access to maximumFileSize variable.
- // We specifically wrote our own getter/setter method to allow us to do this (for performance reasons).
-
- if (fileSize >= maximumFileSize) // YES, we are using direct access. Read note above.
- {
- NSLogVerbose(@"DDFileLogger: Rolling log file due to size...");
-
- [self rollLogFileNow];
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark File Logging
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Returns the log file that should be used.
- * If there is an existing log file that is suitable,
- * within the constraints of maximumFileSize and rollingFrequency, then it is returned.
- *
- * Otherwise a new file is created and returned.
-**/
-- (DDLogFileInfo *)currentLogFileInfo
-{
- if (currentLogFileInfo == nil)
- {
- NSArray *sortedLogFileInfos = [logFileManager sortedLogFileInfos];
-
- if ([sortedLogFileInfos count] > 0)
- {
- DDLogFileInfo *mostRecentLogFileInfo = [sortedLogFileInfos objectAtIndex:0];
-
- BOOL useExistingLogFile = YES;
- BOOL shouldArchiveMostRecent = NO;
-
- if (mostRecentLogFileInfo.isArchived)
- {
- useExistingLogFile = NO;
- shouldArchiveMostRecent = NO;
- }
- else if (mostRecentLogFileInfo.fileSize >= maximumFileSize)
- {
- useExistingLogFile = NO;
- shouldArchiveMostRecent = YES;
- }
- else if (mostRecentLogFileInfo.age >= rollingFrequency)
- {
- useExistingLogFile = NO;
- shouldArchiveMostRecent = YES;
- }
-
- if (useExistingLogFile)
- {
- NSLogVerbose(@"DDFileLogger: Resuming logging with file %@", mostRecentLogFileInfo.fileName);
-
- currentLogFileInfo = [mostRecentLogFileInfo retain];
- }
- else
- {
- if (shouldArchiveMostRecent)
- {
- mostRecentLogFileInfo.isArchived = YES;
-
- if ([logFileManager respondsToSelector:@selector(didArchiveLogFile:)])
- {
- [logFileManager didArchiveLogFile:(mostRecentLogFileInfo.filePath)];
- }
- }
- }
- }
-
- if (currentLogFileInfo == nil)
- {
- NSString *currentLogFilePath = [logFileManager createNewLogFile];
-
- currentLogFileInfo = [[DDLogFileInfo alloc] initWithFilePath:currentLogFilePath];
- }
- }
-
- return currentLogFileInfo;
-}
-
-- (NSFileHandle *)currentLogFileHandle
-{
- if (currentLogFileHandle == nil)
- {
- NSString *logFilePath = [[self currentLogFileInfo] filePath];
-
- currentLogFileHandle = [[NSFileHandle fileHandleForWritingAtPath:logFilePath] retain];
- [currentLogFileHandle seekToEndOfFile];
-
- if (currentLogFileHandle)
- {
- [self scheduleTimerToRollLogFileDueToAge];
- }
- }
-
- return currentLogFileHandle;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark DDLogger Protocol
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-- (void)logMessage:(DDLogMessage *)logMessage
-{
- NSString *logMsg = logMessage->logMsg;
-
- if (formatter)
- {
- logMsg = [formatter formatLogMessage:logMessage];
- }
-
- if (logMsg)
- {
- if (![logMsg hasSuffix:@"\n"])
- {
- logMsg = [logMsg stringByAppendingString:@"\n"];
- }
-
- NSData *logData = [logMsg dataUsingEncoding:NSUTF8StringEncoding];
-
- [[self currentLogFileHandle] writeData:logData];
-
- [self maybeRollLogFileDueToSize];
- }
-}
-
-- (NSString *)loggerName
-{
- return @"cocoa.lumberjack.fileLogger";
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#if TARGET_IPHONE_SIMULATOR
- #define XATTR_ARCHIVED_NAME @"archived"
-#else
- #define XATTR_ARCHIVED_NAME @"lumberjack.log.archived"
-#endif
-
-@implementation DDLogFileInfo
-
-@synthesize filePath;
-
-@dynamic fileName;
-@dynamic fileAttributes;
-@dynamic creationDate;
-@dynamic modificationDate;
-@dynamic fileSize;
-@dynamic age;
-
-@dynamic isArchived;
-
-
-#pragma mark Lifecycle
-
-+ (id)logFileWithPath:(NSString *)aFilePath
-{
- return [[[DDLogFileInfo alloc] initWithFilePath:aFilePath] autorelease];
-}
-
-- (id)initWithFilePath:(NSString *)aFilePath
-{
- if ((self = [super init]))
- {
- filePath = [aFilePath copy];
- }
- return self;
-}
-
-- (void)dealloc
-{
- [filePath release];
- [fileName release];
-
- [fileAttributes release];
-
- [creationDate release];
- [modificationDate release];
-
- [super dealloc];
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark Standard Info
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-- (NSDictionary *)fileAttributes
-{
- if (fileAttributes == nil)
- {
- fileAttributes = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil] retain];
- }
- return fileAttributes;
-}
-
-- (NSString *)fileName
-{
- if (fileName == nil)
- {
- fileName = [[filePath lastPathComponent] retain];
- }
- return fileName;
-}
-
-- (NSDate *)modificationDate
-{
- if (modificationDate == nil)
- {
- modificationDate = [[[self fileAttributes] objectForKey:NSFileModificationDate] retain];
- }
-
- return modificationDate;
-}
-
-- (NSDate *)creationDate
-{
- if (creationDate == nil)
- {
-
- #if TARGET_OS_IPHONE
-
- const char *path = [filePath UTF8String];
-
- struct attrlist attrList;
- memset(&attrList, 0, sizeof(attrList));
- attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
- attrList.commonattr = ATTR_CMN_CRTIME;
-
- struct {
- u_int32_t attrBufferSizeInBytes;
- struct timespec crtime;
- } attrBuffer;
-
- int result = getattrlist(path, &attrList, &attrBuffer, sizeof(attrBuffer), 0);
- if (result == 0)
- {
- double seconds = (double)(attrBuffer.crtime.tv_sec);
- double nanos = (double)(attrBuffer.crtime.tv_nsec);
-
- NSTimeInterval ti = seconds + (nanos / 1000000000.0);
-
- creationDate = [[NSDate dateWithTimeIntervalSince1970:ti] retain];
- }
- else
- {
- NSLogError(@"DDLogFileInfo: creationDate(%@): getattrlist result = %i", self.fileName, result);
- }
-
- #else
-
- creationDate = [[[self fileAttributes] objectForKey:NSFileCreationDate] retain];
-
- #endif
-
- }
- return creationDate;
-}
-
-- (unsigned long long)fileSize
-{
- if (fileSize == 0)
- {
- fileSize = [[[self fileAttributes] objectForKey:NSFileSize] unsignedLongLongValue];
- }
-
- return fileSize;
-}
-
-- (NSTimeInterval)age
-{
- return [[self creationDate] timeIntervalSinceNow] * -1.0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark Archiving
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-- (BOOL)isArchived
-{
-
-#if TARGET_IPHONE_SIMULATOR
-
- // Extended attributes don't work properly on the simulator.
- // So we have to use a less attractive alternative.
- // See full explanation in the header file.
-
- return [self hasExtensionAttributeWithName:XATTR_ARCHIVED_NAME];
-
-#else
-
- return [self hasExtendedAttributeWithName:XATTR_ARCHIVED_NAME];
-
-#endif
-}
-
-- (void)setIsArchived:(BOOL)flag
-{
-
-#if TARGET_IPHONE_SIMULATOR
-
- // Extended attributes don't work properly on the simulator.
- // So we have to use a less attractive alternative.
- // See full explanation in the header file.
-
- if (flag)
- [self addExtensionAttributeWithName:XATTR_ARCHIVED_NAME];
- else
- [self removeExtensionAttributeWithName:XATTR_ARCHIVED_NAME];
-
-#else
-
- if (flag)
- [self addExtendedAttributeWithName:XATTR_ARCHIVED_NAME];
- else
- [self removeExtendedAttributeWithName:XATTR_ARCHIVED_NAME];
-
-#endif
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark Changes
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-- (void)reset
-{
- [fileName release];
- fileName = nil;
-
- [fileAttributes release];
- fileAttributes = nil;
-
- [creationDate release];
- creationDate = nil;
-
- [modificationDate release];
- modificationDate = nil;
-}
-
-- (void)renameFile:(NSString *)newFileName
-{
- // This method is only used on the iPhone simulator, where normal extended attributes are broken.
- // See full explanation in the header file.
-
- if (![newFileName isEqualToString:[self fileName]])
- {
- NSString *fileDir = [filePath stringByDeletingLastPathComponent];
-
- NSString *newFilePath = [fileDir stringByAppendingPathComponent:newFileName];
-
- NSLogVerbose(@"DDLogFileInfo: Renaming file: '%@' -> '%@'", self.fileName, newFileName);
-
- NSError *error = nil;
- if (![[NSFileManager defaultManager] moveItemAtPath:filePath toPath:newFilePath error:&error])
- {
- NSLogError(@"DDLogFileInfo: Error renaming file (%@): %@", self.fileName, error);
- }
-
- [filePath release];
- filePath = [newFilePath retain];
-
- [self reset];
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark Attribute Management
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#if TARGET_IPHONE_SIMULATOR
-
-// Extended attributes don't work properly on the simulator.
-// So we have to use a less attractive alternative.
-// See full explanation in the header file.
-
-- (BOOL)hasExtensionAttributeWithName:(NSString *)attrName
-{
- // This method is only used on the iPhone simulator, where normal extended attributes are broken.
- // See full explanation in the header file.
-
- // Split the file name into components.
- //
- // log-ABC123.archived.uploaded.txt
- //
- // 0. log-ABC123
- // 1. archived
- // 2. uploaded
- // 3. txt
- //
- // So we want to search for the attrName in the components (ignoring the first and last array indexes).
-
- NSArray *components = [[self fileName] componentsSeparatedByString:@"."];
-
- // Watch out for file names without an extension
-
- NSUInteger count = [components count];
- NSUInteger max = (count >= 2) ? count-1 : count;
-
- NSUInteger i;
- for (i = 1; i < max; i++)
- {
- NSString *attr = [components objectAtIndex:i];
-
- if ([attrName isEqualToString:attr])
- {
- return YES;
- }
- }
-
- return NO;
-}
-
-- (void)addExtensionAttributeWithName:(NSString *)attrName
-{
- // This method is only used on the iPhone simulator, where normal extended attributes are broken.
- // See full explanation in the header file.
-
- if ([attrName length] == 0) return;
-
- // Example:
- // attrName = "archived"
- //
- // "log-ABC123.txt" -> "log-ABC123.archived.txt"
-
- NSArray *components = [[self fileName] componentsSeparatedByString:@"."];
-
- NSUInteger count = [components count];
-
- NSUInteger estimatedNewLength = [[self fileName] length] + [attrName length] + 1;
- NSMutableString *newFileName = [NSMutableString stringWithCapacity:estimatedNewLength];
-
- if (count > 0)
- {
- [newFileName appendString:[components objectAtIndex:0]];
- }
-
- NSString *lastExt = @"";
-
- NSUInteger i;
- for (i = 1; i < count; i++)
- {
- NSString *attr = [components objectAtIndex:i];
- if ([attr length] == 0)
- {
- continue;
- }
-
- if ([attrName isEqualToString:attr])
- {
- // Extension attribute already exists in file name
- return;
- }
-
- if ([lastExt length] > 0)
- {
- [newFileName appendFormat:@".%@", lastExt];
- }
-
- lastExt = attr;
- }
-
- [newFileName appendFormat:@".%@", attrName];
-
- if ([lastExt length] > 0)
- {
- [newFileName appendFormat:@".%@", lastExt];
- }
-
- [self renameFile:newFileName];
-}
-
-- (void)removeExtensionAttributeWithName:(NSString *)attrName
-{
- // This method is only used on the iPhone simulator, where normal extended attributes are broken.
- // See full explanation in the header file.
-
- if ([attrName length] == 0) return;
-
- // Example:
- // attrName = "archived"
- //
- // "log-ABC123.txt" -> "log-ABC123.archived.txt"
-
- NSArray *components = [[self fileName] componentsSeparatedByString:@"."];
-
- NSUInteger count = [components count];
-
- NSUInteger estimatedNewLength = [[self fileName] length];
- NSMutableString *newFileName = [NSMutableString stringWithCapacity:estimatedNewLength];
-
- if (count > 0)
- {
- [newFileName appendString:[components objectAtIndex:0]];
- }
-
- BOOL found = NO;
-
- NSUInteger i;
- for (i = 1; i < count; i++)
- {
- NSString *attr = [components objectAtIndex:i];
-
- if ([attrName isEqualToString:attr])
- {
- found = YES;
- }
- else
- {
- [newFileName appendFormat:@".%@", attr];
- }
- }
-
- if (found)
- {
- [self renameFile:newFileName];
- }
-}
-
-#else
-
-- (BOOL)hasExtendedAttributeWithName:(NSString *)attrName
-{
- const char *path = [filePath UTF8String];
- const char *name = [attrName UTF8String];
-
- int result = getxattr(path, name, NULL, 0, 0, 0);
-
- return (result >= 0);
-}
-
-- (void)addExtendedAttributeWithName:(NSString *)attrName
-{
- const char *path = [filePath UTF8String];
- const char *name = [attrName UTF8String];
-
- int result = setxattr(path, name, NULL, 0, 0, 0);
-
- if (result < 0)
- {
- NSLogError(@"DDLogFileInfo: setxattr(%@, %@): error = %i", attrName, self.fileName, result);
- }
-}
-
-- (void)removeExtendedAttributeWithName:(NSString *)attrName
-{
- const char *path = [filePath UTF8String];
- const char *name = [attrName UTF8String];
-
- int result = removexattr(path, name, 0);
-
- if (result < 0 && errno != ENOATTR)
- {
- NSLogError(@"DDLogFileInfo: removexattr(%@, %@): error = %i", attrName, self.fileName, result);
- }
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark Comparisons
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-- (BOOL)isEqual:(id)object
-{
- if ([object isKindOfClass:[self class]])
- {
- DDLogFileInfo *another = (DDLogFileInfo *)object;
-
- return [filePath isEqualToString:[another filePath]];
- }
-
- return NO;
-}
-
-- (NSComparisonResult)reverseCompareByCreationDate:(DDLogFileInfo *)another
-{
- NSDate *us = [self creationDate];
- NSDate *them = [another creationDate];
-
- NSComparisonResult result = [us compare:them];
-
- if (result == NSOrderedAscending)
- return NSOrderedDescending;
-
- if (result == NSOrderedDescending)
- return NSOrderedAscending;
-
- return NSOrderedSame;
-}
-
-- (NSComparisonResult)reverseCompareByModificationDate:(DDLogFileInfo *)another
-{
- NSDate *us = [self modificationDate];
- NSDate *them = [another modificationDate];
-
- NSComparisonResult result = [us compare:them];
-
- if (result == NSOrderedAscending)
- return NSOrderedDescending;
-
- if (result == NSOrderedDescending)
- return NSOrderedAscending;
-
- return NSOrderedSame;
-}
-
-@end
View
529 Common/ThirdParty/CocoaLumberjack/DDLog.h
@@ -1,529 +0,0 @@
-#import <Foundation/Foundation.h>
-
-/**
- * Welcome to Cocoa Lumberjack!
- *
- * The Google Code page has a wealth of documentation if you have any questions.
- * http://code.google.com/p/cocoalumberjack/
- *
- * If you're new to the project you may wish to read the "Getting Started" page.
- * http://code.google.com/p/cocoalumberjack/wiki/GettingStarted
- *
- * Otherwise, here is a quick refresher.
- * There are three steps to using the macros:
- *
- * Step 1:
- * Import the header in your implementation file:
- *
- * #import "DDLog.h"
- *
- * Step 2:
- * Define your logging level in your implementation file:
- *
- * // Debug levels: off, error, warn, info, verbose
- * static const int ddLogLevel = LOG_LEVEL_VERBOSE;
- *
- * Step 3:
- * Replace your NSLog statements with DDLog statements according to the severity of the message.
- *
- * NSLog(@"Fatal error, no dohickey found!"); -> DDLogError(@"Fatal error, no dohickey found!");
- *
- * DDLog works exactly the same as NSLog.
- * This means you can pass it multiple variables just like NSLog.
-**/
-
-
-// Can we use Grand Central Dispatch?
-//
-// This question actually is actually composed of two parts:
-// 1. Is it available to the compiler?
-// 2. Is it available to the runtime?
-//
-// For example, if we are building a universal iPad/iPhone app,
-// our base SDK may be iOS 4, but our deployment target would be iOS 3.2.
-// In this case we can compile against the GCD libraries (which are available starting with iOS 4),
-// but we can only use them at runtime if running on iOS 4 or later.
-// If running on an iPad using iOS 3.2, we need to use runtime checks for backwards compatibility.
-//
-// The solution is to use a combination of compile-time and run-time macros.
-//
-// Note that when the minimum supported SDK supports GCD
-// the run-time checks will be compiled out during optimization.
-
-#if TARGET_OS_IPHONE
-
- // Compiling for iPod/iPhone/iPad
-
- #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000 // 4.0 supported
-
- #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 // 4.0 supported and required
-
- #define IS_GCD_AVAILABLE YES
- #define GCD_MAYBE_AVAILABLE 1
- #define GCD_MAYBE_UNAVAILABLE 0
-
- #else // 4.0 supported but not required
-
- #ifndef NSFoundationVersionNumber_iPhoneOS_4_0
- #define NSFoundationVersionNumber_iPhoneOS_4_0 751.32
- #endif
-
- #define IS_GCD_AVAILABLE (NSFoundationVersionNumber >= NSFoundationVersionNumber_iPhoneOS_4_0)
- #define GCD_MAYBE_AVAILABLE 1
- #define GCD_MAYBE_UNAVAILABLE 1
-
- #endif
-
- #else // 4.0 not supported
-
- #define IS_GCD_AVAILABLE NO
- #define GCD_MAYBE_AVAILABLE 0
- #define GCD_MAYBE_UNAVAILABLE 1
-
- #endif
-
-#else
-
- // Compiling for Mac OS X
-
- #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 // 10.6 supported
-
- #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 // 10.6 supported and required
-
- #define IS_GCD_AVAILABLE YES
- #define GCD_MAYBE_AVAILABLE 1
- #define GCD_MAYBE_UNAVAILABLE 0
-
- #else // 10.6 supported but not required
-
- #ifndef NSFoundationVersionNumber10_6
- #define NSFoundationVersionNumber10_6 751.00
- #endif
-
- #define IS_GCD_AVAILABLE (NSFoundationVersionNumber >= NSFoundationVersionNumber10_6)
- #define GCD_MAYBE_AVAILABLE 1
- #define GCD_MAYBE_UNAVAILABLE 1
-
- #endif
-
- #else // 10.6 not supported
-
- #define IS_GCD_AVAILABLE NO
- #define GCD_MAYBE_AVAILABLE 0
- #define GCD_MAYBE_UNAVAILABLE 1
-
- #endif
-
-#endif
-
-/*
-// Uncomment for quick temporary test to see if it builds for older OS targets
-#undef IS_GCD_AVAILABLE
-#undef GCD_MAYBE_AVAILABLE
-#undef GCD_MAYBE_UNAVAILABLE
-
-#define IS_GCD_AVAILABLE NO
-#define GCD_MAYBE_AVAILABLE 0
-#define GCD_MAYBE_UNAVAILABLE 1
-*/
-
-@class DDLogMessage;
-
-@protocol DDLogger;
-@protocol DDLogFormatter;
-
-/**
- * Define our big multiline macros so all the other macros will be easy to read.
-**/
-
-#define LOG_MACRO(isSynchronous, lvl, flg, fnct, frmt, ...) \
- [DDLog log:isSynchronous \
- level:lvl \
- flag:flg \
- file:__FILE__ \
- function:fnct \
- line:__LINE__ \
- format:(frmt), ##__VA_ARGS__]
-
-#define SYNC_LOG_OBJC_MACRO(lvl, flg, frmt, ...) LOG_MACRO(YES, lvl, flg, sel_getName(_cmd), frmt, ##__VA_ARGS__)
-#define ASYNC_LOG_OBJC_MACRO(lvl, flg, frmt, ...) LOG_MACRO( NO, lvl, flg, sel_getName(_cmd), frmt, ##__VA_ARGS__)
-
-#define SYNC_LOG_C_MACRO(lvl, flg, frmt, ...) LOG_MACRO(YES, lvl, flg, __FUNCTION__, frmt, ##__VA_ARGS__)
-#define ASYNC_LOG_C_MACRO(lvl, flg, frmt, ...) LOG_MACRO( NO, lvl, flg, __FUNCTION__, frmt, ##__VA_ARGS__)
-
-#define LOG_MAYBE(isSynchronous, lvl, flg, fnct, frmt, ...) \
- do { if(lvl & flg) LOG_MACRO(isSynchronous, lvl, flg, fnct, frmt, ##__VA_ARGS__); } while(0)
-
-#define SYNC_LOG_OBJC_MAYBE(lvl, flg, frmt, ...) LOG_MAYBE(YES, lvl, flg, sel_getName(_cmd), frmt, ##__VA_ARGS__)
-#define ASYNC_LOG_OBJC_MAYBE(lvl, flg, frmt, ...) LOG_MAYBE( NO, lvl, flg, sel_getName(_cmd), frmt, ##__VA_ARGS__)
-
-#define SYNC_LOG_C_MAYBE(lvl, flg, frmt, ...) LOG_MAYBE(YES, lvl, flg, __FUNCTION__, frmt, ##__VA_ARGS__)
-#define ASYNC_LOG_C_MAYBE(lvl, flg, frmt, ...) LOG_MAYBE( NO, lvl, flg, __FUNCTION__, frmt, ##__VA_ARGS__)
-
-/**
- * Define our standard log levels.
- *
- * We default to only 4 levels because it makes it easier for beginners
- * to make the transition to a logging framework.
- *
- * More advanced users may choose to completely customize the levels (and level names) to suite their needs.
- * For more information on this see the "Custom Log Levels" page:
- * http://code.google.com/p/cocoalumberjack/wiki/CustomLogLevels
- *
- * Advanced users may also notice that we're using a bitmask.
- * This is to allow for custom fine grained logging:
- * http://code.google.com/p/cocoalumberjack/wiki/FineGrainedLogging
-**/
-
-#define LOG_FLAG_ERROR (1 << 0) // 0...0001
-#define LOG_FLAG_WARN (1 << 1) // 0...0010
-#define LOG_FLAG_INFO (1 << 2) // 0...0100
-#define LOG_FLAG_VERBOSE (1 << 3) // 0...1000
-
-#define LOG_LEVEL_OFF 0
-#define LOG_LEVEL_ERROR (LOG_FLAG_ERROR) // 0...0001
-#define LOG_LEVEL_WARN (LOG_FLAG_ERROR | LOG_FLAG_WARN) // 0...0011
-#define LOG_LEVEL_INFO (LOG_FLAG_ERROR | LOG_FLAG_WARN | LOG_FLAG_INFO) // 0...0111
-#define LOG_LEVEL_VERBOSE (LOG_FLAG_ERROR | LOG_FLAG_WARN | LOG_FLAG_INFO | LOG_FLAG_VERBOSE) // 0...1111
-
-#define LOG_ERROR (ddLogLevel & LOG_FLAG_ERROR)
-#define LOG_WARN (ddLogLevel & LOG_FLAG_WARN)
-#define LOG_INFO (ddLogLevel & LOG_FLAG_INFO)
-#define LOG_VERBOSE (ddLogLevel & LOG_FLAG_VERBOSE)
-
-#define DDLogError(frmt, ...) SYNC_LOG_OBJC_MAYBE(ddLogLevel, LOG_FLAG_ERROR, frmt, ##__VA_ARGS__)
-#define DDLogWarn(frmt, ...) ASYNC_LOG_OBJC_MAYBE(ddLogLevel, LOG_FLAG_WARN, frmt, ##__VA_ARGS__)
-#define DDLogInfo(frmt, ...) ASYNC_LOG_OBJC_MAYBE(ddLogLevel, LOG_FLAG_INFO, frmt, ##__VA_ARGS__)
-#define DDLogVerbose(frmt, ...) ASYNC_LOG_OBJC_MAYBE(ddLogLevel, LOG_FLAG_VERBOSE, frmt, ##__VA_ARGS__)
-
-#define DDLogCError(frmt, ...) SYNC_LOG_C_MAYBE(ddLogLevel, LOG_FLAG_ERROR, frmt, ##__VA_ARGS__)
-#define DDLogCWarn(frmt, ...) ASYNC_LOG_C_MAYBE(ddLogLevel, LOG_FLAG_WARN, frmt, ##__VA_ARGS__)
-#define DDLogCInfo(frmt, ...) ASYNC_LOG_C_MAYBE(ddLogLevel, LOG_FLAG_INFO, frmt, ##__VA_ARGS__)
-#define DDLogCVerbose(frmt, ...) ASYNC_LOG_C_MAYBE(ddLogLevel, LOG_FLAG_VERBOSE, frmt, ##__VA_ARGS__)
-
-/**
- * The THIS_FILE macro gives you an NSString of the file name.
- * For simplicity and clarity, the file name does not include the full path or file extension.
- *
- * For example: DDLogWarn(@"%@: Unable to find thingy", THIS_FILE) -> @"MyViewController: Unable to find thingy"
-**/
-
-NSString *ExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
-
-#define THIS_FILE (ExtractFileNameWithoutExtension(__FILE__, NO))
-
-/**
- * The THIS_METHOD macro gives you the name of the current objective-c method.
- *
- * For example: DDLogWarn(@"%@ - Requires non-nil strings") -> @"setMake:model: requires non-nil strings"
- *
- * Note: This does NOT work in straight C functions (non objective-c).
- * Instead you should use the predefined __FUNCTION__ macro.
-**/
-
-#define THIS_METHOD NSStringFromSelector(_cmd)
-
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@interface DDLog : NSObject
-
-#if GCD_MAYBE_AVAILABLE
-
-/**
- * Provides access to the underlying logging queue.
- * This may be helpful to Logger classes for things like thread synchronization.
-**/
-
-+ (dispatch_queue_t)loggingQueue;
-
-#endif
-
-#if GCD_MAYBE_UNAVAILABLE
-
-/**
- * Provides access to the underlying logging thread.
- * This may be helpful to Logger classes for things like thread synchronization.
-**/
-
-+ (NSThread *)loggingThread;
-
-#endif
-
-/**
- * Logging Primitive.
- *
- * This method is used by the macros above.
- * It is suggested you stick with the macros as they're easier to use.
-**/
-
-+ (void)log:(BOOL)synchronous
- level:(int)level
- flag:(int)flag
- file:(const char *)file
- function:(const char *)function
- line:(int)line
- format:(NSString *)format, ...;
-
-/** Sets the given filename and line to be stored to the next log message.
-
- This is used for nicer Xcode integration when issuing warnings and errors: we don't want Xcode pointing to appledoc files, but instead to user's source files that caused warnings/errors! After next log:level:flag:file:function:line:format: call, these values are reset.
- */
-+ (void)storeFilename:(NSString *)file line:(NSUInteger)line;
-
-/**
- * Since logging can be asynchronous, there may be times when you want to flush the logs.
- * The framework invokes this automatically when the application quits.
-**/
-
-+ (void)flushLog;
-
-/**
- * Loggers
- *
- * If you want your log statements to go somewhere,
- * you should create and add a logger.
-**/
-
-+ (void)addLogger:(id <DDLogger>)logger;
-+ (void)removeLogger:(id <DDLogger>)logger;
-
-+ (void)removeAllLoggers;
-
-/**
- * Registered Dynamic Logging
- *
- * These methods allow you to obtain a list of classes that are using registered dynamic logging,
- * and also provides methods to get and set their log level during run time.
-**/
-
-+ (NSArray *)registeredClasses;
-+ (NSArray *)registeredClassNames;
-
-+ (int)logLevelForClass:(Class)aClass;
-+ (int)logLevelForClassWithName:(NSString *)aClassName;
-
-+ (void)setLogLevel:(int)logLevel forClass:(Class)aClass;
-+ (void)setLogLevel:(int)logLevel forClassWithName:(NSString *)aClassName;
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@protocol DDLogger <NSObject>
-@required
-
-- (void)logMessage:(DDLogMessage *)logMessage;
-
-/**
- * Formatters may optionally be added to any logger.
- * If no formatter is set, the logger simply logs the message as it is given in logMessage.
- * Or it may use its own built in formatting style.
-**/
-- (id <DDLogFormatter>)logFormatter;
-- (void)setLogFormatter:(id <DDLogFormatter>)formatter;
-
-@optional
-
-/**
- * Since logging is asynchronous, adding and removing loggers is also asynchronous.
- * In other words, the loggers are added and removed at appropriate times with regards to log messages.
- *
- * - Loggers will not receive log messages that were executed prior to when they were added.
- * - Loggers will not receive log messages that were executed after they were removed.
- *
- * These methods are executed in the logging thread/queue.
- * This is the same thread/queue that will execute every logMessage: invocation.
- * Loggers may use these methods for thread synchronization or other setup/teardown tasks.
-**/
-
-- (void)didAddLogger;
-- (void)willRemoveLogger;
-
-#if GCD_MAYBE_AVAILABLE
-
-/**
- * When Grand Central Dispatch is available
- * each logger is executed concurrently with respect to the other loggers.
- * Thus, a dedicated dispatch queue is used for each logger.
- * Logger implementations may optionally choose to provide their own dispatch queue.
-**/
-- (dispatch_queue_t)loggerQueue;
-
-/**
- * If the logger implementation does not choose to provide its own queue,
- * one will automatically be created for it.
- * The created queue will receive its name from this method.
- * This may be helpful for debugging or profiling reasons.
-**/
-- (NSString *)loggerName;
-
-#endif
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@protocol DDLogFormatter <NSObject>
-@required
-
-/**
- * Formatters may optionally be added to any logger.
- * This allows for increased flexibility in the logging environment.
- * For example, log messages for log files may be formatted differently than log messages for the console.
- *
- * For more information about formatters, see the "Custom Formatters" page:
- * http://code.google.com/p/cocoalumberjack/wiki/CustomFormatters
- *
- * The formatter may also optionally filter the log message by returning nil,
- * in which case the logger will not log the message.
-**/
-
-- (NSString *)formatLogMessage:(DDLogMessage *)logMessage;
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#pragma mark -
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@protocol DDRegisteredDynamicLogging
-
-/**
- * Implement these methods to allow a file's log level to be managed from a central location.
- *
- * This is useful if you'd like to be able to change log levels for various parts
- * of your code from within the running application.
- *
- * Imagine pulling up the settings for your application,
- * and being able to configure the logging level on a per file basis.
- *
- * The implementation can be very straight-forward:
- *
- * + (int)ddLogLevel
- * {
- * return ddLogLevel;
- * }
- *