Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -845,10 +845,27 @@ * * @return The directory name of the path */ - (OFString*)stringByDeletingLastPathComponent; +/*! + * @brief Returns the path with relative sub paths resolved. + * + * @return The path with relative sub paths resolved + */ +- (OFString*)stringByStandardizingPath; + +/*! + * @brief Returns the URL path with relative sub paths resolved. + * + * This works similar to @ref stringByStandardizingPath, but is intended for + * standardization of paths that are part of a URL. + * + * @return The URL path with relative sub paths resolved + */ +- (OFString*)stringByStandardizingURLPath; + /*! * @brief Returns the decimal value of the string as an intmax_t. * * Leading and trailing whitespaces are ignored. * Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -53,10 +53,57 @@ * However, the MinGW version __strtod seems to be ok. */ #ifdef _WIN32 # define strtod __strtod #endif + +static OFString* +standardize_path(OFArray *components, OFString *currentDirectory, + OFString *parentDirectory, OFString *joinString) +{ + void *pool = objc_autoreleasePoolPush(); + OFMutableArray *array; + OFString *ret; + BOOL done = NO; + + array = [[components mutableCopy] autorelease]; + + while (!done) { + size_t i, length = [array count]; + + done = YES; + + for (i = 0; i < length; i++) { + id object = [array objectAtIndex: i]; + + if ([object isEqual: currentDirectory]) { + [array removeObjectAtIndex: i]; + done = NO; + + break; + } + + if ([object isEqual: parentDirectory]) { + [array removeObjectAtIndex: i]; + + if (i > 0) + [array removeObjectAtIndex: i - 1]; + + done = NO; + + break; + } + } + } + + ret = [[array componentsJoinedByString: joinString] retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} + /* References for static linking */ void _references_to_categories_of_OFString(void) { _OFString_Hashing_reference = 1; @@ -1764,10 +1811,23 @@ objc_autoreleasePoolPop(pool); return @"."; } + +- (OFString*)stringByStandardizingPath +{ + return standardize_path([self pathComponents], + OF_PATH_CURRENT_DIRECTORY, OF_PATH_PARENT_DIRECTORY, + OF_PATH_DELIMITER_STRING); +} + +- (OFString*)stringByStandardizingURLPath +{ + return standardize_path( [self componentsSeparatedByString: @"/"], + @".", @"..", @"/"); +} - (intmax_t)decimalValue { void *pool = objc_autoreleasePoolPush(); const of_unichar_t *string = [self unicodeString]; Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -30,55 +30,10 @@ #import "OFOutOfMemoryException.h" #import "autorelease.h" #import "macros.h" -static OF_INLINE OFString* -resolve_relative_path(OFString *path) -{ - void *pool = objc_autoreleasePoolPush(); - OFMutableArray *array; - OFString *ret; - BOOL done = NO; - - array = [[[path componentsSeparatedByString: @"/"] mutableCopy] - autorelease]; - - while (!done) { - id *objects = [array objects]; - size_t i, length = [array count]; - - done = YES; - - for (i = 0; i < length; i++) { - if ([objects[i] isEqual: @"."]) { - [array removeObjectAtIndex: i]; - done = NO; - - break; - } - - if ([objects[i] isEqual: @".."]) { - [array removeObjectAtIndex: i]; - - if (i > 0) - [array removeObjectAtIndex: i - 1]; - - done = NO; - - break; - } - } - } - - ret = [[array componentsJoinedByString: @"/"] retain]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; -} - @implementation OFURL + (instancetype)URL { return [[[self alloc] init] autorelease]; } @@ -282,11 +237,11 @@ else s = [OFString stringWithFormat: @"%@/../%s", URL->path, UTF8String]; - path = [resolve_relative_path(s) copy]; + path = [[s stringByStandardizingURLPath] copy]; objc_autoreleasePoolPop(pool); } } @catch (id e) { [self release]; Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -118,14 +118,17 @@ abort(); \ } #ifndef _WIN32 # define OF_PATH_DELIMITER '/' +# define OF_PATH_DELIMITER_STRING @"/" #else # define OF_PATH_DELIMITER '\\' +# define OF_PATH_DELIMITER_STRING @"\\" #endif -#define OF_PATH_PARENT_DIR @".." +#define OF_PATH_CURRENT_DIRECTORY @"." +#define OF_PATH_PARENT_DIRECTORY @".." extern id objc_getProperty(id, SEL, ptrdiff_t, BOOL); extern void objc_setProperty(id, SEL, ptrdiff_t, id, BOOL, signed char); #define OF_IVAR_OFFSET(ivar) ((intptr_t)&ivar - (intptr_t)self)