toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.m

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 //
michael@0 2 // GTMLogger.m
michael@0 3 //
michael@0 4 // Copyright 2007-2008 Google Inc.
michael@0 5 //
michael@0 6 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
michael@0 7 // use this file except in compliance with the License. You may obtain a copy
michael@0 8 // of the License at
michael@0 9 //
michael@0 10 // http://www.apache.org/licenses/LICENSE-2.0
michael@0 11 //
michael@0 12 // Unless required by applicable law or agreed to in writing, software
michael@0 13 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
michael@0 14 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
michael@0 15 // License for the specific language governing permissions and limitations under
michael@0 16 // the License.
michael@0 17 //
michael@0 18
michael@0 19 #import "GTMLogger.h"
michael@0 20 #import "GTMGarbageCollection.h"
michael@0 21 #import <fcntl.h>
michael@0 22 #import <unistd.h>
michael@0 23 #import <stdlib.h>
michael@0 24 #import <pthread.h>
michael@0 25
michael@0 26
michael@0 27 #if !defined(__clang__) && (__GNUC__*10+__GNUC_MINOR__ >= 42)
michael@0 28 // Some versions of GCC (4.2 and below AFAIK) aren't great about supporting
michael@0 29 // -Wmissing-format-attribute
michael@0 30 // when the function is anything more complex than foo(NSString *fmt, ...).
michael@0 31 // You see the error inside the function when you turn ... into va_args and
michael@0 32 // attempt to call another function (like vsprintf for example).
michael@0 33 // So we just shut off the warning for this file. We reenable it at the end.
michael@0 34 #pragma GCC diagnostic ignored "-Wmissing-format-attribute"
michael@0 35 #endif // !__clang__
michael@0 36
michael@0 37 // Reference to the shared GTMLogger instance. This is not a singleton, it's
michael@0 38 // just an easy reference to one shared instance.
michael@0 39 static GTMLogger *gSharedLogger = nil;
michael@0 40
michael@0 41
michael@0 42 @implementation GTMLogger
michael@0 43
michael@0 44 // Returns a pointer to the shared logger instance. If none exists, a standard
michael@0 45 // logger is created and returned.
michael@0 46 + (id)sharedLogger {
michael@0 47 @synchronized(self) {
michael@0 48 if (gSharedLogger == nil) {
michael@0 49 gSharedLogger = [[self standardLogger] retain];
michael@0 50 }
michael@0 51 }
michael@0 52 return [[gSharedLogger retain] autorelease];
michael@0 53 }
michael@0 54
michael@0 55 + (void)setSharedLogger:(GTMLogger *)logger {
michael@0 56 @synchronized(self) {
michael@0 57 [gSharedLogger autorelease];
michael@0 58 gSharedLogger = [logger retain];
michael@0 59 }
michael@0 60 }
michael@0 61
michael@0 62 + (id)standardLogger {
michael@0 63 // Don't trust NSFileHandle not to throw
michael@0 64 @try {
michael@0 65 id<GTMLogWriter> writer = [NSFileHandle fileHandleWithStandardOutput];
michael@0 66 id<GTMLogFormatter> fr = [[[GTMLogStandardFormatter alloc] init]
michael@0 67 autorelease];
michael@0 68 id<GTMLogFilter> filter = [[[GTMLogLevelFilter alloc] init] autorelease];
michael@0 69 return [[[self alloc] initWithWriter:writer
michael@0 70 formatter:fr
michael@0 71 filter:filter] autorelease];
michael@0 72 }
michael@0 73 @catch (id e) {
michael@0 74 // Ignored
michael@0 75 }
michael@0 76 return nil;
michael@0 77 }
michael@0 78
michael@0 79 + (id)standardLoggerWithStderr {
michael@0 80 // Don't trust NSFileHandle not to throw
michael@0 81 @try {
michael@0 82 id me = [self standardLogger];
michael@0 83 [me setWriter:[NSFileHandle fileHandleWithStandardError]];
michael@0 84 return me;
michael@0 85 }
michael@0 86 @catch (id e) {
michael@0 87 // Ignored
michael@0 88 }
michael@0 89 return nil;
michael@0 90 }
michael@0 91
michael@0 92 + (id)standardLoggerWithStdoutAndStderr {
michael@0 93 // We're going to take advantage of the GTMLogger to GTMLogWriter adaptor
michael@0 94 // and create a composite logger that an outer "standard" logger can use
michael@0 95 // as a writer. Our inner loggers should apply no formatting since the main
michael@0 96 // logger does that and we want the caller to be able to change formatters
michael@0 97 // or add writers without knowing the inner structure of our composite.
michael@0 98
michael@0 99 // Don't trust NSFileHandle not to throw
michael@0 100 @try {
michael@0 101 GTMLogBasicFormatter *formatter = [[[GTMLogBasicFormatter alloc] init]
michael@0 102 autorelease];
michael@0 103 GTMLogger *stdoutLogger =
michael@0 104 [self loggerWithWriter:[NSFileHandle fileHandleWithStandardOutput]
michael@0 105 formatter:formatter
michael@0 106 filter:[[[GTMLogMaximumLevelFilter alloc]
michael@0 107 initWithMaximumLevel:kGTMLoggerLevelInfo]
michael@0 108 autorelease]];
michael@0 109 GTMLogger *stderrLogger =
michael@0 110 [self loggerWithWriter:[NSFileHandle fileHandleWithStandardError]
michael@0 111 formatter:formatter
michael@0 112 filter:[[[GTMLogMininumLevelFilter alloc]
michael@0 113 initWithMinimumLevel:kGTMLoggerLevelError]
michael@0 114 autorelease]];
michael@0 115 GTMLogger *compositeWriter =
michael@0 116 [self loggerWithWriter:[NSArray arrayWithObjects:
michael@0 117 stdoutLogger, stderrLogger, nil]
michael@0 118 formatter:formatter
michael@0 119 filter:[[[GTMLogNoFilter alloc] init] autorelease]];
michael@0 120 GTMLogger *outerLogger = [self standardLogger];
michael@0 121 [outerLogger setWriter:compositeWriter];
michael@0 122 return outerLogger;
michael@0 123 }
michael@0 124 @catch (id e) {
michael@0 125 // Ignored
michael@0 126 }
michael@0 127 return nil;
michael@0 128 }
michael@0 129
michael@0 130 + (id)standardLoggerWithPath:(NSString *)path {
michael@0 131 @try {
michael@0 132 NSFileHandle *fh = [NSFileHandle fileHandleForLoggingAtPath:path mode:0644];
michael@0 133 if (fh == nil) return nil;
michael@0 134 id me = [self standardLogger];
michael@0 135 [me setWriter:fh];
michael@0 136 return me;
michael@0 137 }
michael@0 138 @catch (id e) {
michael@0 139 // Ignored
michael@0 140 }
michael@0 141 return nil;
michael@0 142 }
michael@0 143
michael@0 144 + (id)loggerWithWriter:(id<GTMLogWriter>)writer
michael@0 145 formatter:(id<GTMLogFormatter>)formatter
michael@0 146 filter:(id<GTMLogFilter>)filter {
michael@0 147 return [[[self alloc] initWithWriter:writer
michael@0 148 formatter:formatter
michael@0 149 filter:filter] autorelease];
michael@0 150 }
michael@0 151
michael@0 152 + (id)logger {
michael@0 153 return [[[self alloc] init] autorelease];
michael@0 154 }
michael@0 155
michael@0 156 - (id)init {
michael@0 157 return [self initWithWriter:nil formatter:nil filter:nil];
michael@0 158 }
michael@0 159
michael@0 160 - (id)initWithWriter:(id<GTMLogWriter>)writer
michael@0 161 formatter:(id<GTMLogFormatter>)formatter
michael@0 162 filter:(id<GTMLogFilter>)filter {
michael@0 163 if ((self = [super init])) {
michael@0 164 [self setWriter:writer];
michael@0 165 [self setFormatter:formatter];
michael@0 166 [self setFilter:filter];
michael@0 167 }
michael@0 168 return self;
michael@0 169 }
michael@0 170
michael@0 171 - (void)dealloc {
michael@0 172 // Unlikely, but |writer_| may be an NSFileHandle, which can throw
michael@0 173 @try {
michael@0 174 [formatter_ release];
michael@0 175 [filter_ release];
michael@0 176 [writer_ release];
michael@0 177 }
michael@0 178 @catch (id e) {
michael@0 179 // Ignored
michael@0 180 }
michael@0 181 [super dealloc];
michael@0 182 }
michael@0 183
michael@0 184 - (id<GTMLogWriter>)writer {
michael@0 185 return [[writer_ retain] autorelease];
michael@0 186 }
michael@0 187
michael@0 188 - (void)setWriter:(id<GTMLogWriter>)writer {
michael@0 189 @synchronized(self) {
michael@0 190 [writer_ autorelease];
michael@0 191 writer_ = nil;
michael@0 192 if (writer == nil) {
michael@0 193 // Try to use stdout, but don't trust NSFileHandle
michael@0 194 @try {
michael@0 195 writer_ = [[NSFileHandle fileHandleWithStandardOutput] retain];
michael@0 196 }
michael@0 197 @catch (id e) {
michael@0 198 // Leave |writer_| nil
michael@0 199 }
michael@0 200 } else {
michael@0 201 writer_ = [writer retain];
michael@0 202 }
michael@0 203 }
michael@0 204 }
michael@0 205
michael@0 206 - (id<GTMLogFormatter>)formatter {
michael@0 207 return [[formatter_ retain] autorelease];
michael@0 208 }
michael@0 209
michael@0 210 - (void)setFormatter:(id<GTMLogFormatter>)formatter {
michael@0 211 @synchronized(self) {
michael@0 212 [formatter_ autorelease];
michael@0 213 formatter_ = nil;
michael@0 214 if (formatter == nil) {
michael@0 215 @try {
michael@0 216 formatter_ = [[GTMLogBasicFormatter alloc] init];
michael@0 217 }
michael@0 218 @catch (id e) {
michael@0 219 // Leave |formatter_| nil
michael@0 220 }
michael@0 221 } else {
michael@0 222 formatter_ = [formatter retain];
michael@0 223 }
michael@0 224 }
michael@0 225 }
michael@0 226
michael@0 227 - (id<GTMLogFilter>)filter {
michael@0 228 return [[filter_ retain] autorelease];
michael@0 229 }
michael@0 230
michael@0 231 - (void)setFilter:(id<GTMLogFilter>)filter {
michael@0 232 @synchronized(self) {
michael@0 233 [filter_ autorelease];
michael@0 234 filter_ = nil;
michael@0 235 if (filter == nil) {
michael@0 236 @try {
michael@0 237 filter_ = [[GTMLogNoFilter alloc] init];
michael@0 238 }
michael@0 239 @catch (id e) {
michael@0 240 // Leave |filter_| nil
michael@0 241 }
michael@0 242 } else {
michael@0 243 filter_ = [filter retain];
michael@0 244 }
michael@0 245 }
michael@0 246 }
michael@0 247
michael@0 248 - (void)logDebug:(NSString *)fmt, ... {
michael@0 249 va_list args;
michael@0 250 va_start(args, fmt);
michael@0 251 [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelDebug];
michael@0 252 va_end(args);
michael@0 253 }
michael@0 254
michael@0 255 - (void)logInfo:(NSString *)fmt, ... {
michael@0 256 va_list args;
michael@0 257 va_start(args, fmt);
michael@0 258 [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelInfo];
michael@0 259 va_end(args);
michael@0 260 }
michael@0 261
michael@0 262 - (void)logError:(NSString *)fmt, ... {
michael@0 263 va_list args;
michael@0 264 va_start(args, fmt);
michael@0 265 [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelError];
michael@0 266 va_end(args);
michael@0 267 }
michael@0 268
michael@0 269 - (void)logAssert:(NSString *)fmt, ... {
michael@0 270 va_list args;
michael@0 271 va_start(args, fmt);
michael@0 272 [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelAssert];
michael@0 273 va_end(args);
michael@0 274 }
michael@0 275
michael@0 276 @end // GTMLogger
michael@0 277
michael@0 278 @implementation GTMLogger (GTMLoggerMacroHelpers)
michael@0 279
michael@0 280 - (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ... {
michael@0 281 va_list args;
michael@0 282 va_start(args, fmt);
michael@0 283 [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelDebug];
michael@0 284 va_end(args);
michael@0 285 }
michael@0 286
michael@0 287 - (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ... {
michael@0 288 va_list args;
michael@0 289 va_start(args, fmt);
michael@0 290 [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelInfo];
michael@0 291 va_end(args);
michael@0 292 }
michael@0 293
michael@0 294 - (void)logFuncError:(const char *)func msg:(NSString *)fmt, ... {
michael@0 295 va_list args;
michael@0 296 va_start(args, fmt);
michael@0 297 [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelError];
michael@0 298 va_end(args);
michael@0 299 }
michael@0 300
michael@0 301 - (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ... {
michael@0 302 va_list args;
michael@0 303 va_start(args, fmt);
michael@0 304 [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelAssert];
michael@0 305 va_end(args);
michael@0 306 }
michael@0 307
michael@0 308 @end // GTMLoggerMacroHelpers
michael@0 309
michael@0 310 @implementation GTMLogger (PrivateMethods)
michael@0 311
michael@0 312 - (void)logInternalFunc:(const char *)func
michael@0 313 format:(NSString *)fmt
michael@0 314 valist:(va_list)args
michael@0 315 level:(GTMLoggerLevel)level {
michael@0 316 // Primary point where logging happens, logging should never throw, catch
michael@0 317 // everything.
michael@0 318 @try {
michael@0 319 NSString *fname = func ? [NSString stringWithUTF8String:func] : nil;
michael@0 320 NSString *msg = [formatter_ stringForFunc:fname
michael@0 321 withFormat:fmt
michael@0 322 valist:args
michael@0 323 level:level];
michael@0 324 if (msg && [filter_ filterAllowsMessage:msg level:level])
michael@0 325 [writer_ logMessage:msg level:level];
michael@0 326 }
michael@0 327 @catch (id e) {
michael@0 328 // Ignored
michael@0 329 }
michael@0 330 }
michael@0 331
michael@0 332 @end // PrivateMethods
michael@0 333
michael@0 334
michael@0 335 @implementation NSFileHandle (GTMFileHandleLogWriter)
michael@0 336
michael@0 337 + (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode {
michael@0 338 int fd = -1;
michael@0 339 if (path) {
michael@0 340 int flags = O_WRONLY | O_APPEND | O_CREAT;
michael@0 341 fd = open([path fileSystemRepresentation], flags, mode);
michael@0 342 }
michael@0 343 if (fd == -1) return nil;
michael@0 344 return [[[self alloc] initWithFileDescriptor:fd
michael@0 345 closeOnDealloc:YES] autorelease];
michael@0 346 }
michael@0 347
michael@0 348 - (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level {
michael@0 349 @synchronized(self) {
michael@0 350 // Closed pipes should not generate exceptions in our caller. Catch here
michael@0 351 // as well [GTMLogger logInternalFunc:...] so that an exception in this
michael@0 352 // writer does not prevent other writers from having a chance.
michael@0 353 @try {
michael@0 354 NSString *line = [NSString stringWithFormat:@"%@\n", msg];
michael@0 355 [self writeData:[line dataUsingEncoding:NSUTF8StringEncoding]];
michael@0 356 }
michael@0 357 @catch (id e) {
michael@0 358 // Ignored
michael@0 359 }
michael@0 360 }
michael@0 361 }
michael@0 362
michael@0 363 @end // GTMFileHandleLogWriter
michael@0 364
michael@0 365
michael@0 366 @implementation NSArray (GTMArrayCompositeLogWriter)
michael@0 367
michael@0 368 - (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level {
michael@0 369 @synchronized(self) {
michael@0 370 id<GTMLogWriter> child = nil;
michael@0 371 GTM_FOREACH_OBJECT(child, self) {
michael@0 372 if ([child conformsToProtocol:@protocol(GTMLogWriter)])
michael@0 373 [child logMessage:msg level:level];
michael@0 374 }
michael@0 375 }
michael@0 376 }
michael@0 377
michael@0 378 @end // GTMArrayCompositeLogWriter
michael@0 379
michael@0 380
michael@0 381 @implementation GTMLogger (GTMLoggerLogWriter)
michael@0 382
michael@0 383 - (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level {
michael@0 384 switch (level) {
michael@0 385 case kGTMLoggerLevelDebug:
michael@0 386 [self logDebug:@"%@", msg];
michael@0 387 break;
michael@0 388 case kGTMLoggerLevelInfo:
michael@0 389 [self logInfo:@"%@", msg];
michael@0 390 break;
michael@0 391 case kGTMLoggerLevelError:
michael@0 392 [self logError:@"%@", msg];
michael@0 393 break;
michael@0 394 case kGTMLoggerLevelAssert:
michael@0 395 [self logAssert:@"%@", msg];
michael@0 396 break;
michael@0 397 default:
michael@0 398 // Ignore the message.
michael@0 399 break;
michael@0 400 }
michael@0 401 }
michael@0 402
michael@0 403 @end // GTMLoggerLogWriter
michael@0 404
michael@0 405
michael@0 406 @implementation GTMLogBasicFormatter
michael@0 407
michael@0 408 - (NSString *)prettyNameForFunc:(NSString *)func {
michael@0 409 NSString *name = [func stringByTrimmingCharactersInSet:
michael@0 410 [NSCharacterSet whitespaceAndNewlineCharacterSet]];
michael@0 411 NSString *function = @"(unknown)";
michael@0 412 if ([name length]) {
michael@0 413 if (// Objective C __func__ and __PRETTY_FUNCTION__
michael@0 414 [name hasPrefix:@"-["] || [name hasPrefix:@"+["] ||
michael@0 415 // C++ __PRETTY_FUNCTION__ and other preadorned formats
michael@0 416 [name hasSuffix:@")"]) {
michael@0 417 function = name;
michael@0 418 } else {
michael@0 419 // Assume C99 __func__
michael@0 420 function = [NSString stringWithFormat:@"%@()", name];
michael@0 421 }
michael@0 422 }
michael@0 423 return function;
michael@0 424 }
michael@0 425
michael@0 426 - (NSString *)stringForFunc:(NSString *)func
michael@0 427 withFormat:(NSString *)fmt
michael@0 428 valist:(va_list)args
michael@0 429 level:(GTMLoggerLevel)level {
michael@0 430 // Performance note: We may want to do a quick check here to see if |fmt|
michael@0 431 // contains a '%', and if not, simply return 'fmt'.
michael@0 432 if (!(fmt && args)) return nil;
michael@0 433 return [[[NSString alloc] initWithFormat:fmt arguments:args] autorelease];
michael@0 434 }
michael@0 435
michael@0 436 @end // GTMLogBasicFormatter
michael@0 437
michael@0 438
michael@0 439 @implementation GTMLogStandardFormatter
michael@0 440
michael@0 441 - (id)init {
michael@0 442 if ((self = [super init])) {
michael@0 443 dateFormatter_ = [[NSDateFormatter alloc] init];
michael@0 444 [dateFormatter_ setFormatterBehavior:NSDateFormatterBehavior10_4];
michael@0 445 [dateFormatter_ setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"];
michael@0 446 pname_ = [[[NSProcessInfo processInfo] processName] copy];
michael@0 447 pid_ = [[NSProcessInfo processInfo] processIdentifier];
michael@0 448 if (!(dateFormatter_ && pname_)) {
michael@0 449 [self release];
michael@0 450 return nil;
michael@0 451 }
michael@0 452 }
michael@0 453 return self;
michael@0 454 }
michael@0 455
michael@0 456 - (void)dealloc {
michael@0 457 [dateFormatter_ release];
michael@0 458 [pname_ release];
michael@0 459 [super dealloc];
michael@0 460 }
michael@0 461
michael@0 462 - (NSString *)stringForFunc:(NSString *)func
michael@0 463 withFormat:(NSString *)fmt
michael@0 464 valist:(va_list)args
michael@0 465 level:(GTMLoggerLevel)level {
michael@0 466 NSString *tstamp = nil;
michael@0 467 @synchronized (dateFormatter_) {
michael@0 468 tstamp = [dateFormatter_ stringFromDate:[NSDate date]];
michael@0 469 }
michael@0 470 return [NSString stringWithFormat:@"%@ %@[%d/%p] [lvl=%d] %@ %@",
michael@0 471 tstamp, pname_, pid_, pthread_self(),
michael@0 472 level, [self prettyNameForFunc:func],
michael@0 473 // |super| has guard for nil |fmt| and |args|
michael@0 474 [super stringForFunc:func withFormat:fmt valist:args level:level]];
michael@0 475 }
michael@0 476
michael@0 477 @end // GTMLogStandardFormatter
michael@0 478
michael@0 479
michael@0 480 @implementation GTMLogLevelFilter
michael@0 481
michael@0 482 // Check the environment and the user preferences for the GTMVerboseLogging key
michael@0 483 // to see if verbose logging has been enabled. The environment variable will
michael@0 484 // override the defaults setting, so check the environment first.
michael@0 485 // COV_NF_START
michael@0 486 static BOOL IsVerboseLoggingEnabled(void) {
michael@0 487 static NSString *const kVerboseLoggingKey = @"GTMVerboseLogging";
michael@0 488 NSString *value = [[[NSProcessInfo processInfo] environment]
michael@0 489 objectForKey:kVerboseLoggingKey];
michael@0 490 if (value) {
michael@0 491 // Emulate [NSString boolValue] for pre-10.5
michael@0 492 value = [value stringByTrimmingCharactersInSet:
michael@0 493 [NSCharacterSet whitespaceAndNewlineCharacterSet]];
michael@0 494 if ([[value uppercaseString] hasPrefix:@"Y"] ||
michael@0 495 [[value uppercaseString] hasPrefix:@"T"] ||
michael@0 496 [value intValue]) {
michael@0 497 return YES;
michael@0 498 } else {
michael@0 499 return NO;
michael@0 500 }
michael@0 501 }
michael@0 502 return [[NSUserDefaults standardUserDefaults] boolForKey:kVerboseLoggingKey];
michael@0 503 }
michael@0 504 // COV_NF_END
michael@0 505
michael@0 506 // In DEBUG builds, log everything. If we're not in a debug build we'll assume
michael@0 507 // that we're in a Release build.
michael@0 508 - (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level {
michael@0 509 #if DEBUG
michael@0 510 return YES;
michael@0 511 #endif
michael@0 512
michael@0 513 BOOL allow = YES;
michael@0 514
michael@0 515 switch (level) {
michael@0 516 case kGTMLoggerLevelDebug:
michael@0 517 allow = NO;
michael@0 518 break;
michael@0 519 case kGTMLoggerLevelInfo:
michael@0 520 allow = IsVerboseLoggingEnabled();
michael@0 521 break;
michael@0 522 case kGTMLoggerLevelError:
michael@0 523 allow = YES;
michael@0 524 break;
michael@0 525 case kGTMLoggerLevelAssert:
michael@0 526 allow = YES;
michael@0 527 break;
michael@0 528 default:
michael@0 529 allow = YES;
michael@0 530 break;
michael@0 531 }
michael@0 532
michael@0 533 return allow;
michael@0 534 }
michael@0 535
michael@0 536 @end // GTMLogLevelFilter
michael@0 537
michael@0 538
michael@0 539 @implementation GTMLogNoFilter
michael@0 540
michael@0 541 - (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level {
michael@0 542 return YES; // Allow everything through
michael@0 543 }
michael@0 544
michael@0 545 @end // GTMLogNoFilter
michael@0 546
michael@0 547
michael@0 548 @implementation GTMLogAllowedLevelFilter
michael@0 549
michael@0 550 // Private designated initializer
michael@0 551 - (id)initWithAllowedLevels:(NSIndexSet *)levels {
michael@0 552 self = [super init];
michael@0 553 if (self != nil) {
michael@0 554 allowedLevels_ = [levels retain];
michael@0 555 // Cap min/max level
michael@0 556 if (!allowedLevels_ ||
michael@0 557 // NSIndexSet is unsigned so only check the high bound, but need to
michael@0 558 // check both first and last index because NSIndexSet appears to allow
michael@0 559 // wraparound.
michael@0 560 ([allowedLevels_ firstIndex] > kGTMLoggerLevelAssert) ||
michael@0 561 ([allowedLevels_ lastIndex] > kGTMLoggerLevelAssert)) {
michael@0 562 [self release];
michael@0 563 return nil;
michael@0 564 }
michael@0 565 }
michael@0 566 return self;
michael@0 567 }
michael@0 568
michael@0 569 - (id)init {
michael@0 570 // Allow all levels in default init
michael@0 571 return [self initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange:
michael@0 572 NSMakeRange(kGTMLoggerLevelUnknown,
michael@0 573 (kGTMLoggerLevelAssert - kGTMLoggerLevelUnknown + 1))]];
michael@0 574 }
michael@0 575
michael@0 576 - (void)dealloc {
michael@0 577 [allowedLevels_ release];
michael@0 578 [super dealloc];
michael@0 579 }
michael@0 580
michael@0 581 - (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level {
michael@0 582 return [allowedLevels_ containsIndex:level];
michael@0 583 }
michael@0 584
michael@0 585 @end // GTMLogAllowedLevelFilter
michael@0 586
michael@0 587
michael@0 588 @implementation GTMLogMininumLevelFilter
michael@0 589
michael@0 590 - (id)initWithMinimumLevel:(GTMLoggerLevel)level {
michael@0 591 return [super initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange:
michael@0 592 NSMakeRange(level,
michael@0 593 (kGTMLoggerLevelAssert - level + 1))]];
michael@0 594 }
michael@0 595
michael@0 596 @end // GTMLogMininumLevelFilter
michael@0 597
michael@0 598
michael@0 599 @implementation GTMLogMaximumLevelFilter
michael@0 600
michael@0 601 - (id)initWithMaximumLevel:(GTMLoggerLevel)level {
michael@0 602 return [super initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange:
michael@0 603 NSMakeRange(kGTMLoggerLevelUnknown, level + 1)]];
michael@0 604 }
michael@0 605
michael@0 606 @end // GTMLogMaximumLevelFilter
michael@0 607
michael@0 608 #if !defined(__clang__) && (__GNUC__*10+__GNUC_MINOR__ >= 42)
michael@0 609 // See comment at top of file.
michael@0 610 #pragma GCC diagnostic error "-Wmissing-format-attribute"
michael@0 611 #endif // !__clang__
michael@0 612

mercurial