Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -278,12 +278,12 @@ enumerator = [pathComponents objectEnumerator]; while ((component = [enumerator nextObject]) != nil) { void *pool2 = objc_autoreleasePoolPush(); if (currentPath != nil) - currentPath = [OFString - stringWithPath: currentPath, component, nil]; + currentPath = [currentPath + stringByAppendingPathComponent: component]; else currentPath = component; if ([currentPath length] > 0 && ![OFFile directoryExistsAtPath: currentPath]) @@ -523,13 +523,13 @@ @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); if ([self directoryExistsAtPath: destination]) { - OFString *filename = [source lastPathComponent]; - destination = [OFString stringWithPath: destination, filename, - nil]; + OFArray *components = [OFArray arrayWithObjects: + destination, [source lastPathComponent], nil]; + destination = [OFString pathWithComponents: components]; } override = [self fileExistsAtPath: destination]; pageSize = [OFSystemInfo pageSize]; @@ -581,13 +581,13 @@ @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); if ([self directoryExistsAtPath: destination]) { - OFString *filename = [source lastPathComponent]; - destination = [OFString stringWithPath: destination, filename, - nil]; + OFArray *components = [OFArray arrayWithObjects: + destination, [source lastPathComponent], nil]; + destination = [OFString pathWithComponents: components]; } #ifndef _WIN32 if (rename([source cStringWithEncoding: OF_STRING_ENCODING_NATIVE], [destination cStringWithEncoding: OF_STRING_ENCODING_NATIVE])) @@ -625,13 +625,13 @@ @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); if ([self directoryExistsAtPath: destination]) { - OFString *filename = [source lastPathComponent]; - destination = [OFString stringWithPath: destination, filename, - nil]; + OFArray *components = [OFArray arrayWithObjects: + destination, [source lastPathComponent], nil]; + destination = [OFString pathWithComponents: components]; } if (link([source cStringWithEncoding: OF_STRING_ENCODING_NATIVE], [destination cStringWithEncoding: OF_STRING_ENCODING_NATIVE]) != 0) @throw [OFLinkFailedException @@ -652,13 +652,13 @@ @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); if ([self directoryExistsAtPath: destination]) { - OFString *filename = [source lastPathComponent]; - destination = [OFString stringWithPath: destination, filename, - nil]; + OFArray *components = [OFArray arrayWithObjects: + destination, [source lastPathComponent], nil]; + destination = [OFString pathWithComponents: components]; } if (symlink([source cStringWithEncoding: OF_STRING_ENCODING_NATIVE], [destination cStringWithEncoding: OF_STRING_ENCODING_NATIVE]) != 0) @throw [OFCreateSymbolicLinkFailedException Index: src/OFMutableString.m ================================================================== --- src/OFMutableString.m +++ src/OFMutableString.m @@ -169,30 +169,10 @@ { return (id)[[OFMutableString_UTF8 alloc] initWithFormat: format arguments: arguments]; } -- initWithPath: (OFString*)firstComponent, ... -{ - id ret; - va_list arguments; - - va_start(arguments, firstComponent); - ret = [[OFMutableString_UTF8 alloc] initWithPath: firstComponent - arguments: arguments]; - va_end(arguments); - - return ret; -} - -- initWithPath: (OFString*)firstComponent - arguments: (va_list)arguments -{ - return (id)[[OFMutableString_UTF8 alloc] initWithPath: firstComponent - arguments: arguments]; -} - - initWithContentsOfFile: (OFString*)path { return (id)[[OFMutableString_UTF8 alloc] initWithContentsOfFile: path]; } Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -270,18 +270,10 @@ * @param format A string used as format to initialize the OFString * @return A new autoreleased OFString */ + (instancetype)stringWithFormat: (OFConstantString*)format, ...; -/*! - * @brief Creates a new OFString containing the constructed specified path. - * - * @param firstComponent The first component of the path - * @return A new autoreleased OFString - */ -+ (instancetype)stringWithPath: (OFString*)firstComponent, ... OF_SENTINEL; - /*! * @brief Creates a new OFString with the contents of the specified UTF-8 * encoded file. * * @param path The path to the file @@ -323,10 +315,18 @@ * @return A new autoreleased OFString */ + (instancetype)stringWithContentsOfURL: (OFURL*)URL encoding: (of_string_encoding_t)encoding; +/*! + * @brief Creates a path from the specified path components. + * + * @param components An array of components for the path + * @return A new autoreleased OFString + */ ++ (instancetype)pathWithComponents: (OFArray*)components; + /*! * @brief Initializes an already allocated OFString from a UTF-8 encoded C * string. * * @param UTF8String A UTF-8 encoded C string to initialize the OFString with @@ -512,30 +512,10 @@ * @return An initialized OFString */ - initWithFormat: (OFConstantString*)format arguments: (va_list)arguments; -/*! - * @brief Initializes an already allocated OFString with the constructed - * specified path. - * - * @param firstComponent The first component of the path - * @return A new autoreleased OFString - */ -- initWithPath: (OFString*)firstComponent, ... OF_SENTINEL; - -/*! - * @brief Initializes an already allocated OFString with the constructed - * specified path. - * - * @param firstComponent The first component of the path - * @param arguments A va_list with the other components of the path - * @return A new autoreleased OFString - */ -- initWithPath: (OFString*)firstComponent - arguments: (va_list)arguments; - /*! * @brief Initializes an already allocated OFString with the contents of the * specified file in the specified encoding. * * @param path The path to the file Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -408,30 +408,10 @@ { return (id)[[OFString_UTF8 alloc] initWithFormat: format arguments: arguments]; } -- initWithPath: (OFString*)firstComponent, ... -{ - id ret; - va_list arguments; - - va_start(arguments, firstComponent); - ret = [[OFString_UTF8 alloc] initWithPath: firstComponent - arguments: arguments]; - va_end(arguments); - - return ret; -} - -- initWithPath: (OFString*)firstComponent - arguments: (va_list)arguments -{ - return (id)[[OFString_UTF8 alloc] initWithPath: firstComponent - arguments: arguments]; -} - - initWithContentsOfFile: (OFString*)path { return (id)[[OFString_UTF8 alloc] initWithContentsOfFile: path]; } @@ -619,23 +599,10 @@ va_end(arguments); return ret; } -+ (instancetype)stringWithPath: (OFString*)firstComponent, ... -{ - id ret; - va_list arguments; - - va_start(arguments, firstComponent); - ret = [[[self alloc] initWithPath: firstComponent - arguments: arguments] autorelease]; - va_end(arguments); - - return ret; -} - + (instancetype)stringWithContentsOfFile: (OFString*)path { return [[[self alloc] initWithContentsOfFile: path] autorelease]; } @@ -655,10 +622,29 @@ encoding: (of_string_encoding_t)encoding { return [[[self alloc] initWithContentsOfURL: URL encoding: encoding] autorelease]; } + ++ (instancetype)pathWithComponents: (OFArray*)components +{ + OFMutableString *ret = [OFMutableString string]; + void *pool = objc_autoreleasePoolPush(); + OFEnumerator *enumerator = [components objectEnumerator]; + OFString *component; + + if ((component = [enumerator nextObject]) != nil) + [ret appendString: component]; + while ((component = [enumerator nextObject]) != nil) { + [ret appendString: OF_PATH_DELIMITER_STRING]; + [ret appendString: component]; + } + + objc_autoreleasePoolPop(pool); + + return ret; +} - init { if (object_getClass(self) == [OFString class]) { @try { @@ -830,36 +816,10 @@ } - initWithFormat: (OFConstantString*)format arguments: (va_list)arguments { - @try { - [self doesNotRecognizeSelector: _cmd]; - } @catch (id e) { - [self release]; - @throw e; - } - - abort(); -} - -- initWithPath: (OFString*)firstComponent, ... -{ - id ret; - va_list arguments; - - va_start(arguments, firstComponent); - ret = [self initWithPath: firstComponent - arguments: arguments]; - va_end(arguments); - - return ret; -} - -- initWithPath: (OFString*)firstComponent - arguments: (va_list)arguments -{ @try { [self doesNotRecognizeSelector: _cmd]; } @catch (id e) { [self release]; @throw e; @@ -1807,11 +1767,19 @@ return new; } - (OFString*)stringByAppendingPathComponent: (OFString*)component { - return [OFString stringWithPath: self, component, nil]; + void *pool = objc_autoreleasePoolPush(); + OFString *ret; + + ret = [OFString pathWithComponents: + [OFArray arrayWithObjects: self, component, nil]]; + + [ret retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; } - (OFString*)stringByPrependingString: (OFString*)string { OFMutableString *new = [[string mutableCopy] autorelease]; Index: src/OFString_UTF8.m ================================================================== --- src/OFString_UTF8.m +++ src/OFString_UTF8.m @@ -653,74 +653,10 @@ } @catch (id e) { [self release]; @throw e; } - return self; -} - -- initWithPath: (OFString*)firstComponent - arguments: (va_list)arguments -{ - self = [super init]; - - @try { - OFString *component; - size_t i, cStringLength; - va_list argumentsCopy; - - _s = &_storage; - - _s->cStringLength = [firstComponent UTF8StringLength]; - - if ([firstComponent isKindOfClass: [OFString_UTF8 class]] || - [firstComponent isKindOfClass: - [OFMutableString_UTF8 class]]) - _s->isUTF8 = - ((OFString_UTF8*)firstComponent)->_s->isUTF8; - else - _s->isUTF8 = true; - - _s->length = [firstComponent length]; - - /* Calculate length and see if we need UTF-8 */ - va_copy(argumentsCopy, arguments); - while ((component = va_arg(argumentsCopy, OFString*)) != nil) { - _s->cStringLength += 1 + [component UTF8StringLength]; - _s->length += 1 + [component length]; - - if ([component isKindOfClass: [OFString_UTF8 class]] || - [component isKindOfClass: - [OFMutableString_UTF8 class]]) - _s->isUTF8 = - ((OFString_UTF8*)component)->_s->isUTF8; - else - _s->isUTF8 = true; - } - - _s->cString = [self allocMemoryWithSize: _s->cStringLength + 1]; - - cStringLength = [firstComponent UTF8StringLength]; - memcpy(_s->cString, [firstComponent UTF8String], cStringLength); - i = cStringLength; - - while ((component = va_arg(arguments, OFString*)) != nil) { - cStringLength = [component UTF8StringLength]; - - _s->cString[i] = OF_PATH_DELIMITER; - memcpy(_s->cString + i + 1, [component UTF8String], - cStringLength); - - i += 1 + cStringLength; - } - - _s->cString[i] = '\0'; - } @catch (id e) { - [self release]; - @throw e; - } - return self; } - (void)dealloc { Index: tests/OFStringTests.m ================================================================== --- tests/OFStringTests.m +++ tests/OFStringTests.m @@ -280,18 +280,20 @@ [a count] == 3 && [[a objectAtIndex: i++] isEqual: @"foo"] && [[a objectAtIndex: i++] isEqual: @"bar"] && [[a objectAtIndex: i++] isEqual: @"baz"]) - TEST(@"+[stringWithPath:]", - (is = [OFString stringWithPath: @"foo", @"bar", @"baz", nil]) && + TEST(@"+[pathWithComponents:]", + (is = [OFString pathWithComponents: [OFArray arrayWithObjects: + @"foo", @"bar", @"baz", nil]]) && #ifndef _WIN32 [is isEqual: @"foo/bar/baz"] && #else [is isEqual: @"foo\\bar\\baz"] && #endif - (is = [OFString stringWithPath: @"foo", nil]) && + (is = [OFString pathWithComponents: + [OFArray arrayWithObjects: @"foo", nil]]) && [is isEqual: @"foo"]) TEST(@"-[pathComponents]", /* /tmp */ (a = [@"/tmp" pathComponents]) && [a count] == 2 &&