Skip to content

Instantly share code, notes, and snippets.

@pavelosipov
Created December 20, 2015 15:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pavelosipov/aacdaace635e139c016c to your computer and use it in GitHub Desktop.
Save pavelosipov/aacdaace635e139c016c to your computer and use it in GitHub Desktop.
Custom NSInputStream implementation
#import "MRCDataStreamDataSource.h"
@interface MRCDataStreamDataSource ()
@property (nonatomic, readonly) NSData *data;
@property (nonatomic) NSUInteger readOffset;
@property (nonatomic, getter = isOpenCompleted) BOOL openCompleted;
@property (nonatomic) NSError *error;
@end
@implementation MRCDataStreamDataSource
@dynamic hasBytesAvailable, atEnd;
#pragma mark Lifecycle
- (instancetype)initWithData:(NSData *)data {
NSParameterAssert(data);
if (self = [super init]) {
_data = data;
}
return self;
}
#pragma mark POSBlobInputStreamDataSource
- (void)open {
self.openCompleted = YES;
}
- (BOOL)hasBytesAvailable {
return _data.length - _readOffset > 0;
}
- (BOOL)isAtEnd {
return _data.length <= _readOffset;
}
- (id)propertyForKey:(NSString *)key {
if (![key isEqualToString:NSStreamFileCurrentOffsetKey]) {
return nil;
}
return @(_readOffset);
}
- (BOOL)setProperty:(id)property forKey:(NSString *)key {
if (![key isEqualToString:NSStreamFileCurrentOffsetKey]) {
return NO;
}
if (![property isKindOfClass:[NSNumber class]]) {
return NO;
}
NSUInteger requestedOffest = [property unsignedIntegerValue];
self.readOffset = requestedOffest;
return YES;
}
- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)bufferLength {
return NO;
}
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)maxLength {
const NSUInteger readResult = MIN(maxLength, MAX(_data.length - _readOffset, 0));
NSRange dataRange = (NSRange){
.location = _readOffset,
.length = readResult
};
[_data getBytes:buffer range:dataRange];
self.readOffset = (_readOffset + readResult);
return (NSInteger)readResult;
}
#pragma mark Private
- (void)setReadOffset:(NSUInteger)readOffset {
const BOOL atEnd = readOffset >= _data.length;
if (atEnd) {
[self willChangeValueForKey:POSBlobInputStreamDataSourceAtEndKeyPath];
}
_readOffset = readOffset;
if (atEnd) {
[self didChangeValueForKey:POSBlobInputStreamDataSourceAtEndKeyPath];
}
}
@end
@pavelosipov
Copy link
Author

Read more in full article Custom NSInputStream with 100 lines of code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment