diff --git a/RegExCategories.h b/RegExCategories.h index 95c68d5..09aeb36 100644 --- a/RegExCategories.h +++ b/RegExCategories.h @@ -185,10 +185,10 @@ * Returns the index of the first match of the passed string. * * ie. - * int i = [RX(@"\d+") indexOf:@"Buy 1 dog or buy 2?"]; // => 4 + * NSUInteger i = [RX(@"\d+") indexOf:@"Buy 1 dog or buy 2?"]; // => 4 */ -- (int) indexOf:(NSString*)str; +- (NSUInteger) indexOf:(NSString*)str; /** @@ -248,7 +248,7 @@ * => @[ @"me@example.com", @"you@example.com" ] */ -- (NSArray*) matches:(NSString*)str; +- (NSArray *) matches:(NSString*)str; /** @@ -272,7 +272,7 @@ * NSArray* matches = [str matchesWithDetails:RX(@"\\w+[@]\\w+[.](\\w+)")]; */ -- (NSArray*) matchesWithDetails:(NSString*)str; +- (NSArray *) matchesWithDetails:(NSString*)str; /** @@ -346,10 +346,10 @@ * the regex passed in. * * ie. - * int i = [@"Buy 1 dog or buy 2?" indexOf:RX(@"\d+")]; // => 4 + * NSUInteger i = [@"Buy 1 dog or buy 2?" indexOf:RX(@"\d+")]; // => 4 */ -- (int) indexOf:(NSRegularExpression*)rx; +- (NSUInteger) indexOf:(NSRegularExpression*)rx; /** diff --git a/RegExCategories.m b/RegExCategories.m index 019f77a..a0f729e 100644 --- a/RegExCategories.m +++ b/RegExCategories.m @@ -56,10 +56,10 @@ - (BOOL) isMatch:(NSString*)matchee return [self numberOfMatchesInString:matchee options:0 range:NSMakeRange(0, matchee.length)] > 0; } -- (int) indexOf:(NSString*)matchee +- (NSUInteger) indexOf:(NSString*)matchee { NSRange range = [self rangeOfFirstMatchInString:matchee options:0 range:NSMakeRange(0, matchee.length)]; - return range.location == NSNotFound ? -1 : (int)range.location; + return range.location; // Can return NSNotFound! } - (NSArray*) split:(NSString *)str @@ -81,7 +81,7 @@ - (NSArray*) split:(NSString *)str (matchingRanges.count == 0 ? str.length : [matchingRanges[0] rangeValue].location))]]; //add between splits ranges and last range - for(int i=0; i=0; i--) { - NSTextCheckingResult* match = matches[i]; - NSString* matchStr = [string substringWithRange:match.range]; - NSString* replacement = replacer(matchStr); - [result replaceCharactersInRange:match.range withString:replacement]; - } + //process matches + __block NSInteger offset = 0; + [self enumerateMatchesInString:string + options:0 + range:NSMakeRange(0, string.length) + usingBlock: + ^(NSTextCheckingResult * _Nullable match, NSMatchingFlags flags, BOOL * _Nonnull stop) { + NSRange range = match.range; + + NSString* matchStr = [string substringWithRange:range]; + NSString* replacement = replacer(matchStr); + if (replacement == nil) return; + + range.location += offset; + + [result replaceCharactersInRange:range withString:replacement]; + + offset += replacement.length - match.range.length; + }]; return result; } @@ -134,21 +143,30 @@ - (NSString*) replace:(NSString *)string withDetailsBlock:(NSString*(^)(RxMatch* //copy the string so we can replace subsections NSMutableString* replaced = [string mutableCopy]; - //get matches - NSArray* matches = [self matchesInString:string options:0 range:NSMakeRange(0, string.length)]; - - //replace each match (right to left so indexing doesn't get messed up) - for (int i=(int)matches.count-1; i>=0; i--) { - NSTextCheckingResult* result = matches[i]; - RxMatch* match = [self resultToMatch:result original:string]; - NSString* replacement = replacer(match); - [replaced replaceCharactersInRange:result.range withString:replacement]; - } + //process matches + __block NSInteger offset = 0; + [self enumerateMatchesInString:string + options:0 + range:NSMakeRange(0, string.length) + usingBlock: + ^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) { + NSRange range = result.range; + + RxMatch* match = [self resultToMatch:result original:string]; + NSString* replacement = replacer(match); + if (replacement == nil) return; + + range.location += offset; + + [replaced replaceCharactersInRange:range withString:replacement]; + + offset += replacement.length - result.range.length; + }]; return replaced; } -- (NSArray*) matches:(NSString*)str +- (NSArray *) matches:(NSString*)str { NSMutableArray* matches = [NSMutableArray array]; @@ -179,7 +197,7 @@ - (RxMatch*) resultToMatch:(NSTextCheckingResult*)result original:(NSString*)ori //groups NSMutableArray* groups = [NSMutableArray array]; - for(int i=0; i *) matchesWithDetails:(NSString*)str { NSMutableArray* matches = [NSMutableArray array]; @@ -238,7 +256,7 @@ - (BOOL) isMatch:(NSRegularExpression*)rx return [rx isMatch:self]; } -- (int) indexOf:(NSRegularExpression*)rx +- (NSUInteger) indexOf:(NSRegularExpression*)rx { return [rx indexOf:self]; } diff --git a/TestProject/Objective-C-Regex-Categories.xcodeproj/project.pbxproj b/TestProject/Objective-C-Regex-Categories.xcodeproj/project.pbxproj index 73a4735..0143c6d 100644 --- a/TestProject/Objective-C-Regex-Categories.xcodeproj/project.pbxproj +++ b/TestProject/Objective-C-Regex-Categories.xcodeproj/project.pbxproj @@ -30,7 +30,6 @@ BC7CC817184AF846007FCB6B /* NSString+IndexOf.m in Sources */ = {isa = PBXBuildFile; fileRef = BC7CC816184AF846007FCB6B /* NSString+IndexOf.m */; }; BC7CC819184AF963007FCB6B /* NSString+IsMatch.m in Sources */ = {isa = PBXBuildFile; fileRef = BC7CC818184AF963007FCB6B /* NSString+IsMatch.m */; }; BC7CC81B184AF9ED007FCB6B /* NSString+Initialization.m in Sources */ = {isa = PBXBuildFile; fileRef = BC7CC81A184AF9ED007FCB6B /* NSString+Initialization.m */; }; - BCCD4868185009E80038ADCB /* docs.md in Resources */ = {isa = PBXBuildFile; fileRef = BCCD4863185009E80038ADCB /* docs.md */; }; BCCD4869185009E80038ADCB /* LICENSE.txt in Resources */ = {isa = PBXBuildFile; fileRef = BCCD4864185009E80038ADCB /* LICENSE.txt */; }; BCCD486A185009E80038ADCB /* RegExCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = BCCD4866185009E80038ADCB /* RegExCategories.m */; }; BCCD486B185009E80038ADCB /* readme.md in Resources */ = {isa = PBXBuildFile; fileRef = BCCD4867185009E80038ADCB /* readme.md */; }; @@ -74,7 +73,7 @@ BC7CC816184AF846007FCB6B /* NSString+IndexOf.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+IndexOf.m"; sourceTree = ""; }; BC7CC818184AF963007FCB6B /* NSString+IsMatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+IsMatch.m"; sourceTree = ""; }; BC7CC81A184AF9ED007FCB6B /* NSString+Initialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Initialization.m"; sourceTree = ""; }; - BCCD4863185009E80038ADCB /* docs.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = docs.md; path = ../docs.md; sourceTree = ""; }; + BCCD4863185009E80038ADCB /* readme.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = readme.md; path = ../readme.md; sourceTree = ""; }; BCCD4864185009E80038ADCB /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LICENSE.txt; path = ../LICENSE.txt; sourceTree = ""; }; BCCD4865185009E80038ADCB /* RegExCategories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegExCategories.h; path = ../RegExCategories.h; sourceTree = ""; }; BCCD4866185009E80038ADCB /* RegExCategories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RegExCategories.m; path = ../RegExCategories.m; sourceTree = ""; }; @@ -108,7 +107,7 @@ BC7CC7C61848F63D007FCB6B = { isa = PBXGroup; children = ( - BCCD4863185009E80038ADCB /* docs.md */, + BCCD4863185009E80038ADCB /* readme.md */, BCCD4864185009E80038ADCB /* LICENSE.txt */, BCCD4865185009E80038ADCB /* RegExCategories.h */, BCCD4866185009E80038ADCB /* RegExCategories.m */, @@ -119,6 +118,7 @@ BC7CC7D01848F63D007FCB6B /* Products */, ); sourceTree = ""; + usesTabs = 0; }; BC7CC7D01848F63D007FCB6B /* Products */ = { isa = PBXGroup; @@ -236,7 +236,7 @@ BC7CC7C71848F63D007FCB6B /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0500; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Bendy Tree"; TargetAttributes = { BC7CC7E91848F63E007FCB6B = { @@ -270,7 +270,6 @@ BCCD4869185009E80038ADCB /* LICENSE.txt in Resources */, BC7CC7DD1848F63E007FCB6B /* InfoPlist.strings in Resources */, BCCD486B185009E80038ADCB /* readme.md in Resources */, - BCCD4868185009E80038ADCB /* docs.md in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -349,7 +348,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -364,6 +362,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -389,7 +388,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -427,6 +425,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Objective-C-Regex-Categories/Objective-C-Regex-Categories-Prefix.pch"; INFOPLIST_FILE = "Objective-C-Regex-Categories/Objective-C-Regex-Categories-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.bendytree.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; @@ -440,6 +439,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Objective-C-Regex-Categories/Objective-C-Regex-Categories-Prefix.pch"; INFOPLIST_FILE = "Objective-C-Regex-Categories/Objective-C-Regex-Categories-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.bendytree.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; @@ -448,7 +448,6 @@ BC7CC7FF1848F63E007FCB6B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Objective-C-Regex-Categories.app/Objective-C-Regex-Categories"; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", @@ -462,6 +461,7 @@ "$(inherited)", ); INFOPLIST_FILE = "Objective-C-Regex-CategoriesTests/Objective-C-Regex-CategoriesTests-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.bendytree.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUNDLE_LOADER)"; WRAPPER_EXTENSION = xctest; @@ -471,7 +471,6 @@ BC7CC8001848F63E007FCB6B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Objective-C-Regex-Categories.app/Objective-C-Regex-Categories"; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", @@ -481,6 +480,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Objective-C-Regex-Categories/Objective-C-Regex-Categories-Prefix.pch"; INFOPLIST_FILE = "Objective-C-Regex-CategoriesTests/Objective-C-Regex-CategoriesTests-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.bendytree.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUNDLE_LOADER)"; WRAPPER_EXTENSION = xctest; diff --git a/TestProject/Objective-C-Regex-Categories.xcodeproj/xcshareddata/xcschemes/Objective-C-Regex-Categories.xcscheme b/TestProject/Objective-C-Regex-Categories.xcodeproj/xcshareddata/xcschemes/Objective-C-Regex-Categories.xcscheme index 3226652..ca60db1 100644 --- a/TestProject/Objective-C-Regex-Categories.xcodeproj/xcshareddata/xcschemes/Objective-C-Regex-Categories.xcscheme +++ b/TestProject/Objective-C-Regex-Categories.xcodeproj/xcshareddata/xcschemes/Objective-C-Regex-Categories.xcscheme @@ -1,6 +1,6 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -62,17 +62,21 @@ ReferencedContainer = "container:Objective-C-Regex-Categories.xcodeproj"> + + - + - + CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.bendytree.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/TestProject/Objective-C-Regex-CategoriesTests/NSRegularExpression+IndexOf.m b/TestProject/Objective-C-Regex-CategoriesTests/NSRegularExpression+IndexOf.m index 8710de2..5ea17b0 100644 --- a/TestProject/Objective-C-Regex-CategoriesTests/NSRegularExpression+IndexOf.m +++ b/TestProject/Objective-C-Regex-CategoriesTests/NSRegularExpression+IndexOf.m @@ -14,19 +14,19 @@ @implementation NSRegularExpression_IndexOf - (void) test_indexOf_on_matching_string_returns_index_of_first_match { - int i = [RX(@"\\d") indexOf:@"You 2 can have 3 cows."]; + NSUInteger i = [RX(@"\\d") indexOf:@"You 2 can have 3 cows."]; XCTAssertEqual(i, 4, @"Expected to match index 4."); } - (void) test_indexOf_on_non_matching_string_returns_negative_one { - int i = [RX(@"\\d") indexOf:@"You two can have three cows."]; - XCTAssertEqual(i, -1, @"Expected to match index -1."); + NSUInteger i = [RX(@"\\d") indexOf:@"You two can have three cows."]; + XCTAssertEqual(i, NSNotFound); } - (void) test_indexOf_on_matching_rx_returns_index_of_first_match { - int i = [RX(@"\\d") indexOf:@"You 2 can have 3 cows."]; + NSUInteger i = [RX(@"\\d") indexOf:@"You 2 can have 3 cows."]; XCTAssertEqual(i, 4, @"Expected to match index 4."); } diff --git a/TestProject/Objective-C-Regex-CategoriesTests/NSRegularExpression+Replace.m b/TestProject/Objective-C-Regex-CategoriesTests/NSRegularExpression+Replace.m index 22f501e..2c604b0 100644 --- a/TestProject/Objective-C-Regex-CategoriesTests/NSRegularExpression+Replace.m +++ b/TestProject/Objective-C-Regex-CategoriesTests/NSRegularExpression+Replace.m @@ -34,12 +34,18 @@ - (void) test_replace_replaces_with_nil_callback_returns_original_string { NSString* result = [RX(@"[A-Z]+") replace:@"i love COW" withBlock:nil]; XCTAssertEqualObjects(result, @"i love COW", @"Result should be unchanged."); + + NSString* result2 = [RX(@"\\w+") replace:@"hi bud" withBlock:^NSString *(NSString *match) { return nil; }]; + XCTAssertEqualObjects(result2, @"hi bud"); } - (void) test_replace_replaces_with_sets_callback { NSString* result = [RX(@"\\w+") replace:@"hi bud" withDetailsBlock:^(RxMatch* match){ return [NSString stringWithFormat:@"%lu", (unsigned long)match.value.length]; }]; XCTAssertEqualObjects(result, @"2 3", @"Result should be '2 3'."); + + NSString* result2 = [RX(@"\\w+") replace:@"hi bud" withDetailsBlock:^NSString *(RxMatch *match){ return nil; }]; + XCTAssertEqualObjects(result2, @"hi bud"); } - (void) test_replace_replaces_with_nil_sets_callback_returns_original_string diff --git a/TestProject/Objective-C-Regex-CategoriesTests/NSString+IndexOf.m b/TestProject/Objective-C-Regex-CategoriesTests/NSString+IndexOf.m index bdc7975..247567e 100644 --- a/TestProject/Objective-C-Regex-CategoriesTests/NSString+IndexOf.m +++ b/TestProject/Objective-C-Regex-CategoriesTests/NSString+IndexOf.m @@ -14,7 +14,7 @@ @implementation NSString_IndexOf - (void) test_indexOf_can_be_called_on_an_NSString { - int i = [@"You 2 can have 3 cows." indexOf:RX(@"\\d")]; + NSUInteger i = [@"You 2 can have 3 cows." indexOf:RX(@"\\d")]; XCTAssertEqual(i, 4, @"Expected to match index 4."); } diff --git a/TestProject/Objective-C-Regex-CategoriesTests/Objective-C-Regex-CategoriesTests-Info.plist b/TestProject/Objective-C-Regex-CategoriesTests/Objective-C-Regex-CategoriesTests-Info.plist index e050c12..169b6f7 100644 --- a/TestProject/Objective-C-Regex-CategoriesTests/Objective-C-Regex-CategoriesTests-Info.plist +++ b/TestProject/Objective-C-Regex-CategoriesTests/Objective-C-Regex-CategoriesTests-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.bendytree.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/readme.md b/readme.md index 20287af..8014f59 100644 --- a/readme.md +++ b/readme.md @@ -250,18 +250,18 @@ Get the character index of the first match. If no match is found, then `-1`. ######From NSRegularExpression - int index = [RX(@"\\d+") indexOf:@"Buy 1 dog or buy 2?"]; + NSUInteger index = [RX(@"\\d+") indexOf:@"Buy 1 dog or buy 2?"]; // => 4 - int index = [RX(@"\\d+") indexOf:@"Buy a dog?"]; + NSUInteger index = [RX(@"\\d+") indexOf:@"Buy a dog?"]; // => -1 ######From NSString - int index = [@"Buy 1 dog or buy 2?" indexOf:RX(@"\\d+")]; + NSUInteger index = [@"Buy 1 dog or buy 2?" indexOf:RX(@"\\d+")]; // => 4 - int index = [@"Buy a dog?" indexOf:RX(@"\\d+")]; + NSUInteger index = [@"Buy a dog?" indexOf:RX(@"\\d+")]; // => -1