Permalink
Browse files

Add HSRandomDataInputStream

  • Loading branch information...
1 parent 0c5278d commit a27eeeb8552c62d6a56cfe5229280011d1d873c2 BJ Homer committed May 12, 2011
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ B770D6A91375802D00E07924 /* HSRandomDataInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = B770D6A81375802D00E07924 /* HSRandomDataInputStream.m */; };
B7B206F713557E9500C1C6BA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B7B206F613557E9500C1C6BA /* Foundation.framework */; };
B7B206FA13557E9500C1C6BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B7B206F913557E9500C1C6BA /* main.m */; };
B7B2070513557ED300C1C6BA /* HSCountingInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = B7B2070413557ED300C1C6BA /* HSCountingInputStream.m */; };
@@ -26,6 +27,8 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ B770D6A71375802D00E07924 /* HSRandomDataInputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HSRandomDataInputStream.h; sourceTree = "<group>"; };
+ B770D6A81375802D00E07924 /* HSRandomDataInputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HSRandomDataInputStream.m; sourceTree = "<group>"; };
B7B206F213557E9500C1C6BA /* HSCountingInputStream */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = HSCountingInputStream; sourceTree = BUILT_PRODUCTS_DIR; };
B7B206F613557E9500C1C6BA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
B7B206F913557E9500C1C6BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
@@ -80,6 +83,8 @@
B7B206F913557E9500C1C6BA /* main.m */,
B7B2070313557ED300C1C6BA /* HSCountingInputStream.h */,
B7B2070413557ED300C1C6BA /* HSCountingInputStream.m */,
+ B770D6A71375802D00E07924 /* HSRandomDataInputStream.h */,
+ B770D6A81375802D00E07924 /* HSRandomDataInputStream.m */,
B7B206FB13557E9500C1C6BA /* Supporting Files */,
);
path = HSCountingInputStream;
@@ -145,6 +150,7 @@
files = (
B7B206FA13557E9500C1C6BA /* main.m in Sources */,
B7B2070513557ED300C1C6BA /* HSCountingInputStream.m in Sources */,
+ B770D6A91375802D00E07924 /* HSRandomDataInputStream.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -228,6 +234,7 @@
B7B2070213557E9500C1C6BA /* Release */,
);
defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
@@ -0,0 +1,17 @@
+//
+// HSRandomDataInputStream.h
+// HSCountingInputStream
+//
+// Created by BJ Homer on 5/7/11.
+// Copyright 2011 BJ Homer. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface HSRandomDataInputStream : NSInputStream {
+@private
+
+}
+
+@end
@@ -0,0 +1,154 @@
+//
+// HSRandomDataInputStream.m
+// HSCountingInputStream
+//
+// Created by BJ Homer on 5/7/11.
+// Copyright 2011 BJ Homer. All rights reserved.
+//
+
+#import "HSRandomDataInputStream.h"
+
+
+@implementation HSRandomDataInputStream
+{
+ NSStreamStatus streamStatus;
+
+ id <NSStreamDelegate> delegate;
+
+ CFReadStreamClientCallBack copiedCallback;
+ CFStreamClientContext copiedContext;
+ CFOptionFlags requestedEvents;
+}
+
+- (id)init
+{
+ self = [super init];
+ if (self) {
+ // Initialization code here.
+ streamStatus = NSStreamStatusNotOpen;
+ }
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [super dealloc];
+}
+
+#pragma mark - NSStream subclass overrides
+
+- (void)open {
+ streamStatus = NSStreamStatusOpen;
+}
+
+- (void)close {
+ streamStatus = NSStreamStatusClosed;
+}
+
+- (id<NSStreamDelegate>)delegate {
+ return delegate;
+}
+
+- (void)setDelegate:(id<NSStreamDelegate>)aDelegate {
+ delegate = aDelegate;
+}
+
+- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode {
+ // Nothing to do here, because this stream does not need a run loop to produce its data.
+}
+
+- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode {
+ // Nothing to do here, because this stream does not need a run loop to produce its data.
+}
+
+- (id)propertyForKey:(NSString *)key {
+ return nil;
+}
+
+- (BOOL)setProperty:(id)property forKey:(NSString *)key {
+ return NO;
+}
+
+- (NSStreamStatus)streamStatus {
+ return streamStatus;
+}
+
+- (NSError *)streamError {
+ return nil;
+}
+
+
+#pragma mark - NSInputStream subclass overrides
+
+- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len {
+
+ for (NSUInteger i=0; i<len; ++i) {
+ buffer[i] = arc4random() & 0x00000000ffffffff;
+ }
+
+ if (CFReadStreamGetStatus((CFReadStreamRef)self) == kCFStreamStatusOpen) {
+
+ double delayInSeconds = 0;
+ dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
+ dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
+ if (copiedCallback && (requestedEvents & kCFStreamEventHasBytesAvailable)) {
+ copiedCallback((CFReadStreamRef)self, kCFStreamEventHasBytesAvailable, &copiedContext);
+ }
+ });
+ }
+
+ return len;
+}
+
+- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len {
+ // Not appropriate for this kind of stream; return NO.
+ return NO;
+}
+
+- (BOOL)hasBytesAvailable {
+ // There are always bytes available.
+ return YES;
+}
+
+#pragma mark - Undocumented CFReadStream bridged methods
+
+- (void)_scheduleInCFRunLoop:(CFRunLoopRef)aRunLoop forMode:(CFStringRef)aMode {
+ // Nothing to do here, because this stream does not need a run loop to produce its data.
+}
+
+- (BOOL)_setCFClientFlags:(CFOptionFlags)inFlags
+ callback:(CFReadStreamClientCallBack)inCallback
+ context:(CFStreamClientContext *)inContext {
+
+ if (inCallback != NULL) {
+ requestedEvents = inFlags;
+ copiedCallback = inCallback;
+ memcpy(&copiedContext, inContext, sizeof(CFStreamClientContext));
+
+ if (copiedContext.info && copiedContext.retain) {
+ copiedContext.retain(copiedContext.info);
+ }
+
+ copiedCallback((CFReadStreamRef)self, kCFStreamEventHasBytesAvailable, &copiedContext);
+ }
+ else {
+ requestedEvents = kCFStreamEventNone;
+ copiedCallback = NULL;
+ if (copiedContext.info && copiedContext.release) {
+ copiedContext.release(copiedContext.info);
+ }
+
+ memset(&copiedContext, 0, sizeof(CFStreamClientContext));
+ }
+
+ return YES;
+
+}
+
+- (void)_unscheduleFromCFRunLoop:(CFRunLoopRef)aRunLoop forMode:(CFStringRef)aMode {
+ // Nothing to do here, because this stream does not need a run loop to produce its data.
+}
+
+
+@end
@@ -8,20 +8,51 @@
#import <Foundation/Foundation.h>
#import "HSCountingInputStream.h"
+#import "HSRandomDataInputStream.h"
void downloadFile();
+void produceRandomData();
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
downloadFile();
+ produceRandomData();
[pool drain];
return 0;
}
+void clientCallback(CFReadStreamRef stream, CFStreamEventType type, void *clientCallBackInfo) {
+ UInt8 buffer[32];
+ CFReadStreamRead(stream, buffer, 32);
+
+ NSData *data = [NSData dataWithBytes:buffer length:32];
+ NSLog(@"Here are 32 random bytes: %@", data);
+
+ CFReadStreamClose(stream);
+}
+
+void produceRandomData() {
+ HSRandomDataInputStream *randomStream = [[HSRandomDataInputStream alloc] init];
+ CFReadStreamRef cfRandomStream = (CFReadStreamRef)randomStream;
+
+ CFReadStreamScheduleWithRunLoop(cfRandomStream, [[NSRunLoop currentRunLoop] getCFRunLoop], kCFRunLoopCommonModes);
+
+ CFStreamClientContext context = {0};
+ CFReadStreamSetClient(cfRandomStream, kCFStreamEventHasBytesAvailable, &clientCallback, &context);
+
+ [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
+
+
+
+
+
+ [randomStream release];
+}
+
void downloadFile() {
// A note: I'm using CFReadStreamCreateForHTTPRequest() here because it's the simplest way I know of

0 comments on commit a27eeeb

Please sign in to comment.