Last active
April 23, 2016 03:37
-
-
Save boredzo/8640626 to your computer and use it in GitHub Desktop.
Category on NSString to enumerate a string's substrings that match another string
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
@interface NSString (PRHEnumerateMatches) | |
- (NSUInteger) enumerateSubstringsMatchingString_PRH:(NSString *)otherString | |
options:(NSStringCompareOptions)mask | |
usingBlock:(void (^)(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop))block; | |
@end | |
static void test(NSString *stringToFind, NSString *stringToSearch, NSStringCompareOptions options); | |
int main(int argc, char *argv[]) { | |
@autoreleasepool { | |
NSString *stringToFind, *stringToSearch; | |
stringToFind = @"and"; | |
stringToSearch = @"One, two! One, two! And through and through\n" | |
@"The vorpal blade went snicker-snack!\n" | |
@"He left it dead, and with its head\n" | |
@"He went galumphing back."; | |
test(stringToFind, stringToSearch, NSCaseInsensitiveSearch); | |
stringToSearch = @"Hello world!"; | |
stringToFind = @"world!"; | |
test(stringToFind, stringToSearch, 0); | |
stringToSearch = @"Hello world"; | |
stringToFind = @"world!"; | |
test(stringToFind, stringToSearch, 0); | |
} | |
return EXIT_SUCCESS; | |
} | |
static void test(NSString *stringToFind, NSString *stringToSearch, NSStringCompareOptions options) { | |
void (^block)(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) = ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop){ | |
NSLog(@"%lu-character string[%lu:%lu] = '%@'", stringToSearch.length, substringRange.location, NSMaxRange(substringRange), substring); | |
}; | |
NSUInteger count = [stringToSearch enumerateSubstringsMatchingString_PRH:stringToFind | |
options:options | |
usingBlock:block]; | |
NSLog(@"Number of matches: %lu", count); | |
} | |
@implementation NSString (PRHEnumerateMatches) | |
- (NSUInteger) enumerateSubstringsMatchingString_PRH:(NSString *)stringToFind | |
options:(NSStringCompareOptions)mask | |
usingBlock:(void (^)(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop))block | |
{ | |
NSUInteger count = 0; | |
NSUInteger selfLength = self.length; | |
NSRange searchRange = { 0, selfLength }; | |
NSRange foundRange; | |
BOOL stop = NO; | |
while (( ! stop ) && (foundRange = [self rangeOfString:stringToFind options:mask range:searchRange]).location != NSNotFound) { | |
++count; | |
if (block != NULL) { | |
@autoreleasepool { | |
NSString *substring = [self substringWithRange:foundRange]; | |
block(substring, foundRange, /*TODO include terminators and separators in enclosingRange as described in enumerateSubstringsWithOptions:: docs*/ foundRange, &stop); | |
} | |
} | |
searchRange.location = NSMaxRange(foundRange); | |
if (searchRange.location >= self.length) | |
break; | |
searchRange.length = selfLength - searchRange.location; | |
} | |
return count; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment