Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Buffering NSOutputStream used as NSInputStream?

I have this consumer class that takes an NSInputStream as argument which will be processed async, and I want to push data that comes from a producer class that requires that it has an NSOutputStream provided as its output source. Now how could I set up a buffering (or transparent) stream that acts as the output stream for the producer, and at the same time as the NSInputStream for my consumer class?

I've looked a bit at the NSOutputStream +outputStreamToMemory and +outputStreamToBuffer:capacity: but haven't really figured out how to use it as input for an NSInputSource.

I had some idea of setting up a middle-man class that holds the actual buffer, then creating two subclasses (one for each NSInput/OutputStream) which holds a reference to this buffering class, and having these subclasses delegate most calls to that class, e.g output subclass methods hasSpaceAvailable, write:maxLength:, and for the input, hasBytesAvailable, read:maxLength: etc.

Any tips on how to approach this situation are appreciated. Thanks.

like image 479
cahlbin Avatar asked Jul 10 '10 22:07

cahlbin


1 Answers

One way to accomplish this would be to use the example code on the apple developer site. SimpleURLConnection example

This is how to do it, as can be seen in the PostController.m code

@interface NSStream (BoundPairAdditions)
+ (void)createBoundInputStream:(NSInputStream **)inputStreamPtr outputStream:(NSOutputStream **)outputStreamPtr bufferSize:(NSUInteger)bufferSize;
@end

@implementation NSStream (BoundPairAdditions)

+ (void)createBoundInputStream:(NSInputStream **)inputStreamPtr outputStream:(NSOutputStream **)outputStreamPtr bufferSize:(NSUInteger)bufferSize
{
    CFReadStreamRef     readStream;
    CFWriteStreamRef    writeStream;

    assert( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) );

    readStream = NULL;
    writeStream = NULL;

    CFStreamCreateBoundPair(
        NULL, 
        ((inputStreamPtr  != nil) ? &readStream : NULL),
        ((outputStreamPtr != nil) ? &writeStream : NULL), 
        (CFIndex) bufferSize);

    if (inputStreamPtr != NULL) {
        *inputStreamPtr  = [NSMakeCollectable(readStream) autorelease];
    }
    if (outputStreamPtr != NULL) {
        *outputStreamPtr = [NSMakeCollectable(writeStream) autorelease];
    }
}
@end

Basically you attach the ends of two streams together with a buffer.

like image 134
JugsteR Avatar answered Sep 20 '22 13:09

JugsteR