[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: [Q] NSFileHandle -readDataOfLength behaviour
From: |
Vaisburd, Haim |
Subject: |
RE: [Q] NSFileHandle -readDataOfLength behaviour |
Date: |
Fri, 13 Apr 2007 12:03:11 -0700 |
Richard Frith-Macdonald [mailto:richard@tiptree.demon.co.uk] wrote:
> Tima Vaisburd wrote:
> > RFM> this method should block until it reads the specified amount of
data
> > RFM> (or eof).
>
> > but for my stream class I need exactly what read() does, since the
> > whole idea was to read byte after byte until the record ends (which
is
> > determined by the structure of the incoming byte stream, not by the
> > length passed in the header).
>
> Maybe availableData is what you want.
-availableData does not have a limit. I might be able to use it,
but what I would really want is -readDataOfLength that would not block
until it gets all the length but would return what's available,
blocking only until the first byte comes ( i.e. like read() ).
I hoped that that's what it should do and was a little disappointed
when you said "block". Since I cannot test on Mac right now (I have one
recently but haven't programmed on it yet) I searched the web for
the proof. Could not find one but I found two other open source
implementations that do what I want and not what you say (see below).
Of course they are not a proof of anything, but raise a concern in my
mind.
Could you, please, test the behavior on Mac OSX or just confirm that
you've
done it before?
1.
http://svn.opengroupware.org/SOPE/trunk/libFoundation/Foundation/NSConcr
eteFileHandle.m :
/*
NSConcreteFileHandle.m
Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
All rights reserved.
Author: Ovidiu Predescu <ovidiu@net-community.com>
Date: May 1997
This file is part of libFoundation.
[...]
*/
@implementation NSConcreteFileHandle
- (NSData *)readDataOfLength:(unsigned int)length
{
[...]
else if (type == NSFileHandleSocket) {
void *buffer;
int howMany;
/* Force the compiler to allocate `buffer' on stack */
*&buffer = MallocAtomic(length);
howMany = read(fd, buffer, length);
if (howMany == -1) {
lfFree(buffer);
[[[NSFileHandleOperationException alloc]
initWithFileHandle:self
operation:@"Error while reading from socket!"]
raise];
}
if (howMany < (int)length)
buffer = Realloc(buffer, howMany);
data = [NSData dataWithBytesNoCopy:buffer length:howMany];
}
[...]
}
2.
http://www.quantum-step.com/download/sources/mySTEP/Foundation/Sources/N
SFileHandle.m
/*
NSFileHandle.m
Implementation of NSFileHandle for mySTEP
Copyright (C) 1997 Free Software Foundation, Inc.
Author: Richard Frith-Macdonald <richard@brainstorm.co.uk>
Date: 1997
Complete rewrite based on NSStream:
Dr. H. Nikolaus Schaller <hns@computer.org>
Date: Jan 2006
This file is part of the mySTEP Library [...]
*/
@implementation NSFileHandle
- (NSData *) readDataOfLength:(unsigned int) length;
{
unsigned char *buffer;
unsigned int len;
if([_inputStream getBuffer:&buffer length:&len])
return [NSData dataWithBytes:buffer length:MIN(len,
length)]; // buffer is directly available
if(!(buffer=objc_malloc(length)))
return nil; // can't allocate large enough buffer
len=[_inputStream read:buffer maxLength:length]; // fetch
get as much as possible
if(len < 0)
{
objc_free(buffer);
[NSException raise:NSFileHandleOperationException
format:@"failed to read data from NSFileHandle - %s", strerror(errno)];
return nil;
}
buffer=objc_realloc(buffer, len); // free unused buffer
space
return [NSData dataWithBytesNoCopy:buffer length:len
freeWhenDone:YES]; // take over responsibility for buffer
}
> If you really want to read an individual byte at a time, NSStream is
probably better than NSFileHandle ...
> but that's a shockingly inefficient way to do I/O
Do you refer to NSStream or "byte at a time" as being shockingly
inefficient?
Of course I meant "byte at a time" in the way getc() macro of standard
IO library does it:
read a block with a system call, scan it with something fast.
With comminucation channel though the last read() call may give me the
end of some record
( "}}}}}" , 5 bytes ) and the server might not send anything else until
further request from the client.
In the client I need to get these five bytes, if everyting works OK the
last '}' will be
the end of the record, I'll process it and send another request.
Thank you,
Tima