Created
December 20, 2015 15:28
-
-
Save pavelosipov/aacdaace635e139c016c to your computer and use it in GitHub Desktop.
Custom NSInputStream implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Read more in full article Custom NSInputStream with 100 lines of code.