Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -11,10 +11,11 @@ #include #include #import "OFObject.h" +#import "OFArray.h" /** * A class for managing strings. */ @interface OFString: OFObject @@ -147,6 +148,14 @@ /** * Lower the OFString. */ - lower; + +/** + * Splits an OFString into an OFArray of OFStrings. + * + * \param delimiter The delimiter for splitting + * \return An autoreleased OFArray with the splitted string + */ +- (OFArray*)splitWithDelimiter: (OFString*)delimiter; @end Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -10,14 +10,16 @@ */ #import "config.h" #include +#include #include #import "OFString.h" #import "OFMutableString.h" +#import "OFAutoreleasePool.h" #import "OFExceptions.h" #import "OFMacros.h" @implementation OFString + string @@ -152,6 +154,61 @@ - lower { @throw [OFNotImplementedException newWithClass: isa andSelector: _cmd]; } + +- (OFArray*)splitWithDelimiter: (OFString*)delimiter +{ + OFAutoreleasePool *pool; + OFArray *array = [[OFArray alloc] init]; + const char *delim = [delimiter cString]; + size_t delim_len = [delimiter length]; + size_t i, last; + + @try { + pool = [[OFAutoreleasePool alloc] init]; + } @catch (OFException *e) { + [array release]; + @throw e; + } + + @try { + for (i = 0, last = 0; i <= length; i++) { + if (OF_UNLIKELY(i == length || + !memcmp(string + i, delim, delim_len))) { + OFString *str; + char *tmp; + + /* + * We can't use [self allocWithSize:] here as + * self might be a @""-literal. + */ + if ((tmp = malloc(i - last + 1)) == NULL) + @throw [OFNoMemException + newWithClass: isa + andSize: i - last + 1]; + memcpy(tmp, string + last, i - last); + tmp[i - last] = '\0'; + @try { + str = [OFString stringWithCString: tmp]; + } @finally { + free(tmp); + } + + [array add: str]; + [pool releaseObjects]; + + i += delim_len - 1; + last = i + 1; + } + } + } @catch (OFException *e) { + [array release]; + @throw e; + } @finally { + [pool release]; + } + + return [array autorelease]; +} @end Index: tests/OFString/OFString.m ================================================================== --- tests/OFString/OFString.m +++ tests/OFString/OFString.m @@ -13,20 +13,22 @@ #include #include #import "OFString.h" -#import "OFExceptions.h" +#import "OFConstString.h" +#import "OFArray.h" #import "OFAutoreleasePool.h" +#import "OFExceptions.h" #ifndef _WIN32 #define ZD "%zd" #else #define ZD "%u" #endif -#define NUM_TESTS 15 +#define NUM_TESTS 21 #define SUCCESS \ printf("\r\033[1;%dmTests successful: " ZD "/%d\033[0m", \ (i == NUM_TESTS - 1 ? 32 : 33), i + 1, NUM_TESTS); \ fflush(stdout); #define FAIL \ @@ -51,16 +53,18 @@ int main() { size_t i = 0; + size_t j = 0; OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFString *s1 = [OFString stringWithCString: "test"]; OFString *s2 = [OFString stringWithCString: ""]; OFString *s3; OFString *s4 = [OFString string]; + OFArray *a; s3 = [s1 copy]; CHECK([s1 isEqual: s3]) CHECK(![s1 isEqual: [[OFObject alloc] init]]) @@ -94,10 +98,18 @@ s1 = [OFString stringWithFormat: "%s: %d", "test", 123]; CHECK(!strcmp([s1 cString], "test: 123")) [s1 appendWithFormatCString: "%02X", 15]; CHECK(!strcmp([s1 cString], "test: 1230F")) + + a = [@"fooXXbarXXXXbazXXXX" splitWithDelimiter: @"XX"]; + CHECK([[a object: j++] isEqual: @"foo"]) + CHECK([[a object: j++] isEqual: @"bar"]) + CHECK([[a object: j++] isEqual: @""]) + CHECK([[a object: j++] isEqual: @"baz"]) + CHECK([[a object: j++] isEqual: @""]) + CHECK([[a object: j++] isEqual: @""]) puts(""); return 0; }