From 3fcbbc711ff7b8c993af4814253b70ffa4818dba Mon Sep 17 00:00:00 2001 From: Xiaomin Date: Tue, 24 Jul 2018 19:29:40 +0800 Subject: [PATCH] # This is a combination of 2 commits. # This is the 1st commit message: [WEEX-511][iOS] Improve compatibility for debuglog # This is the commit message #2: [WEEX-511][iOS] Make debug log simpler --- ios/sdk/WeexSDK/Sources/Utility/WXLog.m | 386 ++++++++++++++++-------- 1 file changed, 253 insertions(+), 133 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXLog.m b/ios/sdk/WeexSDK/Sources/Utility/WXLog.m index e7383b907e..9c7ffc8cbe 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXLog.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXLog.m @@ -6,9 +6,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -82,7 +82,7 @@ + (void)setLogLevel:(WXLogLevel)level { if (((WXLog*)[self sharedInstance])->_logLevel != level) { ((WXLog*)[self sharedInstance])->_logLevel = level; - + [[WXSDKManager bridgeMgr] resetEnvironment]; } #pragma clang diagnostic push @@ -126,7 +126,7 @@ + (void)setLogLevelString:(NSString *)levelString @"debug" : @(WXLogLevelDebug), @"log" : @(WXLogLevelLog) }; - + [self setLogLevel:[logLevelStringToEnum[levelString] unsignedIntegerValue]]; } @@ -151,16 +151,16 @@ + (void)log:(WXLogFlag)flag file:(const char *)fileName line:(NSUInteger)line me flagString = @"info"; break; } - + NSString *logMessage = [NSString stringWithFormat:@"[%@]%s:%ld, %@", flagString, fileName, (unsigned long)line, message]; - - + + if ([_externalLog logLevel] & flag) { [_externalLog log:flag message:logMessage]; } - + [[WXSDKManager bridgeMgr] logToWebSocket:flagString message:message]; - + if ([WXLog logLevel] & flag) { NSLog(@"%@", logMessage); } @@ -189,7 +189,7 @@ + (void)devLog:(WXLogFlag)flag file:(const char *)fileName line:(NSUInteger)line flagString = @"info"; break; } - + va_list args; va_start(args, format); NSString *message = @""; @@ -199,7 +199,7 @@ + (void)devLog:(WXLogFlag)flag file:(const char *)fileName line:(NSUInteger)line message = [[NSString alloc] initWithFormat:format arguments:args]; } va_end(args); - + NSArray *messageAry = [NSArray arrayWithObjects:message, nil]; Class WXLogClass = NSClassFromString(@"WXDebugger"); if (WXLogClass) { @@ -216,7 +216,7 @@ + (void)devLog:(WXLogFlag)flag file:(const char *)fileName line:(NSUInteger)line [invocation setArgument:&messageAry atIndex:3]; [invocation invoke]; } - + [self log:flag file:fileName line:line message:message]; } } @@ -231,145 +231,265 @@ + (void)registerExternalLog:(id)externalLog @end #pragma mark - WXSafeLog -static NSString *dealWithArray(NSArray *array, NSMutableSet *outSet); +static void dealWithValue(NSMutableString *result, id value, NSMutableSet *outSet); static NSUInteger getParamCount(NSString *format, NSMutableDictionary *outDict) { - NSUInteger paramCount = 0; - NSUInteger formatLength = [format length]; - - NSRange searchRange = NSMakeRange(0, formatLength); - NSRange paramRange = [format rangeOfString:@"%" options:0 range:searchRange]; - - NSMutableArray *paramLocations = [NSMutableArray array]; - NSArray *possibleTwo = @[@"l", @"h", @"z"]; - NSArray *two = @[@"hh", @"ld", @"lu", @"lx", @"zx"]; - while (paramRange.location != NSNotFound) - { - NSString *subString = [format substringWithRange:NSMakeRange(paramRange.location+1, 1)]; - if ([possibleTwo containsObject:subString]) { - NSString *subString2 = [format substringWithRange:NSMakeRange(paramRange.location+1, 2)]; - if ([two containsObject:subString2]) { - subString = subString2; - } - } - [outDict setObject:subString forKey:@(paramCount)]; - paramCount++; + static NSMutableSet *possibleTwoSet = nil; + static NSMutableSet *possibleThreeSet = nil; + static NSMutableSet *possibleTwo = nil; + static NSMutableSet *possibleThree = nil; - [paramLocations addObject:@(paramRange.location)]; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSArray *longArray = @[@"ld"]; + NSArray *longLongArray = @[@"lld"]; + NSDictionary *coolDict = @{@"long":longArray, @"long long":longLongArray}; + possibleTwoSet = [NSMutableSet set]; + possibleThreeSet = [NSMutableSet set]; + possibleTwo = [NSMutableSet set]; + possibleThree = [NSMutableSet set]; + for (NSString * key in coolDict.allKeys) { + NSArray *array = coolDict[key]; + for (NSString * value in array) { + if (value.length == 2) { + [possibleTwoSet addObject:value]; + NSString *sub = [value substringWithRange:NSMakeRange(0,1)]; + if (![possibleTwo containsObject:sub]) { + [possibleTwo addObject:sub]; + } + } else if (value.length == 3) { + [possibleThreeSet addObject:value]; + NSString *sub = [value substringWithRange:NSMakeRange(0,2)]; + if (![possibleThree containsObject:sub]) { + [possibleThree addObject:sub]; + } + } + } + } + }); + + NSUInteger paramCount = 0; + NSUInteger formatLength = [format length]; + NSRange searchRange = NSMakeRange(0, formatLength); + NSRange paramRange = [format rangeOfString:@"%" options:0 range:searchRange]; - searchRange.location = paramRange.location + 1; - searchRange.length = formatLength - searchRange.location; + while (paramRange.location != NSNotFound) + { + NSString *subString = @" "; + NSUInteger location = paramRange.location; + do { + location ++; + subString = [format substringWithRange:NSMakeRange(location, 1)]; + } while (([subString compare:@"0"] != NSOrderedAscending && [subString compare:@"9"] != NSOrderedDescending) || [subString compare:@"."] == NSOrderedSame); + if ([possibleTwo containsObject:subString]) { + NSString *subString3 = [format substringWithRange:NSMakeRange(location, 2)]; + if ([possibleThree containsObject:subString3]) { + NSString *subString4 = [format substringWithRange:NSMakeRange(location, 3)]; + if ([possibleThreeSet containsObject:subString4]) { + subString = subString4; + } + } else { + NSString *subString2 = [format substringWithRange:NSMakeRange(location, 2)]; + if ([possibleTwoSet containsObject:subString2]) { + subString = subString2; + } + } + } + [outDict setObject:subString forKey:@(paramCount)]; + paramCount++; + searchRange.location = paramRange.location + 1; + searchRange.length = formatLength - searchRange.location; - paramRange = [format rangeOfString:@"%" options:0 range:searchRange]; - } - return paramCount; + paramRange = [format rangeOfString:@"%" options:0 range:searchRange]; + } + return paramCount; } static NSString *dealWithDictionary(NSDictionary *dict, NSMutableSet *outSet) { - NSMutableString *result = [NSMutableString new]; - [result appendString:@" { "]; - int i = 0; - for (id key in dict.allKeys) { - if ([key isKindOfClass:[NSDictionary class]] || [key isKindOfClass:[NSArray class]]) { - [result appendString:@"(invalid Dictionary key) : ( )"]; - } else { - [result appendString:[NSString stringWithFormat:@"%@ : ", key]]; - id value = [dict objectForKey:key]; - if ([outSet containsObject:value]) { - [result appendString:@"(found Retain Recycle!!!)"]; - } else { - [outSet addObject:value]; - if ([value isKindOfClass:[NSArray class]]) { - NSString *tempString = dealWithArray((NSArray *)value, outSet); - [result appendString:tempString]; - } else if ([value isKindOfClass:[NSDictionary class]]) { - [result appendString:dealWithDictionary((NSDictionary *)value, outSet)]; - } else { - [result appendString:[NSString stringWithFormat:@"%@", value]]; - } - } - } - i++; - if (i < dict.allKeys.count) { - [result appendString:@" , "]; - } - } - [result appendString:@" } "]; - return result; + NSMutableString *result = [NSMutableString new]; + [result appendString:@" { "]; + int i = 0; + for (id key in dict.allKeys) { + if ([key isKindOfClass:[NSDictionary class]] || [key isKindOfClass:[NSArray class]] || [key isKindOfClass:[NSSet class]]) { + [result appendString:@"(invalid Dictionary key) : ( )"]; + } else { + [result appendString:[NSString stringWithFormat:@"%@ : ", key]]; + id value = [dict objectForKey:key]; + NSNumber *pointerValue = [NSNumber numberWithLong:(long)value]; + if ([outSet containsObject:pointerValue]) { + [result appendString:@"(Found Retain Cycle!!!)"]; + } else { + dealWithValue(result, value, outSet); + } + } + i++; + if (i < dict.allKeys.count) { + [result appendString:@" , "]; + } + } + [result appendString:@" } "]; + return result; } static NSString *dealWithArray(NSArray *array, NSMutableSet *outSet) { - NSMutableString *result = [NSMutableString new]; - [result appendString:@" [ "]; - int i = 0; - for (id value in array) { - if ([outSet containsObject:value]) { - [result appendString:@"(found Retain Recycle!!!)"]; - } else { - [outSet addObject:value]; - if ([value isKindOfClass:[NSArray class]]) { - NSString *tempString = dealWithArray((NSArray *)value, outSet); - [result appendString:tempString]; - } else if ([value isKindOfClass:[NSDictionary class]]) { - [result appendString:dealWithDictionary((NSDictionary *)value, outSet)]; - } else { - [result appendString:[NSString stringWithFormat:@"%@", value]]; - } - } - i++; - if (i < array.count) { - [result appendString:@" , "]; - } - } - [result appendString:@" ] "]; - return result; + NSMutableString *result = [NSMutableString new]; + [result appendString:@" [ "]; + int i = 0; + for (id value in array) { + NSNumber *pointerValue = [NSNumber numberWithLong:(long)value]; + if ([outSet containsObject:pointerValue]) { + [result appendString:@"(Found Retain Cycle!!!)"]; + } else { + dealWithValue(result, value, outSet); + } + i++; + if (i < array.count) { + [result appendString:@" , "]; + } + } + [result appendString:@" ] "]; + return result; +} + +static NSString *dealWithSet(NSSet *set, NSMutableSet *outSet) +{ + NSMutableString *result = [NSMutableString new]; + [result appendString:@" ( "]; + int i = 0; + for (id value in set) { + NSNumber *pointerValue = [NSNumber numberWithLong:(long)value]; + if ([outSet containsObject:pointerValue]) { + [result appendString:@"(Found Retain Cycle!!!)"]; + } else { + dealWithValue(result, value, outSet); + } + i++; + if (i < set.count) { + [result appendString:@" , "]; + } + } + [result appendString:@" ) "]; + return result; +} + +static void dealWithValue(NSMutableString *result, id value, NSMutableSet *outSet) +{ + NSNumber *pointerValue = [NSNumber numberWithLong:(long)value]; + if (pointerValue.longValue > 100000) { + [outSet addObject:pointerValue]; + } + if ([value isKindOfClass:[NSArray class]]) { + NSString *tempString = dealWithArray((NSArray *)value, outSet); + [result appendString:tempString]; + } else if ([value isKindOfClass:[NSDictionary class]]) { + [result appendString:dealWithDictionary((NSDictionary *)value, outSet)]; + } else if ([value isKindOfClass:[NSSet class]]) { + [result appendString:dealWithSet((NSSet *)value, outSet)]; + } else { + [result appendString:[NSString stringWithFormat:@"%@", value]]; + } } @implementation WXSafeLog + (NSString *)getLogMessage:(NSString *)format arguments:(va_list)args { - NSMutableString *mutableFormat = [NSMutableString stringWithString:format]; - NSMutableDictionary *dict = [NSMutableDictionary dictionary]; - NSUInteger count = getParamCount(format, dict); - NSMutableArray *replacedDict = [NSMutableArray array]; - for (NSUInteger i = 0; i < count; i++) { - if ([dict[@(i)] isEqualToString:@"@"]) { - NSMutableSet *outSet = [NSMutableSet set]; - id obj = va_arg(args, id); - NSString *output = @""; - if (obj) { - if ([obj isKindOfClass:[NSDictionary class]]) { - output = dealWithDictionary((NSDictionary *)obj, outSet); - } else if ([obj isKindOfClass:[NSArray class]]) { - output = dealWithArray((NSArray *)obj, outSet); - } else { - output = [NSString stringWithFormat:@"%@", obj]; - } - } - [replacedDict addObject:output]; - } else { - va_arg(args, void *); - } - } - NSString *prefix = @"#$~"; - NSString *suffix = @"~$#"; - NSString *replace = [NSString stringWithFormat:@"%@%%p%@", prefix, suffix]; - [mutableFormat replaceOccurrencesOfString:@"%@" withString:replace options:NSLiteralSearch range:NSMakeRange(0, mutableFormat.length)]; - NSMutableString *result = [[NSMutableString alloc] initWithFormat:mutableFormat arguments:args]; - int j = 0; - NSRange range, range1, range2; - range1 = [result rangeOfString:prefix options:NSLiteralSearch]; - range2 = [result rangeOfString:suffix options:NSLiteralSearch]; - range = NSMakeRange(range1.location, range2.location+range2.length - range1.location); - while(range1.length>0 && range2.length>0) { - [result replaceCharactersInRange:range withString:replacedDict[j++]]; - range1 = [result rangeOfString:prefix options:NSLiteralSearch]; - range2 = [result rangeOfString:suffix options:NSLiteralSearch]; - range = NSMakeRange(range1.location, range2.location+range2.length - range1.location); - } - return result; + NSMutableString *mutableFormat = [NSMutableString stringWithString:format]; + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + NSUInteger count = getParamCount(format, dict); + NSMutableArray *replacedDict = [NSMutableArray array]; + for (NSUInteger i = 0; i < count; i++) { + if ([dict[@(i)] isEqualToString:@"@"]) { + NSMutableSet *outSet = [NSMutableSet set]; + __unsafe_unretained id obj = va_arg(args, id); + NSString *output = @""; + if (obj) { + if ([obj isKindOfClass:[NSDictionary class]]) { + output = dealWithDictionary((NSDictionary *)obj, outSet); + } else if ([obj isKindOfClass:[NSArray class]]) { + output = dealWithArray((NSArray *)obj, outSet); + } else if ([obj isKindOfClass:[NSSet class]]) { + output = dealWithSet((NSSet *)obj, outSet); + } else { + output = [NSString stringWithFormat:@"%@", obj]; + } + } + [replacedDict addObject:output]; + } else { + NSString *logFormat = dict[@(i)]; + if (logFormat.length == 1) { +#define LEN 2 + char tempChar[LEN]; + memset(tempChar, 0, LEN); + [logFormat getCString:tempChar maxLength:LEN encoding:NSASCIIStringEncoding]; + switch(tempChar[0]) { + case '%': + case 'c': +//Suppress "Second argument to 'va_arg' is of promotable type 'char'; this va_arg has undefined behavior because arguments will be promoted to 'int'" warning +// va_arg(args, char); + va_arg(args, int); + break; + case 'd': + case 'D': + va_arg(args, int); + break; + case 'f': + case 'F': + va_arg(args, double); + break; + case 'C': +// va_arg(args, unichar); + va_arg(args, int); + break; + case 's': + va_arg(args, char *); + break; + case 'S': + va_arg(args, unichar *); + break; + case 'p': + va_arg(args, void *); + break; + default: + va_arg(args, void *); + break; + } + } else { + static NSDictionary *map; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + map = @{ + @"ld":@"long", \ + @"lld":@"long long", \ + }; + }); + NSString *type = map[dict[@(i)]]; + if ([type isEqualToString:@"long"]) { + va_arg(args, long); + } else if ([type isEqualToString:@"long long"]) { + va_arg(args, long long); + } + } + } + } + NSString *prefix = @"#$~"; + NSString *suffix = @"~$#"; + NSString *replace = [NSString stringWithFormat:@"%@%%p%@", prefix, suffix]; + [mutableFormat replaceOccurrencesOfString:@"%@" withString:replace options:NSLiteralSearch range:NSMakeRange(0, mutableFormat.length)]; + NSMutableString *result = [[NSMutableString alloc] initWithFormat:mutableFormat arguments:args]; + int j = 0; + NSRange range, range1, range2; + range1 = [result rangeOfString:prefix options:NSLiteralSearch]; + range2 = [result rangeOfString:suffix options:NSLiteralSearch]; + range = NSMakeRange(range1.location, range2.location+range2.length - range1.location); + while(range1.length>0 && range2.length>0) { + [result replaceCharactersInRange:range withString:replacedDict[j++]]; + range1 = [result rangeOfString:prefix options:NSLiteralSearch]; + range2 = [result rangeOfString:suffix options:NSLiteralSearch]; + range = NSMakeRange(range1.location, range2.location+range2.length - range1.location); + } + return result; } @end