Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -728,10 +728,20 @@ * \param delimiter The delimiter for splitting * \return An autoreleased OFArray with the split string */ - (OFArray*)componentsSeparatedByString: (OFString*)delimiter; +/** + * \brief Splits an OFString into an OFArray of OFStrings. + * + * \param delimiter The delimiter for splitting + * \param skipEmpty Whether empty components should be skipped + * \return An autoreleased OFArray with the split string + */ +- (OFArray*)componentsSeparatedByString: (OFString*)delimiter + skipEmpty: (BOOL)skipEmpty; + /** * \brief Returns the components of the path. * * \return The components of the path */ Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -1523,16 +1523,24 @@ return !compare; } - (OFArray*)componentsSeparatedByString: (OFString*)delimiter { + return [self componentsSeparatedByString: delimiter + skipEmpty: NO]; +} + +- (OFArray*)componentsSeparatedByString: (OFString*)delimiter + skipEmpty: (BOOL)skipEmpty +{ OFAutoreleasePool *pool; OFMutableArray *array = [OFMutableArray array]; const of_unichar_t *string, *delimiterString; size_t length = [self length]; size_t delimiterLength = [delimiter length]; size_t i, last; + OFString *component; pool = [[OFAutoreleasePool alloc] init]; string = [self unicodeString]; delimiterString = [delimiter unicodeString]; @@ -1549,18 +1557,20 @@ for (i = 0, last = 0; i <= length - delimiterLength; i++) { if (memcmp(string + i, delimiterString, delimiterLength * sizeof(of_unichar_t))) continue; - [array addObject: [self substringWithRange: - of_range(last, i - last)]]; + component = [self substringWithRange: of_range(last, i - last)]; + if (!skipEmpty || ![component isEqual: @""]) + [array addObject: component]; i += delimiterLength - 1; last = i + 1; } - [array addObject: - [self substringWithRange: of_range(last, length - last)]]; + component = [self substringWithRange: of_range(last, length - last)]; + if (!skipEmpty || ![component isEqual: @""]) + [array addObject: component]; [array makeImmutable]; [pool release]; Index: src/OFString_UTF8.m ================================================================== --- src/OFString_UTF8.m +++ src/OFString_UTF8.m @@ -888,16 +888,18 @@ return !memcmp(s->cString + (s->cStringLength - cStringLength), [suffix UTF8String], cStringLength); } - (OFArray*)componentsSeparatedByString: (OFString*)delimiter + skipEmpty: (BOOL)skipEmpty { OFAutoreleasePool *pool; OFMutableArray *array; const char *cString = [delimiter UTF8String]; size_t cStringLength = [delimiter UTF8StringLength]; size_t i, last; + OFString *component; array = [OFMutableArray array]; pool = [[OFAutoreleasePool alloc] init]; if (cStringLength > s->cStringLength) { @@ -909,17 +911,21 @@ for (i = 0, last = 0; i <= s->cStringLength - cStringLength; i++) { if (memcmp(s->cString + i, cString, cStringLength)) continue; - [array addObject: - [OFString stringWithUTF8String: s->cString + last - length: i - last]]; + component = [OFString stringWithUTF8String: s->cString + last + length: i - last]; + if (!skipEmpty || ![component isEqual: @""]) + [array addObject: component]; + i += cStringLength - 1; last = i + 1; } - [array addObject: [OFString stringWithUTF8String: s->cString + last]]; + component = [OFString stringWithUTF8String: s->cString + last]; + if (!skipEmpty || ![component isEqual: @""]) + [array addObject: component]; [array makeImmutable]; [pool release]; Index: tests/OFStringTests.m ================================================================== --- tests/OFStringTests.m +++ tests/OFStringTests.m @@ -247,17 +247,27 @@ ![@"foobar" hasSuffix: @"foobar0"]) i = 0; TEST(@"-[componentsSeparatedByString:]", (a = [@"fooXXbarXXXXbazXXXX" componentsSeparatedByString: @"XX"]) && + [a count] == 6 && [[a objectAtIndex: i++] isEqual: @"foo"] && [[a objectAtIndex: i++] isEqual: @"bar"] && [[a objectAtIndex: i++] isEqual: @""] && [[a objectAtIndex: i++] isEqual: @"baz"] && [[a objectAtIndex: i++] isEqual: @""] && [[a objectAtIndex: i++] isEqual: @""]) + i = 0; + TEST(@"-[componentsSeparatedByString:skipEmpty:]", + (a = [@"fooXXbarXXXXbazXXXX" componentsSeparatedByString: @"XX" + skipEmpty: YES]) && + [a count] == 3 && + [[a objectAtIndex: i++] isEqual: @"foo"] && + [[a objectAtIndex: i++] isEqual: @"bar"] && + [[a objectAtIndex: i++] isEqual: @"baz"]) + TEST(@"+[stringWithPath:]", (s[0] = [OFString stringWithPath: @"foo", @"bar", @"baz", nil]) && #ifndef _WIN32 [s[0] isEqual: @"foo/bar/baz"] && #else