Skip to content

Instantly share code, notes, and snippets.

@nevyn
Created November 19, 2013 22:42
Show Gist options
  • Save nevyn/7553896 to your computer and use it in GitHub Desktop.
Save nevyn/7553896 to your computer and use it in GitHub Desktop.
Simple helpers for working with common data types on NSData-backed input and output streams.
#import <Foundation/Foundation.h>
/** @category TCInputStream
@abstract Reads Big Endian data in convenient sizes
*/
@interface NSInputStream (TCInputStream)
- (int8_t)readByte;
- (uint16_t)readShort;
- (uint32_t)readInt;
- (uint64_t)readLongLong;
- (NSString*)readUTF8StringWithLengthSize:(size_t)lengthSize;
- (NSData*)readBytes:(size_t)byteCount;
@end
/** @category TCOutputStream
@abstract Writes Big Endian data in convenient sizes
*/
@interface NSOutputStream (TCOutputStream)
- (void)writeByte:(uint8_t)number;
- (void)writeShort:(uint16_t)number;
- (void)writeInt:(uint32_t)number;
- (void)writeLongLong:(uint64_t)number;
- (void)writeUTF8String:(NSString*)string withLengthSize:(size_t)lengthSize;
- (void)writeData:(NSData*)data;
- (NSData*)tc_data;
@end
#import "TCStream.h"
@implementation NSInputStream (TCInputStream)
- (int8_t)readByte
{
uint16_t number;
size_t lengthRead = [self read:(uint8_t*)&number maxLength:1];
NSAssert(lengthRead == 1, @"Missing data in stream");
return number;
}
- (uint16_t)readShort
{
uint16_t number;
size_t lengthRead = [self read:(uint8_t*)&number maxLength:2];
NSAssert(lengthRead == 2, @"Missing data in stream");
return NSSwapBigShortToHost(number);
}
- (uint32_t)readInt
{
uint32_t number;
size_t lengthRead = [self read:(uint8_t*)&number maxLength:4];
NSAssert(lengthRead == 4, @"Missing data in stream");
return NSSwapBigIntToHost(number);
}
- (uint64_t)readLongLong
{
uint64_t number;
size_t lengthRead = [self read:(uint8_t*)&number maxLength:8];
NSAssert(lengthRead == 8, @"Missing data in stream");
return NSSwapBigLongLongToHost(number);
}
- (NSString*)readUTF8StringWithLengthSize:(size_t)lengthSize
{
NSAssert(lengthSize == 1 || lengthSize == 2 || lengthSize == 4, @"Invalid lengthSize");
uint32_t length = lengthSize == 1 ? [self readByte] :
lengthSize == 2 ? [self readShort] :
/*lengthSize == 4 ?*/[self readInt];
NSData *stringData = [self readBytes:length];
return [[NSString alloc] initWithData:stringData encoding:NSUTF8StringEncoding];
}
- (NSData*)readBytes:(size_t)byteCount
{
NSMutableData *data = [NSMutableData dataWithLength:byteCount];
size_t lengthRead = [self read:data.mutableBytes maxLength:byteCount];
NSAssert(lengthRead == byteCount, @"Missing data in stream");
return data;
}
@end
@implementation NSOutputStream (TCOutputStream)
- (void)writeByte:(uint8_t)number
{
size_t lengthWritten = [self write:(uint8_t*)&number maxLength:1];
NSAssert(lengthWritten == 1, @"Stream ended too early");
}
- (void)writeShort:(uint16_t)number
{
number = NSSwapHostShortToBig(number);
size_t lengthWritten = [self write:(uint8_t*)&number maxLength:2];
NSAssert(lengthWritten == 2, @"Stream ended too early");
}
- (void)writeInt:(uint32_t)number
{
number = NSSwapHostIntToBig(number);
size_t lengthWritten = [self write:(uint8_t*)&number maxLength:4];
NSAssert(lengthWritten == 4, @"Stream ended too early. %@ %@", self, [self streamError]);
}
- (void)writeLongLong:(uint64_t)number
{
number = NSSwapHostLongLongToBig(number);
size_t lengthWritten = [self write:(uint8_t*)&number maxLength:8];
NSAssert(lengthWritten == 8, @"Stream ended too early");
}
- (void)writeUTF8String:(NSString*)string withLengthSize:(size_t)lengthSize
{
NSAssert(lengthSize == 1 || lengthSize == 2 || lengthSize == 4, @"Invalid lengthSize");
NSData *stringData = [string dataUsingEncoding:NSUTF8StringEncoding];
uint32_t length = (uint32_t)stringData.length;
if(lengthSize == 1) [self writeByte:length];
else if(lengthSize == 2) [self writeShort:length];
else if(lengthSize == 4) [self writeInt:length];
size_t lengthWritten = [self write:stringData.bytes maxLength:length];
NSAssert(length == lengthWritten, @"Stream ended too early");
}
- (void)writeData:(NSData*)data
{
[self write:data.bytes maxLength:data.length];
}
- (NSData*)tc_data
{
return [self propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment