Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -31,10 +31,12 @@ productName = configure; }; /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 4B0256E4172B60400062B5F1 /* OFStdIOStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B0256E2172B60400062B5F1 /* OFStdIOStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B0256E5172B60400062B5F1 /* OFStdIOStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0256E3172B60400062B5F1 /* OFStdIOStream.m */; }; 4B11005C14329B9A003A45D8 /* OFXMLNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B11005A14329B9A003A45D8 /* OFXMLNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B11005D14329B9A003A45D8 /* OFXMLNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B11005B14329B9A003A45D8 /* OFXMLNode.m */; }; 4B141BA415FCDF74000C21A8 /* OFSortedList.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B141BA215FCDF74000C21A8 /* OFSortedList.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B141BA515FCDF74000C21A8 /* OFSortedList.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B141BA315FCDF74000C21A8 /* OFSortedList.m */; }; 4B17FF73133A2A76003E6DCD /* OFException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B17FF71133A28FC003E6DCD /* OFException.m */; }; @@ -455,10 +457,12 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 4B0108C910EB8C9300631877 /* OFEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFEnumerator.h; path = src/OFEnumerator.h; sourceTree = ""; }; 4B0108CA10EB8C9300631877 /* OFEnumerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFEnumerator.m; path = src/OFEnumerator.m; sourceTree = ""; }; + 4B0256E2172B60400062B5F1 /* OFStdIOStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFStdIOStream.h; path = src/OFStdIOStream.h; sourceTree = ""; }; + 4B0256E3172B60400062B5F1 /* OFStdIOStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFStdIOStream.m; path = src/OFStdIOStream.m; sourceTree = ""; }; 4B0D249411DFAA3D00ED6FFC /* OFXMLElementBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFXMLElementBuilder.h; path = src/OFXMLElementBuilder.h; sourceTree = ""; }; 4B0D249511DFAA3D00ED6FFC /* OFXMLElementBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLElementBuilder.m; path = src/OFXMLElementBuilder.m; sourceTree = ""; }; 4B11005A14329B9A003A45D8 /* OFXMLNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFXMLNode.h; path = src/OFXMLNode.h; sourceTree = ""; }; 4B11005B14329B9A003A45D8 /* OFXMLNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLNode.m; path = src/OFXMLNode.m; sourceTree = ""; }; 4B141BA215FCDF74000C21A8 /* OFSortedList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSortedList.h; path = src/OFSortedList.h; sourceTree = ""; }; @@ -1165,10 +1169,12 @@ 4BA85BC9140ECCE800E91D51 /* OFSet_hashtable.m */, 4BF1BCC411C9663F0025511F /* OFSHA1Hash.h */, 4BF1BCC511C9663F0025511F /* OFSHA1Hash.m */, 4B141BA215FCDF74000C21A8 /* OFSortedList.h */, 4B141BA315FCDF74000C21A8 /* OFSortedList.m */, + 4B0256E2172B60400062B5F1 /* OFStdIOStream.h */, + 4B0256E3172B60400062B5F1 /* OFStdIOStream.m */, 4B67997D1099E7C50041064A /* OFStream.h */, 4B67997E1099E7C50041064A /* OFStream.m */, 4BAF5F47123460C900F4E111 /* OFStreamObserver.h */, 4BAF5F48123460C900F4E111 /* OFStreamObserver.m */, 4B83F0F2142FDEFD00E4A821 /* OFStreamObserver_kqueue.h */, @@ -1410,10 +1416,11 @@ 4B3D23D31337FCB000DD29B8 /* OFSeekableStream.h in Headers */, 4B989C2F13771A3700109A30 /* OFSerialization.h in Headers */, 4B39844213D3A24600E6F825 /* OFSet.h in Headers */, 4B3D23D41337FCB000DD29B8 /* OFSHA1Hash.h in Headers */, 4B141BA415FCDF74000C21A8 /* OFSortedList.h in Headers */, + 4B0256E4172B60400062B5F1 /* OFStdIOStream.h in Headers */, 4B3D23D51337FCB000DD29B8 /* OFStream.h in Headers */, 4B3D23D61337FCB000DD29B8 /* OFStreamObserver.h in Headers */, 4B3D23D71337FCB000DD29B8 /* OFStreamSocket.h in Headers */, 4B3D23D81337FCB000DD29B8 /* OFString.h in Headers */, 4B3D23D91337FCB000DD29B8 /* OFString+Hashing.h in Headers */, @@ -1761,10 +1768,11 @@ 4B3D23A11337FC0D00DD29B8 /* OFSeekableStream.m in Sources */, 4B39844313D3A24600E6F825 /* OFSet.m in Sources */, 4BA85BCF140ECCE800E91D51 /* OFSet_hashtable.m in Sources */, 4B3D23A21337FC0D00DD29B8 /* OFSHA1Hash.m in Sources */, 4B141BA515FCDF74000C21A8 /* OFSortedList.m in Sources */, + 4B0256E5172B60400062B5F1 /* OFStdIOStream.m in Sources */, 4B3D23A31337FC0D00DD29B8 /* OFStream.m in Sources */, 4B3D23A41337FC0D00DD29B8 /* OFStreamObserver.m in Sources */, 4B83F0F5142FDEFD00E4A821 /* OFStreamObserver_kqueue.m in Sources */, 4B64D6F01425381E007BDFB1 /* OFStreamObserver_poll.m in Sources */, 4B64D6F21425381E007BDFB1 /* OFStreamObserver_select.m in Sources */, Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -37,10 +37,11 @@ OFRunLoop.m \ OFSeekableStream.m \ OFSet.m \ OFSHA1Hash.m \ OFSortedList.m \ + OFStdIOStream.m \ OFStream.m \ OFString.m \ OFString+Hashing.m \ OFString+JSONValue.m \ OFString+Serialization.m \ Index: src/OFFile.h ================================================================== --- src/OFFile.h +++ src/OFFile.h @@ -26,25 +26,16 @@ #import "OFSeekableStream.h" @class OFArray; @class OFDate; -#ifdef __cplusplus -extern "C" { -#endif -extern void of_log(OFConstantString*, ...); -#ifdef __cplusplus -} -#endif - /*! * @brief A class which provides functions to read, write and manipulate files. */ @interface OFFile: OFSeekableStream { int _fd; - bool _closable; bool _atEndOfStream; } /*! * @brief Creates a new OFFile with the specified path and mode. @@ -267,28 +258,5 @@ * @param fd A file descriptor, returned from for example open(). * It is not closed when the OFFile object is deallocated! */ - initWithFileDescriptor: (int)fd; @end - -#ifdef __cplusplus -extern "C" { -#endif -/*! @file */ - -/*! - * @brief The standard input stream as an OFStream instance. - */ -extern OFStream *of_stdin; - -/*! - * @brief The standard output stream as an OFStream instance. - */ -extern OFStream *of_stdout; - -/*! - * @brief The standard error stream as an OFStream instance. - */ -extern OFStream *of_stderr; -#ifdef __cplusplus -} -#endif Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -47,11 +47,10 @@ #import "OFArray.h" #ifdef OF_HAVE_THREADS # import "threading.h" #endif #import "OFDate.h" -#import "OFApplication.h" #import "OFSystemInfo.h" #import "OFChangeDirectoryFailedException.h" #import "OFChangeFileModeFailedException.h" #import "OFChangeFileOwnerFailedException.h" @@ -97,14 +96,10 @@ #endif #define DEFAULT_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH #define DIR_MODE DEFAULT_MODE | S_IXUSR | S_IXGRP | S_IXOTH -OFStream *of_stdin = nil; -OFStream *of_stdout = nil; -OFStream *of_stderr = nil; - #if defined(OF_HAVE_CHOWN) && defined(OF_HAVE_THREADS) static of_mutex_t mutex; #endif static int parse_mode(const char *mode) @@ -135,36 +130,10 @@ return O_RDWR | O_CREAT | O_APPEND | O_BINARY; return -1; } -void -of_log(OFConstantString *format, ...) -{ - void *pool = objc_autoreleasePoolPush(); - OFDate *date; - OFString *dateString, *me, *msg; - va_list arguments; - - date = [OFDate date]; - dateString = [date localDateStringWithFormat: @"%Y-%m-%d %H:%M:%S"]; - me = [[OFApplication programName] lastPathComponent]; - - va_start(arguments, format); - msg = [[[OFString alloc] initWithFormat: format - arguments: arguments] autorelease]; - va_end(arguments); - - [of_stderr writeFormat: @"[%@.%03d %@(%d)] %@\n", dateString, - [date microsecond] / 1000, me, getpid(), msg]; - - objc_autoreleasePoolPop(pool); -} - -@interface OFFileSingleton: OFFile -@end - @implementation OFFile #if defined(OF_HAVE_CHOWN) && defined(OF_HAVE_THREADS) + (void)initialize { if (self != [OFFile class]) @@ -695,12 +664,10 @@ #endif @throw [OFOpenFileFailedException exceptionWithClass: [self class] path: path mode: mode]; - - _closable = true; } @catch (id e) { [self release]; @throw e; } @@ -778,68 +745,11 @@ _fd = -1; } - (void)dealloc { - if (_closable && _fd != -1) + if (_fd != -1) close(_fd); [super dealloc]; } -@end - -@implementation OFFileSingleton -+ (void)load -{ - of_stdin = [[OFFileSingleton alloc] initWithFileDescriptor: 0]; - of_stdout = [[OFFileSingleton alloc] initWithFileDescriptor: 1]; - of_stderr = [[OFFileSingleton alloc] initWithFileDescriptor: 2]; -} - -- initWithPath: (OFString*)path - mode: (OFString*)mode -{ - @try { - [self doesNotRecognizeSelector: _cmd]; - } @catch (id e) { - [self release]; - @throw e; - } - - abort(); -} - -- autorelease -{ - return self; -} - -- retain -{ - return self; -} - -- (void)release -{ -} - -- (unsigned int)retainCount -{ - return OF_RETAIN_COUNT_MAX; -} - -- (void)dealloc -{ - [self doesNotRecognizeSelector: _cmd]; - abort(); - - /* Get rid of stupid warning */ - [super dealloc]; -} - -- (void)lowlevelSeekToOffset: (off_t)offset - whence: (int)whence -{ - [self doesNotRecognizeSelector: _cmd]; - abort(); -} @end ADDED src/OFStdIOStream.h Index: src/OFStdIOStream.h ================================================================== --- src/OFStdIOStream.h +++ src/OFStdIOStream.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 + * 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.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFStream.h" + +/*! + * @brief A class for providing standard input, output and error as OFStream. + */ +@interface OFStdIOStream: OFStream +{ + int _fd; + bool _atEndOfStream; +} + +- OF_initWithFileDescriptor: (int)fd; +@end + +#ifdef __cplusplus +extern "C" { +#endif +/*! @file */ + +/*! + * @brief The standard input as an OFStream. + */ +extern OFStdIOStream *of_stdin; + +/*! + * @brief The standard output as an OFStream. + */ +extern OFStdIOStream *of_stdout; + +/*! + * @brief The standard error as an OFStream. + */ +extern OFStdIOStream *of_stderr; + +extern void of_log(OFConstantString*, ...); +#ifdef __cplusplus +} +#endif ADDED src/OFStdIOStream.m Index: src/OFStdIOStream.m ================================================================== --- src/OFStdIOStream.m +++ src/OFStdIOStream.m @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 + * 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.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include +#include + +#import "OFStdIOStream.h" +#import "OFDate.h" +#import "OFApplication.h" + +#import "OFReadFailedException.h" +#import "OFWriteFailedException.h" + +#import "autorelease.h" + +OFStdIOStream *of_stdin = nil; +OFStdIOStream *of_stdout = nil; +OFStdIOStream *of_stderr = nil; + +void +of_log(OFConstantString *format, ...) +{ + void *pool = objc_autoreleasePoolPush(); + OFDate *date; + OFString *dateString, *me, *msg; + va_list arguments; + + date = [OFDate date]; + dateString = [date localDateStringWithFormat: @"%Y-%m-%d %H:%M:%S"]; + me = [[OFApplication programName] lastPathComponent]; + + va_start(arguments, format); + msg = [[[OFString alloc] initWithFormat: format + arguments: arguments] autorelease]; + va_end(arguments); + + [of_stderr writeFormat: @"[%@.%03d %@(%d)] %@\n", dateString, + [date microsecond] / 1000, me, getpid(), msg]; + + objc_autoreleasePoolPop(pool); +} + +@implementation OFStdIOStream ++ (void)load +{ + of_stdin = [[OFStdIOStream alloc] OF_initWithFileDescriptor: 0]; + of_stdout = [[OFStdIOStream alloc] OF_initWithFileDescriptor: 1]; + of_stderr = [[OFStdIOStream alloc] OF_initWithFileDescriptor: 2]; +} + +- init +{ + @try { + [self doesNotRecognizeSelector: _cmd]; + } @catch (id e) { + [self release]; + @throw e; + } + + abort(); +} + +- OF_initWithFileDescriptor: (int)fd +{ + self = [super init]; + + _fd = fd; + + return self; +} + +- (bool)lowlevelIsAtEndOfStream +{ + if (_fd == -1) + return true; + + return _atEndOfStream; +} + +- (size_t)lowlevelReadIntoBuffer: (void*)buffer + length: (size_t)length +{ + ssize_t ret; + + if (_fd == -1 || _atEndOfStream || + (ret = read(_fd, buffer, length)) < 0) + @throw [OFReadFailedException exceptionWithClass: [self class] + stream: self + requestedLength: length]; + + if (ret == 0) + _atEndOfStream = true; + + return ret; +} + +- (void)lowlevelWriteBuffer: (const void*)buffer + length: (size_t)length +{ + if (_fd == -1 || _atEndOfStream || write(_fd, buffer, length) < length) + @throw [OFWriteFailedException exceptionWithClass: [self class] + stream: self + requestedLength: length]; +} + +- (int)fileDescriptorForReading +{ + return _fd; +} + +- (int)fileDescriptorForWriting +{ + return _fd; +} + +- (void)close +{ + if (_fd != -1) + close(_fd); + + _fd = -1; +} + +- autorelease +{ + return self; +} + +- retain +{ + return self; +} + +- (void)release +{ +} + +- (unsigned int)retainCount +{ + return OF_RETAIN_COUNT_MAX; +} + +- (void)dealloc +{ + [self doesNotRecognizeSelector: _cmd]; + abort(); + + /* Get rid of stupid warning */ + [super dealloc]; +} +@end Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -43,10 +43,11 @@ #import "OFNumber.h" #import "OFDate.h" #import "OFURL.h" #import "OFStream.h" +#import "OFStdIOStream.h" #import "OFFile.h" #ifdef OF_HAVE_SOCKETS # import "OFStreamSocket.h" # import "OFTCPSocket.h" # import "OFTLSSocket.h" Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -17,11 +17,11 @@ #include "config.h" #include #import "OFString.h" -#import "OFFile.h" +#import "OFStdIOStream.h" #import "OFAutoreleasePool.h" #import "TestsAppDelegate.h" #ifdef _PSP