123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- //
- // NSString+YYAdd.m
- // YYKit <https://github.com/ibireme/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 "UIDevice+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
|