Index: src/OFFile.h ================================================================== --- src/OFFile.h +++ src/OFFile.h @@ -39,10 +39,16 @@ * It is not closed when the OFFile object is deallocated! * \return A new autoreleased OFFile */ + fileWithFileDescriptor: (int)fd; +/** + * \param path The path for which the last component should be returned + * \return The last component of the path + */ ++ (OFString*)lastComponentOfPath: (OFString*)path; + /** * \param path The path to check * \return A boolean whether there is a file at the specified path */ + (BOOL)fileExistsAtPath: (OFString*)path; Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -41,10 +41,16 @@ # define S_IROTH 0 #endif #define DEFAULT_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH #define DIR_MODE DEFAULT_MODE | S_IXUSR | S_IXGRP | S_IXOTH + +#ifndef _WIN32 +# define PATH_DELIM '/' +#else +# define PATH_DELIM '\\' +#endif OFFile *of_stdin = nil; OFFile *of_stdout = nil; OFFile *of_stderr = nil; @@ -103,10 +109,40 @@ + fileWithFileDescriptor: (int)fd_ { return [[[self alloc] initWithFileDescriptor: fd_] autorelease]; } + ++ (OFString*)lastComponentOfPath: (OFString*)path +{ + const char *path_c = [path cString]; + size_t path_len = [path cStringLength]; + ssize_t i; + + if (path_len == 0) + return @""; + + if (path_c[path_len - 1] == PATH_DELIM) + path_len--; + + for (i = path_len - 1; i >= 0; i--) { + if (path_c[i] == PATH_DELIM) { + i++; + break; + } + } + + /* + * Only one component, but the trailing delimiter might have been + * removed, so return a new string anyway. + */ + if (i < 0) + i++; + + return [OFString stringWithCString: path_c + i + length: path_len - i]; +} + (BOOL)fileExistsAtPath: (OFString*)path { struct stat s; Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -4,10 +4,11 @@ PROG_NOINST = tests${PROG_SUFFIX} SRCS = OFArrayTests.m \ OFDataArrayTests.m \ OFDictionaryTests.m \ + OFFileTests.m \ OFHashesTests.m \ OFListTests.m \ OFNumberTests.m \ OFObjectTests.m \ ${OFPLUGINTESTS_M} \ ADDED tests/OFFileTests.m Index: tests/OFFileTests.m ================================================================== --- /dev/null +++ tests/OFFileTests.m @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2008 - 2010 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE included in + * the packaging of this file. + */ + +#include "config.h" + +#import "OFFile.h" +#import "OFAutoreleasePool.h" +#import "OFString.h" +#import "OFExceptions.h" + +#import "TestsAppDelegate.h" + +static OFString *module = @"OFFile"; + +@implementation TestsAppDelegate (OFFileTests) +- (void)fileTests +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + + TEST(@"+[lastComponentOfPath", + [[OFFile lastComponentOfPath: @"/tmp"] isEqual: @"tmp"] && + [[OFFile lastComponentOfPath: @"/tmp/"] isEqual: @"tmp"] && + [[OFFile lastComponentOfPath: @"/"] isEqual: @""] && + [[OFFile lastComponentOfPath: @"foo"] isEqual: @"foo"] /* && + [[OFFile lastComponentOfPath: @"foo/bar"] isEqual: @"bar"] && + [[OFFile lastComponentOfPath: @"foo/bar/baz/"] isEqual: @"baz"]*/) + + [pool drain]; +} +@end Index: tests/TestsAppDelegate.h ================================================================== --- tests/TestsAppDelegate.h +++ tests/TestsAppDelegate.h @@ -76,10 +76,14 @@ @end @interface TestsAppDelegate (OFDictionaryTests) - (void)dictionaryTests; @end + +@interface TestsAppDelegate (OFFileTests) +- (void)fileTests; +@end @interface TestsAppDelegate (OFHashesTests) - (void)hashesTests; @end Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -75,12 +75,13 @@ } - (void)applicationDidFinishLaunching { [self objectTests]; - [self hashesTests]; [self stringTests]; + [self fileTests]; + [self hashesTests]; [self dataArrayTests]; [self arrayTests]; [self dictionaryTests]; [self listTests]; [self numberTests];