Permalink
Browse files

improved helper functions inspired by ruby.

  • Loading branch information...
1 parent 3dae527 commit e6c0e648a5a11f7035a2a568bd000ead22207e54 @psychs committed Jul 25, 2008

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>net.limechat.CocoaOnigurumaTest</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+</dict>
+</plist>
@@ -11,19 +11,31 @@
@interface NSString (OnigRegexpUtility)
-// expression is OnigRegexp or NSString
+// pattern is OnigRegexp or NSString
-- (NSRange)rangeOfRegexp:(id)expression;
-- (NSArray*)splitByRegexp:(id)expression;
+- (NSRange)rangeOfRegexp:(id)pattern;
+
+// based on ruby's split
+
+- (NSArray*)split;
+- (NSArray*)splitByRegexp:(id)pattern;
+- (NSArray*)splitByRegexp:(id)pattern limit:(int)limit;
+
+// based on ruby's gsub
+
+- (NSString*)replaceByRegexp:(id)pattern with:(NSString*)string;
+- (NSString*)replaceAllByRegexp:(id)pattern with:(NSString*)string;
@end
@interface NSMutableString (OnigRegexpUtility)
-// expression is OnigRegexp or NSString
+// pattern is OnigRegexp or NSString
+
+// based on ruby's gsub
-- (BOOL)replaceByRegexp:(id)expression with:(NSString*)string;
-- (int)replaceAllByRegexp:(id)expression with:(NSString*)string;
+- (NSMutableString*)replaceByRegexp:(id)pattern with:(NSString*)string;
+- (NSMutableString*)replaceAllByRegexp:(id)pattern with:(NSString*)string;
@end
@@ -4,77 +4,200 @@
#import "OnigRegexpUtility.h"
-@implementation NSString (OnigRegexpUtility)
+@interface NSString (OnigRegexpNSStringUtilityPrivate)
+- (NSArray*)__split:(id)pattern limit:(NSNumber*)limit;
+@end
+
+@implementation NSString (OnigRegexpNSStringUtility)
-- (NSRange)rangeOfRegexp:(id)expression
+- (NSRange)rangeOfRegexp:(id)pattern
{
- if (![expression isKindOfClass:[OnigRegexp class]]) {
- expression = [OnigRegexp compile:(NSString*)expression];
+ if (![pattern isKindOfClass:[OnigRegexp class]]) {
+ pattern = [OnigRegexp compile:(NSString*)pattern];
}
- OnigResult* res = [expression search:self];
+ OnigResult* res = [pattern search:self];
return res ? [res bodyRange] : NSMakeRange(NSNotFound, 0);
}
-- (NSArray*)splitByRegexp:(id)expression
+- (NSArray*)split
+{
+ return [self splitByRegexp:@" "];
+}
+
+- (NSArray*)splitByRegexp:(id)pattern
{
- if (![expression isKindOfClass:[OnigRegexp class]]) {
- expression = [OnigRegexp compile:(NSString*)expression];
+ return [self __split:pattern limit:nil];
+}
+
+- (NSArray*)splitByRegexp:(id)pattern limit:(int)limit
+{
+ return [self __split:pattern limit:[NSNumber numberWithInt:limit]];
+}
+
+//
+// This implementation is based on ruby 1.8.
+//
+
+- (NSArray*)__split:(id)pattern limit:(NSNumber*)limitNum
+{
+ NSString* target = self;
+
+ if (![pattern isKindOfClass:[OnigRegexp class]]) {
+ if ([pattern isEqual:@" "]) {
+ // If the pattern is a single space,
+ // split by contiguous white spaces,
+ // where leading and trailing white spaces are ignored.
+
+ NSRange r = [target rangeOfRegexp:@"^\\s+"];
+ if (r.location != NSNotFound) {
+ target = [target substringFromIndex:NSMaxRange(r)];
+ }
+ r = [target rangeOfRegexp:@"\\s+$"];
+ if (r.location != NSNotFound) {
+ target = [target substringToIndex:r.location];
+ }
+ pattern = [OnigRegexp compile:@"\\s+"];
+ } else {
+ pattern = [OnigRegexp compile:(NSString*)pattern];
+ }
+ }
+
+ int i = 0;
+ int limit = 0;
+
+ if (limitNum) {
+ limit = [limitNum intValue];
+ if (limit <=0) {
+ limitNum = nil;
+ } else if (limit == 1) {
+ if ([target length] == 0) return [NSArray array];
+ return [NSArray arrayWithObjects:[[target copy] autorelease], nil];
+ }
+ i = 1;
}
NSMutableArray* array = [NSMutableArray array];
- int n = 0;
+ int start = 0;
+ int begin = 0;
+ BOOL lastNull = NO;
+
OnigResult* res;
- while (res = [expression search:self start:n]) {
+ while (res = [pattern search:target start:start]) {
NSRange range = [res bodyRange];
- [array addObject:[self substringWithRange:NSMakeRange(n, range.location - n)]];
- n = NSMaxRange(range);
+ int end = range.location;
+ int right = NSMaxRange(range);
+
+ if (start == end && range.length == 0) {
+ if ([target length] == 0) {
+ [array addObject:@""];
+ break;
+ } else if (lastNull) {
+ [array addObject:[target substringWithRange:NSMakeRange(begin, 1)]];
+ begin = start;
+ } else {
+ start++;
+ lastNull = YES;
+ continue;
+ }
+ } else {
+ [array addObject:[target substringWithRange:NSMakeRange(begin, end-begin)]];
+ begin = start = right;
+ }
+ lastNull = NO;
+
+ if (limitNum && limit <= ++i) break;
}
- if (n < [self length]) {
- [array addObject:[self substringFromIndex:n]];
+
+ if ([target length] > 0 && (limitNum || [target length] > begin || limit < 0)) {
+ if ([target length] == begin) {
+ [array addObject:@""];
+ } else {
+ [array addObject:[target substringFromIndex:begin]];
+ }
+ }
+
+ if (!limitNum && limit == 0) {
+ NSString* last;
+ while ((last = [array lastObject]) && [last length] == 0) {
+ [array removeLastObject];
+ }
}
+
return array;
}
-@end
-
-
-@implementation NSMutableString (OnigRegexpUtility)
-
-- (BOOL)replaceByRegexp:(id)expression with:(NSString*)string
+- (NSString*)replaceByRegexp:(id)pattern with:(NSString*)string
{
- if (![expression isKindOfClass:[OnigRegexp class]]) {
- expression = [OnigRegexp compile:(NSString*)expression];
+ if (![pattern isKindOfClass:[OnigRegexp class]]) {
+ pattern = [OnigRegexp compile:(NSString*)pattern];
}
- OnigResult* res = [expression search:self];
+ OnigResult* res = [pattern search:self];
if (res) {
- [self replaceCharactersInRange:[res bodyRange] withString:string];
- return YES;
+ NSMutableString* s = [[self mutableCopy] autorelease];
+ [s replaceCharactersInRange:[res bodyRange] withString:string];
+ return s;
} else {
- return NO;
+ return [[self mutableCopy] autorelease];
}
}
-- (int)replaceAllByRegexp:(id)expression with:(NSString*)string
+//
+// This implementation is based on ruby 1.8.
+//
+
+- (NSString*)replaceAllByRegexp:(id)pattern with:(NSString*)string
{
- if (![expression isKindOfClass:[OnigRegexp class]]) {
- expression = [OnigRegexp compile:(NSString*)expression];
+ if (![pattern isKindOfClass:[OnigRegexp class]]) {
+ pattern = [OnigRegexp compile:(NSString*)pattern];
+ }
+
+ OnigResult* res = [pattern search:self];
+ if (!res) {
+ return [[self mutableCopy] autorelease];
}
- OnigResult* res;
- int n = 0;
- int count = 0;
- while (res = [expression search:self start:n]) {
+ NSMutableString* s = [NSMutableString string];
+ int offset = 0;
+
+ do {
NSRange range = [res bodyRange];
- [self replaceCharactersInRange:range withString:string];
- int next = range.location + [string length];
- if (n == next) next++;
- n = next;
- count++;
- if ([self length] <= n) break;
+ int len = range.location-offset;
+ if (len > 0) [s appendString:[self substringWithRange:NSMakeRange(offset, len)]];
+ [s appendString:string];
+
+ offset = NSMaxRange(range);
+ if (range.length == 0) {
+ // consume 1 character at least
+ if ([self length] <= offset) break;
+ [s appendString:[self substringWithRange:NSMakeRange(offset, 1)]];
+ offset++;
+ }
+ if ([self length] < offset) break;
+
+ } while (res = [pattern search:self start:offset]);
+
+ if (offset < [self length]) {
+ [s appendString:[self substringFromIndex:offset]];
}
- return count;
+
+ return s;
+}
+
+@end
+
+
+@implementation NSMutableString (OnigRegexpNSMutableStringUtility)
+
+- (NSMutableString*)replaceByRegexp:(id)pattern with:(NSString*)string
+{
+ return (NSMutableString*)[super replaceByRegexp:pattern with:string];
+}
+
+- (NSMutableString*)replaceAllByRegexp:(id)pattern with:(NSString*)string
+{
+ return (NSMutableString*)[super replaceAllByRegexp:pattern with:string];
}
@end
@@ -0,0 +1,37 @@
+#import <Foundation/Foundation.h>
+#import <CocoaOniguruma/OnigRegexp.h>
+
+int main()
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+/*
+ NSLog(@"%@", [@" now's the time" split]);
+ NSLog(@"%@", [@" now's the time" splitByRegexp:@" "]);
+ NSLog(@"%@", [@" now's the time" splitByRegexp:[OnigRegexp compile:@" "]]);
+ NSLog(@"%@", [@"1, 2.34,56, 7" splitByRegexp:@",\\s*"]);
+ NSLog(@"%@", [@"hello" splitByRegexp:@""]);
+ NSLog(@"%@", [@"hello" splitByRegexp:@"" limit:3]);
+ NSLog(@"%@", [@"hi mom" splitByRegexp:@"\\s*"]);
+ NSLog(@"%@", [@"mellow yellow" splitByRegexp:@"ello"]);
+ NSLog(@"%@", [@"1,2,,3,4,," splitByRegexp:@","]);
+ NSLog(@"%@", [@"1,2,,3,4,," splitByRegexp:@"," limit:4]);
+ NSLog(@"%@", [@"1,2,,3,4,," splitByRegexp:@"," limit:-4]);
+ NSLog(@"%@", [@"h ello" splitByRegexp:@"\\s*" limit:3]);
+ NSLog(@"%@", [@"a,b,c" splitByRegexp:@","]);
+ NSLog(@"%@", [@"a,b,,c" splitByRegexp:@","]);
+ NSLog(@"%@", [@"a,b, c" splitByRegexp:@",\\s*"]);
+ NSLog(@"%@", [@"abc" splitByRegexp:@""]);
+ NSLog(@"%@", [@"abc" splitByRegexp:@"^"]);
+ NSLog(@"%@", [@"abc" splitByRegexp:@"$"]);
+ NSLog(@"%@", [@"abc" splitByRegexp:@"^" limit:-1]);
+ NSLog(@"%@", [@"abc" splitByRegexp:@"$" limit:-1]);
+ NSLog(@"%@", [@"abc" splitByRegexp:@"."]);
+ NSLog(@"%@", [@"abc" splitByRegexp:@"." limit:-1]);
+ NSLog(@"%@", [@"abc" splitByRegexp:@""]);
+ NSLog(@"%@", [@"abc" splitByRegexp:@"" limit:-1]);
+*/
+
+ [pool release];
+ return 0;
+}
@@ -0,0 +1,4 @@
+#import <SenTestingKit/SenTestingKit.h>
+
+@interface OnigRegexpTest : SenTestCase
+@end
Oops, something went wrong.

0 comments on commit e6c0e64

Please sign in to comment.