Artifact 84af7e353c8ecbdcc86635ccbb3ca213795ca7ab1f4526494a3b340487b6f2af:
- File
src/OFStdIOStream.m
— part of check-in
[4e59d2692f]
at
2014-04-26 00:40:17
on branch trunk
— Fix a few issues on LLP64 and Win64
LLP64 was mostly fast enumeration using an unsigned long for the state,
which can't store a pointer or a size_t on LLP64. This is now solved by
either throwing an OFOutOfRangeException if the value of the size_t is
bigger than ULONG_MAX or storing the pointer in the extra field (copied
using memcpy, as it's an array of unsigned long, which again would be
too small to store a pointer).Win64 was mostly Microsoft not being able to decide whether a length is
a size_t, a DWORD, an int or an unsigned int (thus the different types
in places that seem to be almost the same). But since that would not be
confusing enough, a file descriptor is an int if it's for a file, but a
long long if it is for a socket. But of course, for ReadFile and friends
it's a DWORD instead of an int then. (user: js, size: 3662) [annotate] [blame] [check-ins using]
/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 * Jonathan Schleifer <js@webkeks.org> * * 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 <unistd.h> #import "OFStdIOStream.h" #import "OFDate.h" #import "OFApplication.h" #import "OFOutOfRangeException.h" #import "OFReadFailedException.h" #import "OFWriteFailedException.h" #import "autorelease.h" #import "macros.h" OFStdIOStream *of_stdin = nil; OFStdIOStream *of_stdout = nil; OFStdIOStream *of_stderr = nil; @interface OFStdIOStream (OF_PRIVATE_CATEGORY) - (instancetype)OF_initWithFileDescriptor: (int)fd; @end 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 { OF_INVALID_INIT_METHOD } - (instancetype)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; #ifndef _WIN32 if (_fd == -1 || _atEndOfStream || (ret = read(_fd, buffer, length)) < 0) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length]; #else if (length > UINT_MAX) @throw [OFOutOfRangeException exception]; if (_fd == -1 || _atEndOfStream || (ret = read(_fd, buffer, (unsigned int)length)) < 0) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length]; #endif if (ret == 0) _atEndOfStream = true; return ret; } - (void)lowlevelWriteBuffer: (const void*)buffer length: (size_t)length { #ifndef _WIN32 if (_fd == -1 || _atEndOfStream || write(_fd, buffer, length) < length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length]; #else if (length > UINT_MAX) @throw [OFOutOfRangeException exception]; if (_fd == -1 || _atEndOfStream || write(_fd, buffer, (unsigned int)length) < length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length]; #endif } - (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 { OF_UNRECOGNIZED_SELECTOR /* Get rid of a stupid warning */ [super dealloc]; } @end