@@ -15,22 +15,57 @@ #include #include #include #include +#include #import "OFFile.h" #import "OFString.h" #import "OFExceptions.h" #ifdef _WIN32 # import #endif + +#ifndef O_BINARY +# define O_BINARY 0 +#endif OFFile *of_stdin = nil; OFFile *of_stdout = nil; OFFile *of_stderr = nil; + +static int parse_mode(const char *mode) +{ + if (!strcmp(mode, "r")) + return O_RDONLY; + if (!strcmp(mode, "rb")) + return O_RDONLY | O_BINARY; + if (!strcmp(mode, "r+")) + return O_RDWR; + if (!strcmp(mode, "rb+") || !strcmp(mode, "r+b")) + return O_RDWR | O_BINARY; + if (!strcmp(mode, "w")) + return O_WRONLY | O_CREAT | O_TRUNC; + if (!strcmp(mode, "wb")) + return O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; + if (!strcmp(mode, "w+")) + return O_RDWR | O_CREAT | O_TRUNC; + if (!strcmp(mode, "wb+") || !strcmp(mode, "w+b")) + return O_RDWR | O_CREAT | O_TRUNC | O_BINARY; + if (!strcmp(mode, "a")) + return O_WRONLY | O_CREAT | O_APPEND; + if (!strcmp(mode, "ab")) + return O_WRONLY | O_CREAT | O_APPEND | O_BINARY; + if (!strcmp(mode, "a+")) + return O_RDWR | O_CREAT | O_APPEND; + if (!strcmp(mode, "ab+") || !strcmp(mode, "a+b")) + return O_RDWR | O_CREAT | O_APPEND | O_BINARY; + + return -1; +} /// \cond internal @interface OFFileSingleton: OFFile @end /// \endcond @@ -39,25 +74,25 @@ + (void)load { if (self != [OFFile class]) return; - of_stdin = [[OFFileSingleton alloc] initWithFilePointer: stdin]; - of_stdout = [[OFFileSingleton alloc] initWithFilePointer: stdout]; - of_stderr = [[OFFileSingleton alloc] initWithFilePointer: stderr]; + of_stdin = [[OFFileSingleton alloc] initWithFileDescriptor: 0]; + of_stdout = [[OFFileSingleton alloc] initWithFileDescriptor: 1]; + of_stderr = [[OFFileSingleton alloc] initWithFileDescriptor: 2]; } + fileWithPath: (OFString*)path mode: (OFString*)mode { return [[[self alloc] initWithPath: path mode: mode] autorelease]; } -+ fileWithFilePointer: (FILE*)fp_ ++ fileWithFileDescriptor: (int)fd_ { - return [[[self alloc] initWithFilePointer: fp_] autorelease]; + return [[[self alloc] initWithFileDescriptor: fd_] autorelease]; } + (void)changeModeOfFile: (OFString*)path toMode: (mode_t)mode { @@ -151,82 +186,90 @@ - initWithPath: (OFString*)path mode: (OFString*)mode { Class c; + int flags; self = [super init]; - if ((fp = fopen([path cString], [mode cString])) == NULL) { + if ((flags = parse_mode([mode cString])) == -1) { + c = isa; + [super dealloc]; + @throw [OFInvalidArgumentException newWithClass: c + selector: _cmd]; + } + + if ((fd = open([path cString], flags)) == -1) { c = isa; [super dealloc]; @throw [OFOpenFileFailedException newWithClass: c path: path mode: mode]; } - close = YES; + closable = YES; return self; } -- initWithFilePointer: (FILE*)fp_ +- initWithFileDescriptor: (int)fd_ { self = [super init]; - fp = fp_; + fd = fd_; return self; } - (void)dealloc { - if (close && fp != NULL) - fclose(fp); + if (closable && fd != -1) + close(fd); [super dealloc]; } - (BOOL)atEndOfStreamWithoutCache { - if (fp == NULL) + if (fd == -1) return YES; - return (feof(fp) == 0 ? NO : YES); + return eos; } - (size_t)readNBytesWithoutCache: (size_t)size intoBuffer: (char*)buf { size_t ret; - if (fp == NULL || feof(fp) || ((ret = fread(buf, 1, size, fp)) == 0 && - size != 0 && !feof(fp))) + if (fd == -1 || eos) @throw [OFReadFailedException newWithClass: isa size: size]; + if ((ret = read(fd, buf, size)) == 0) + eos = YES; return ret; } - (size_t)writeNBytes: (size_t)size fromBuffer: (const char*)buf { size_t ret; - if (fp == NULL || feof(fp) || - ((ret = fwrite(buf, 1, size, fp)) < size && size != 0)) + if (fd == -1 || eos || (ret = write(fd, buf, size)) < size) @throw [OFWriteFailedException newWithClass: isa size: size]; return ret; } - close { - if (fp != NULL) - fclose(fp); - fp = NULL; + if (fd != -1) + close(fd); + fd = -1; return self; } @end