// // NSString+YYAdd.m // YYKit // // Created by ibireme on 13/4/3. // Copyright (c) 2015 ibireme. // // This source code is licensed under the MIT-style license found in the // LICENSE file in the root directory of this source tree. // #import "NSString+YYAdd.h" #import "NSData+YYAdd.h" #import "NSNumber+YYAdd.h" #import "YYKitMacro.h" YYSYNTH_DUMMY_CLASS(NSString_YYAdd) @implementation NSString (YYAdd) - (NSString *)md2String { return [[self dataUsingEncoding:NSUTF8StringEncoding] md2String]; } - (NSString *)md4String { return [[self dataUsingEncoding:NSUTF8StringEncoding] md4String]; } - (NSString *)md5String { return [[self dataUsingEncoding:NSUTF8StringEncoding] md5String]; } - (NSString *)sha1String { return [[self dataUsingEncoding:NSUTF8StringEncoding] sha1String]; } - (NSString *)sha224String { return [[self dataUsingEncoding:NSUTF8StringEncoding] sha224String]; } - (NSString *)sha256String { return [[self dataUsingEncoding:NSUTF8StringEncoding] sha256String]; } - (NSString *)sha384String { return [[self dataUsingEncoding:NSUTF8StringEncoding] sha384String]; } - (NSString *)sha512String { return [[self dataUsingEncoding:NSUTF8StringEncoding] sha512String]; } - (NSString *)crc32String { return [[self dataUsingEncoding:NSUTF8StringEncoding] crc32String]; } - (NSString *)hmacMD5StringWithKey:(NSString *)key { return [[self dataUsingEncoding:NSUTF8StringEncoding] hmacMD5StringWithKey:key]; } - (NSString *)hmacSHA1StringWithKey:(NSString *)key { return [[self dataUsingEncoding:NSUTF8StringEncoding] hmacSHA1StringWithKey:key]; } - (NSString *)hmacSHA224StringWithKey:(NSString *)key { return [[self dataUsingEncoding:NSUTF8StringEncoding] hmacSHA224StringWithKey:key]; } - (NSString *)hmacSHA256StringWithKey:(NSString *)key { return [[self dataUsingEncoding:NSUTF8StringEncoding] hmacSHA256StringWithKey:key]; } - (NSString *)hmacSHA384StringWithKey:(NSString *)key { return [[self dataUsingEncoding:NSUTF8StringEncoding] hmacSHA384StringWithKey:key]; } - (NSString *)hmacSHA512StringWithKey:(NSString *)key { return [[self dataUsingEncoding:NSUTF8StringEncoding] hmacSHA512StringWithKey:key]; } - (NSString *)base64EncodedString { return [[self dataUsingEncoding:NSUTF8StringEncoding] base64EncodedString]; } + (NSString *)stringWithBase64EncodedString:(NSString *)base64EncodedString { NSData *data = [NSData dataWithBase64EncodedString:base64EncodedString]; return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; } - (NSString *)stringByURLEncode { if ([self respondsToSelector:@selector(stringByAddingPercentEncodingWithAllowedCharacters:)]) { /** AFNetworking/AFURLRequestSerialization.m Returns a percent-escaped string following RFC 3986 for a query string key or value. RFC 3986 states that the following characters are "reserved" characters. - General Delimiters: ":", "#", "[", "]", "@", "?", "/" - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/" should be percent-escaped in the query string. - parameter string: The string to be percent-escaped. - returns: The percent-escaped string. */ static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4 static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;="; NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; [allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]]; static NSUInteger const batchSize = 50; NSUInteger index = 0; NSMutableString *escaped = @"".mutableCopy; while (index < self.length) { NSUInteger length = MIN(self.length - index, batchSize); NSRange range = NSMakeRange(index, length); // To avoid breaking up character sequences such as 👴🏻👮🏽 range = [self rangeOfComposedCharacterSequencesForRange:range]; NSString *substring = [self substringWithRange:range]; NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; [escaped appendString:encoded]; index += range.length; } return escaped; } else { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" CFStringEncoding cfEncoding = CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding); NSString *encoded = (__bridge_transfer NSString *) CFURLCreateStringByAddingPercentEscapes( kCFAllocatorDefault, (__bridge CFStringRef)self, NULL, CFSTR("!#$&'()*+,/:;=?@[]"), cfEncoding); return encoded; #pragma clang diagnostic pop } } - (NSString *)stringByURLDecode { if ([self respondsToSelector:@selector(stringByRemovingPercentEncoding)]) { return [self stringByRemovingPercentEncoding]; } else { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" CFStringEncoding en = CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding); NSString *decoded = [self stringByReplacingOccurrencesOfString:@"+" withString:@" "]; decoded = (__bridge_transfer NSString *) CFURLCreateStringByReplacingPercentEscapesUsingEncoding( NULL, (__bridge CFStringRef)decoded, CFSTR(""), en); return decoded; #pragma clang diagnostic pop } } - (NSString *)stringByEscapingHTML { NSUInteger len = self.length; if (!len) return self; unichar *buf = malloc(sizeof(unichar) * len); if (!buf) return self; [self getCharacters:buf range:NSMakeRange(0, len)]; NSMutableString *result = [NSMutableString string]; for (int i = 0; i < len; i++) { unichar c = buf[i]; NSString *esc = nil; switch (c) { case 34: esc = @"""; break; case 38: esc = @"&"; break; case 39: esc = @"'"; break; case 60: esc = @"<"; break; case 62: esc = @">"; break; default: break; } if (esc) { [result appendString:esc]; } else { CFStringAppendCharacters((CFMutableStringRef)result, &c, 1); } } free(buf); return result; } - (CGSize)sizeForFont:(UIFont *)font size:(CGSize)size mode:(NSLineBreakMode)lineBreakMode { CGSize result; if (!font) font = [UIFont systemFontOfSize:12]; if ([self respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) { NSMutableDictionary *attr = [NSMutableDictionary new]; attr[NSFontAttributeName] = font; if (lineBreakMode != NSLineBreakByWordWrapping) { NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; paragraphStyle.lineBreakMode = lineBreakMode; attr[NSParagraphStyleAttributeName] = paragraphStyle; } CGRect rect = [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attr context:nil]; result = rect.size; } else { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" result = [self sizeWithFont:font constrainedToSize:size lineBreakMode:lineBreakMode]; #pragma clang diagnostic pop } return result; } - (CGFloat)widthForFont:(UIFont *)font { CGSize size = [self sizeForFont:font size:CGSizeMake(HUGE, HUGE) mode:NSLineBreakByWordWrapping]; return size.width; } - (CGFloat)heightForFont:(UIFont *)font width:(CGFloat)width { CGSize size = [self sizeForFont:font size:CGSizeMake(width, HUGE) mode:NSLineBreakByWordWrapping]; return size.height; } - (BOOL)matchesRegex:(NSString *)regex options:(NSRegularExpressionOptions)options { NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:regex options:options error:NULL]; if (!pattern) return NO; return ([pattern numberOfMatchesInString:self options:0 range:NSMakeRange(0, self.length)] > 0); } - (void)enumerateRegexMatches:(NSString *)regex options:(NSRegularExpressionOptions)options usingBlock:(void (^)(NSString *match, NSRange matchRange, BOOL *stop))block { if (regex.length == 0 || !block) return; NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:regex options:options error:nil]; if (!regex) return; [pattern enumerateMatchesInString:self options:kNilOptions range:NSMakeRange(0, self.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { block([self substringWithRange:result.range], result.range, stop); }]; } - (NSString *)stringByReplacingRegex:(NSString *)regex options:(NSRegularExpressionOptions)options withString:(NSString *)replacement; { NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:regex options:options error:nil]; if (!pattern) return self; return [pattern stringByReplacingMatchesInString:self options:0 range:NSMakeRange(0, [self length]) withTemplate:replacement]; } - (char)charValue { return self.numberValue.charValue; } - (unsigned char) unsignedCharValue { return self.numberValue.unsignedCharValue; } - (short) shortValue { return self.numberValue.shortValue; } - (unsigned short) unsignedShortValue { return self.numberValue.unsignedShortValue; } - (unsigned int) unsignedIntValue { return self.numberValue.unsignedIntValue; } - (long) longValue { return self.numberValue.longValue; } - (unsigned long) unsignedLongValue { return self.numberValue.unsignedLongValue; } - (unsigned long long) unsignedLongLongValue { return self.numberValue.unsignedLongLongValue; } - (NSUInteger) unsignedIntegerValue { return self.numberValue.unsignedIntegerValue; } + (NSString *)stringWithUUID { CFUUIDRef uuid = CFUUIDCreate(NULL); CFStringRef string = CFUUIDCreateString(NULL, uuid); CFRelease(uuid); return (__bridge_transfer NSString *)string; } + (NSString *)stringWithUTF32Char:(UTF32Char)char32 { char32 = NSSwapHostIntToLittle(char32); return [[NSString alloc] initWithBytes:&char32 length:4 encoding:NSUTF32LittleEndianStringEncoding]; } + (NSString *)stringWithUTF32Chars:(const UTF32Char *)char32 length:(NSUInteger)length { return [[NSString alloc] initWithBytes:(const void *)char32 length:length * 4 encoding:NSUTF32LittleEndianStringEncoding]; } - (void)enumerateUTF32CharInRange:(NSRange)range usingBlock:(void (^)(UTF32Char char32, NSRange range, BOOL *stop))block { NSString *str = self; if (range.location != 0 || range.length != self.length) { str = [self substringWithRange:range]; } NSUInteger len = [str lengthOfBytesUsingEncoding:NSUTF32StringEncoding] / 4; UTF32Char *char32 = (UTF32Char *)[str cStringUsingEncoding:NSUTF32LittleEndianStringEncoding]; if (len == 0 || char32 == NULL) return; NSUInteger location = 0; BOOL stop = NO; NSRange subRange; UTF32Char oneChar; for (NSUInteger i = 0; i < len; i++) { oneChar = char32[i]; subRange = NSMakeRange(location, oneChar > 0xFFFF ? 2 : 1); block(oneChar, subRange, &stop); if (stop) return; location += subRange.length; } } - (NSString *)stringByTrim { NSCharacterSet *set = [NSCharacterSet whitespaceAndNewlineCharacterSet]; return [self stringByTrimmingCharactersInSet:set]; } - (NSString *)stringByAppendingNameScale:(CGFloat)scale { if (fabs(scale - 1) <= __FLT_EPSILON__ || self.length == 0 || [self hasSuffix:@"/"]) return self.copy; return [self stringByAppendingFormat:@"@%@x", @(scale)]; } - (NSString *)stringByAppendingPathScale:(CGFloat)scale { if (fabs(scale - 1) <= __FLT_EPSILON__ || self.length == 0 || [self hasSuffix:@"/"]) return self.copy; NSString *ext = self.pathExtension; NSRange extRange = NSMakeRange(self.length - ext.length, 0); if (ext.length > 0) extRange.location -= 1; NSString *scaleStr = [NSString stringWithFormat:@"@%@x", @(scale)]; return [self stringByReplacingCharactersInRange:extRange withString:scaleStr]; } - (CGFloat)pathScale { if (self.length == 0 || [self hasSuffix:@"/"]) return 1; NSString *name = self.stringByDeletingPathExtension; __block CGFloat scale = 1; [name enumerateRegexMatches:@"@[0-9]+\\.?[0-9]*x$" options:NSRegularExpressionAnchorsMatchLines usingBlock: ^(NSString *match, NSRange matchRange, BOOL *stop) { scale = [match substringWithRange:NSMakeRange(1, match.length - 2)].doubleValue; }]; return scale; } - (BOOL)isNotBlank { NSCharacterSet *blank = [NSCharacterSet whitespaceAndNewlineCharacterSet]; for (NSInteger i = 0; i < self.length; ++i) { unichar c = [self characterAtIndex:i]; if (![blank characterIsMember:c]) { return YES; } } return NO; } - (BOOL)containsString:(NSString *)string { if (string == nil) return NO; return [self rangeOfString:string].location != NSNotFound; } - (BOOL)containsCharacterSet:(NSCharacterSet *)set { if (set == nil) return NO; return [self rangeOfCharacterFromSet:set].location != NSNotFound; } - (NSNumber *)numberValue { return [NSNumber numberWithString:self]; } - (NSData *)dataValue { return [self dataUsingEncoding:NSUTF8StringEncoding]; } - (NSRange)rangeOfAll { return NSMakeRange(0, self.length); } - (id)jsonValueDecoded { return [[self dataValue] jsonValueDecoded]; } + (NSString *)stringNamed:(NSString *)name { NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@""]; NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]; if (!str) { path = [[NSBundle mainBundle] pathForResource:name ofType:@"txt"]; str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]; } return str; } @end