Created
April 26, 2017 00:42
-
-
Save swillits/c3ed14f95878085e909677db7dc09980 to your computer and use it in GitHub Desktop.
AGBinaryStream Obj-C
This file contains hidden or 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
// | |
// AGBinaryDataStream.h | |
// AraeliumFoundation | |
// | |
// Created by Seth Willits on 11/15/09. | |
// Copyright 2009 Araelium Group. All rights reserved. | |
// | |
#import <Cocoa/Cocoa.h> | |
#import "AGBinaryStream.h" | |
@interface AGBinaryDataStream : AGBinaryStream { | |
NSData * mData; | |
uint64_t mPosition; | |
} | |
@end |
This file contains hidden or 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
// | |
// AGBinaryDataStream.m | |
// AraeliumFoundation | |
// | |
// Created by Seth Willits on 11/15/09. | |
// Copyright 2009 Araelium Group. All rights reserved. | |
// | |
#import "AGBinaryDataStream.h" | |
#define AGBinaryStreamRaiseIfNoData \ | |
if (!mData) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryDataStream has no data"]; | |
#define AGBinaryDataStreamReadBytes(arg_data, arg_length) \ | |
if ((NSUInteger)(mPosition) + (NSUInteger)(arg_length) <= [mData length]) { \ | |
[mData getBytes:(arg_data) range:NSMakeRange((NSUInteger)mPosition, (NSUInteger)(arg_length))]; \ | |
mPosition += (arg_length); \ | |
} else { \ | |
mPosition = (uint64_t)[self length]; \ | |
[NSException raise:AGBinaryStreamEndOfStreamException format:@"AGBinaryStream reached EOF"]; \ | |
} | |
#define AGBinaryDataStreamWriteBytes(arg_data, arg_length) \ | |
if ((NSUInteger)(mPosition + (arg_length)) > [mData length]) { \ | |
[(NSMutableData *)mData increaseLengthBy:(NSUInteger)((NSUInteger)(mPosition + (arg_length)) - [mData length])]; \ | |
} \ | |
[(NSMutableData *)mData replaceBytesInRange:NSMakeRange((NSUInteger)mPosition, (NSUInteger)(arg_length)) withBytes:(arg_data) length:(NSUInteger)(arg_length)]; \ | |
mPosition += (arg_length); | |
@implementation AGBinaryDataStream | |
- (id)initWithData:(NSData *)data; | |
{ | |
if (!(self = [super init])) { | |
[self release]; | |
return nil; | |
} | |
if (data) { | |
mData = [data retain]; | |
} else { | |
mData = [[NSMutableData alloc] init]; | |
} | |
mLittleEndian = NO; | |
return self; | |
} | |
- (void)dealloc; | |
{ | |
[self close]; | |
[mData release]; | |
[super dealloc]; | |
} | |
- (BOOL)open:(NSInteger)options error:(NSError **)error; | |
{ | |
[self close]; | |
// Endianness | |
if (options & AGBSOptionsLittleEndian) { | |
mLittleEndian = YES; | |
} else if (options & AGBSOptionsBigEndian) { | |
mLittleEndian = NO; | |
} else { | |
#if BS_Byte_Order == BS_LITTLE_ENDIAN | |
mLittleEndian = YES; | |
#else | |
mLittleEndian = NO; | |
#endif | |
} | |
if (options & AGBSOptionsWrite) { | |
if (![mData isKindOfClass:[NSMutableData class]]) { | |
[mData autorelease]; | |
mData = [[NSMutableData alloc] initWithData:mData]; | |
} | |
} | |
return YES; | |
} | |
- (void)close; | |
{ | |
} | |
- (void)flush; | |
{ | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// | |
// Options and Such | |
// | |
////////////////////////////////////////////////////////////////////////////////// | |
#pragma mark - | |
#pragma mark Accessors | |
- (FILE *)file; | |
{ | |
return NULL; | |
} | |
- (NSData *)data; | |
{ | |
return mData; | |
} | |
- (BOOL)isEndOfFile; | |
{ | |
return ([self position] == [self length]); | |
} | |
- (NSInteger)lastErrorCode; | |
{ | |
return 0; | |
} | |
- (uint64_t)length; | |
{ | |
return [mData length]; | |
} | |
- (void)setLength:(uint64_t)length; | |
{ | |
[(NSMutableData *)mData setLength:(NSUInteger)length]; | |
} | |
- (BOOL)isLittleEndian; | |
{ | |
return mLittleEndian; | |
} | |
- (void)setLittleEndian:(BOOL)set; | |
{ | |
mLittleEndian = set; | |
} | |
- (off_t)position; | |
{ | |
return (off_t)mPosition; | |
} | |
- (void)setPosition:(off_t)pos; | |
{ | |
mPosition = pos; | |
if (mPosition > [self length]) { | |
[(NSMutableData *)mData increaseLengthBy:(NSUInteger)(mPosition - [mData length])]; | |
} | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// | |
// File Writing | |
// | |
////////////////////////////////////////////////////////////////////////////////// | |
#pragma mark - | |
#pragma mark Writing | |
- (size_t)writeData:(const void *)data length:(unsigned long)length; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamWriteBytes(data, length) | |
return length; | |
} | |
- (void)writeDouble:(double)data; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
double value = data; | |
uint64_t intValue = *(uint64_t*)&value; | |
if (mLittleEndian != BS_Byte_Order) { | |
intValue = BS_Swap64(intValue); | |
} | |
AGBinaryDataStreamWriteBytes(&intValue, sizeof(intValue)) | |
} | |
- (void)writeFloat:(float)data; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
float value = data; | |
uint32_t intValue = *(uint32_t*)&value; | |
if (mLittleEndian != BS_Byte_Order) { | |
intValue = BS_Swap32(intValue); | |
} | |
AGBinaryDataStreamWriteBytes(&intValue, sizeof(intValue)) | |
} | |
- (void)writeBool:(BOOL)data; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
char value = 0; | |
if (data) value = 1; | |
AGBinaryDataStreamWriteBytes(&value, sizeof(value)) | |
} | |
- (void)writeInt8:(int8_t)data; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
int8_t value = data; | |
AGBinaryDataStreamWriteBytes(&value, sizeof(value)) | |
} | |
- (void)writeInt16:(int16_t)data; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
int16_t value = (mLittleEndian == BS_Byte_Order) ? data : BS_Swap16(data); | |
AGBinaryDataStreamWriteBytes(&value, sizeof(value)) | |
} | |
- (void)writeInt32:(int32_t)data; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
int32_t value = (mLittleEndian == BS_Byte_Order) ? data : BS_Swap32(data); | |
AGBinaryDataStreamWriteBytes(&value, sizeof(value)) | |
} | |
- (void)writeInt64:(int64_t)data; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
int64_t value = (mLittleEndian == BS_Byte_Order) ? data : BS_Swap64(data); | |
AGBinaryDataStreamWriteBytes(&value, sizeof(value)) | |
} | |
- (void)writeUInt8:(uint8_t)data; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
uint8_t value = data; | |
AGBinaryDataStreamWriteBytes(&value, sizeof(value)) | |
} | |
- (void)writeUInt16:(uint16_t)data; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
uint16_t value = (mLittleEndian == BS_Byte_Order) ? data : BS_Swap16(data); | |
AGBinaryDataStreamWriteBytes(&value, sizeof(value)) | |
} | |
- (void)writeUInt32:(uint32_t)data; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
uint32_t value = (mLittleEndian == BS_Byte_Order) ? data : BS_Swap32(data); | |
AGBinaryDataStreamWriteBytes(&value, sizeof(value)) | |
} | |
- (void)writeUInt64:(uint64_t)data; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
uint64_t value = (mLittleEndian == BS_Byte_Order) ? data : BS_Swap64(data); | |
AGBinaryDataStreamWriteBytes(&value, sizeof(value)) | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// | |
// File Reading | |
// | |
////////////////////////////////////////////////////////////////////////////////// | |
#pragma mark - | |
#pragma mark Reading | |
- (size_t)readData:(void *)data length:(unsigned long)length; | |
{ | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamReadBytes(data, length) | |
return length; | |
} | |
- (double)readDouble; | |
{ | |
double value; | |
uint64_t intValue = 0; | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamReadBytes(&intValue, sizeof(uint64_t)); | |
if (mLittleEndian != BS_Byte_Order) { | |
intValue = BS_Swap64(intValue); | |
} | |
value = *(double*)(&intValue); | |
return value; | |
} | |
- (float)readFloat; | |
{ | |
float value; | |
uint32_t intValue = 0; | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamReadBytes(&intValue, sizeof(uint32_t)); | |
if (mLittleEndian != BS_Byte_Order) { | |
intValue = BS_Swap32(intValue); | |
} | |
value = *(float*)(&intValue); | |
return value; | |
} | |
- (BOOL)readBool; | |
{ | |
char value = 0; | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamReadBytes(&value, sizeof(value)); | |
return (value != '\0'); | |
} | |
- (int8_t)readInt8; | |
{ | |
int8_t value = 0; | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamReadBytes(&value, sizeof(value)); | |
return value; | |
} | |
- (int16_t)readInt16; | |
{ | |
int16_t value = 0; | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamReadBytes(&value, sizeof(value)); | |
if (mLittleEndian != BS_Byte_Order) value = BS_Swap16(value); | |
return value; | |
} | |
- (int32_t)readInt32; | |
{ | |
int32_t value = 0; | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamReadBytes(&value, sizeof(value)); | |
if (mLittleEndian != BS_Byte_Order) value = BS_Swap32(value); | |
return value; | |
} | |
- (int64_t)readInt64; | |
{ | |
int64_t value = 0; | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamReadBytes(&value, sizeof(value)); | |
if (mLittleEndian != BS_Byte_Order) value = BS_Swap64(value); | |
return value; | |
} | |
- (uint8_t)readUInt8; | |
{ | |
uint8_t value = 0; | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamReadBytes(&value, sizeof(value)); | |
return value; | |
} | |
- (uint16_t)readUInt16; | |
{ | |
uint16_t value = 0; | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamReadBytes(&value, sizeof(value)); | |
if (mLittleEndian != BS_Byte_Order) value = BS_Swap16(value); | |
return value; | |
} | |
- (uint32_t)readUInt32; | |
{ | |
uint32_t value = 0; | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamReadBytes(&value, sizeof(value)); | |
if (mLittleEndian != BS_Byte_Order) value = BS_Swap32(value); | |
return value; | |
} | |
- (uint64_t)readUInt64; | |
{ | |
uint64_t value = 0; | |
AGBinaryStreamRaiseIfNoData | |
AGBinaryDataStreamReadBytes(&value, sizeof(value)) | |
if (mLittleEndian != BS_Byte_Order) value = BS_Swap64(value); | |
return value; | |
} | |
@end | |
This file contains hidden or 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
// | |
// AGBinaryFileStream.h | |
// AraeliumFoundation | |
// | |
// Created by Seth Willits on 11/15/09. | |
// Copyright 2009 Araelium Group. All rights reserved. | |
// | |
#import <Cocoa/Cocoa.h> | |
#import "AGBinaryStream.h" | |
@interface AGBinaryFileStream : AGBinaryStream { | |
NSString * mFilePath; | |
FILE * mFile; | |
NSInteger mLastErrorCode; | |
} | |
@end |
This file contains hidden or 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
// | |
// AGBinaryFileStream.m | |
// AraeliumFoundation | |
// | |
// Created by Seth Willits on 11/15/09. | |
// Copyright 2009 Araelium Group. All rights reserved. | |
// | |
#import "AGBinaryFileStream.h" | |
@implementation AGBinaryFileStream | |
- (id)initWithFilePath:(NSString *)filePath; | |
{ | |
if (!(self = [super init])) { | |
[self release]; | |
return nil; | |
} | |
assert(filePath != nil); | |
mFilePath = [filePath copy]; | |
mLittleEndian = NO; | |
mLastErrorCode = 0; | |
return self; | |
} | |
- (void)dealloc; | |
{ | |
[self close]; | |
[mFilePath release]; | |
[super dealloc]; | |
} | |
- (BOOL)open:(NSInteger)options error:(NSError **)error; | |
{ | |
[self close]; | |
// Endianness | |
if (options & AGBSOptionsLittleEndian) { | |
mLittleEndian = YES; | |
} else if (options & AGBSOptionsBigEndian) { | |
mLittleEndian = NO; | |
} else { | |
#if BS_Byte_Order == BS_LITTLE_ENDIAN | |
mLittleEndian = YES; | |
#else | |
mLittleEndian = NO; | |
#endif | |
} | |
// Make Options String | |
char flags[4] = {'\0'}; NSInteger flag = 0; | |
if ((options & AGBSOptionsRead) && (options & AGBSOptionsWrite)) { | |
flags[flag++] = 'w'; | |
flags[flag++] = '+'; | |
} else if (options & AGBSOptionsRead) { | |
flags[flag++] = 'r'; | |
} else if (options & AGBSOptionsWrite) { | |
flags[flag++] = 'w'; | |
} | |
// Always binary | |
flags[flag] = 'b'; | |
// Open the File | |
mFile = fopen([mFilePath fileSystemRepresentation], flags); | |
if (!mFile) { | |
mLastErrorCode = errno; | |
if (error) *error = [NSError errorWithDomain:NSPOSIXErrorDomain code:mLastErrorCode userInfo:[NSDictionary dictionaryWithObjectsAndKeys: | |
[NSString stringWithFormat:@"Could not open file %@", mFilePath], NSLocalizedDescriptionKey, | |
[NSString stringWithFormat:@"AGBinaryStream: failed to open %@. Error (%d) %s", mFilePath, (int)mLastErrorCode, strerror(errno)], NSLocalizedFailureReasonErrorKey, | |
nil]]; | |
return NO; | |
} | |
return YES; | |
} | |
- (void)close; | |
{ | |
if (mFile) { | |
if (fclose(mFile)) { | |
mLastErrorCode = errno; | |
} else { | |
mLastErrorCode = 0; | |
} | |
mFile = NULL; | |
} | |
} | |
- (void)flush; | |
{ | |
if (mFile) { | |
if (fflush(mFile)) { | |
mLastErrorCode = errno; | |
} else { | |
mLastErrorCode = 0; | |
} | |
} | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// | |
// Options and Such | |
// | |
////////////////////////////////////////////////////////////////////////////////// | |
#pragma mark - | |
#pragma mark Accessors | |
- (FILE *)file; | |
{ | |
return mFile; | |
} | |
- (NSData *)data; | |
{ | |
return nil; | |
} | |
- (BOOL)isEndOfFile; | |
{ | |
if (mFile) { | |
if (self.position == self.length) { | |
return YES; | |
} | |
return (feof(mFile) == 1); | |
} | |
return YES; | |
} | |
- (NSInteger)lastErrorCode; | |
{ | |
if (mFile) { | |
return mLastErrorCode; //ferror(mFile); | |
} | |
return -1; | |
} | |
- (uint64_t)length; | |
{ | |
off_t currentPosition = [self position]; | |
uint64_t length = 0; | |
if (mFile) { | |
if (fseeko(mFile, 0, SEEK_END)) { | |
mLastErrorCode = errno; | |
} else { | |
length = [self position]; | |
[self setPosition:currentPosition]; | |
} | |
} | |
return length; | |
} | |
- (void)setLength:(uint64_t)length; | |
{ | |
[self doesNotRecognizeSelector:_cmd]; | |
} | |
- (BOOL)isLittleEndian; | |
{ | |
return mLittleEndian; | |
} | |
- (void)setLittleEndian:(BOOL)set; | |
{ | |
mLittleEndian = set; | |
} | |
- (off_t)position; | |
{ | |
off_t position = 0; | |
if (mFile) { | |
position = ftello(mFile); | |
if (position == -1) { | |
mLastErrorCode = errno; | |
} else { | |
mLastErrorCode = 0; | |
} | |
} | |
return position; | |
} | |
- (void)setPosition:(off_t)pos; | |
{ | |
if (mFile) { | |
if (fseeko(mFile, pos, SEEK_SET)) { | |
mLastErrorCode = errno; | |
} else { | |
mLastErrorCode = 0; | |
} | |
} | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// | |
// File Writing | |
// | |
////////////////////////////////////////////////////////////////////////////////// | |
#pragma mark - | |
#pragma mark Writing | |
- (size_t)writeData:(const void *)data length:(unsigned long)length; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
size_t written = fwrite(data, 1, length, mFile); | |
mLastErrorCode = (written == length ? 0 : errno); | |
return written; | |
} | |
- (void)writeDouble:(double)data; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
double value = data; | |
uint64_t intValue = *(uint64_t*)&value; | |
if (mLittleEndian != BS_Byte_Order) { | |
intValue = BS_Swap64(intValue); | |
} | |
size_t written = fwrite(&intValue, sizeof(uint64_t), 1, mFile); | |
mLastErrorCode = (written == 1 ? 0 : errno); | |
} | |
- (void)writeFloat:(float)data; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
float value = data; | |
uint32_t intValue = *(uint32_t*)&value; | |
if (mLittleEndian != BS_Byte_Order) { | |
intValue = BS_Swap32(intValue); | |
} | |
size_t written = fwrite(&intValue, sizeof(uint32_t), 1, mFile); | |
mLastErrorCode = (written == 1 ? 0 : errno); | |
} | |
- (void)writeBool:(BOOL)data; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
char value = 0; | |
if (data) value = 1; | |
size_t written = fwrite(&value, sizeof(char), 1, mFile); | |
mLastErrorCode = (written == 1 ? 0 : errno); | |
} | |
- (void)writeInt8:(int8_t)data; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
int8_t value = data; | |
size_t written = fwrite(&value, sizeof(int8_t), 1, mFile); | |
mLastErrorCode = (written == 1 ? 0 : errno); | |
} | |
- (void)writeInt16:(int16_t)data; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
int16_t value = (mLittleEndian == BS_Byte_Order) ? data : BS_Swap16(data); | |
size_t written = fwrite(&value, sizeof(int16_t), 1, mFile); | |
mLastErrorCode = (written == 1 ? 0 : errno); | |
} | |
- (void)writeInt32:(int32_t)data; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
int32_t value = (mLittleEndian == BS_Byte_Order) ? data : BS_Swap32(data); | |
size_t written = fwrite(&value, sizeof(int32_t), 1, mFile); | |
mLastErrorCode = (written == 1 ? 0 : errno); | |
} | |
- (void)writeInt64:(int64_t)data; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
int64_t value = (mLittleEndian == BS_Byte_Order) ? data : BS_Swap64(data); | |
size_t written = fwrite(&value, sizeof(int64_t), 1, mFile); | |
mLastErrorCode = (written == 1 ? 0 : errno); | |
} | |
- (void)writeUInt8:(uint8_t)data; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
uint8_t value = data; | |
size_t written = fwrite(&value, sizeof(uint8_t), 1, mFile); | |
mLastErrorCode = (written == 1 ? 0 : errno); | |
} | |
- (void)writeUInt16:(uint16_t)data; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
uint16_t value = (mLittleEndian == BS_Byte_Order) ? data : BS_Swap16(data); | |
size_t written = fwrite(&value, sizeof(uint16_t), 1, mFile); | |
mLastErrorCode = (written == 1 ? 0 : errno); | |
} | |
- (void)writeUInt32:(uint32_t)data; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
uint32_t value = (mLittleEndian == BS_Byte_Order) ? data : BS_Swap32(data); | |
size_t written = fwrite(&value, sizeof(uint32_t), 1, mFile); | |
mLastErrorCode = (written == 1 ? 0 : errno); | |
} | |
- (void)writeUInt64:(uint64_t)data; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
uint64_t value = (mLittleEndian == BS_Byte_Order) ? data : BS_Swap64(data); | |
size_t written = fwrite(&value, sizeof(uint64_t), 1, mFile); | |
mLastErrorCode = (written == 1 ? 0 : errno); | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// | |
// File Reading | |
// | |
////////////////////////////////////////////////////////////////////////////////// | |
#pragma mark - | |
#pragma mark Reading | |
- (size_t)readData:(void *)data length:(unsigned long)length; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
size_t result = fread(data, 1, length, mFile); | |
AGBinaryStreamRaiseReadEOF(result, length); | |
return result; | |
} | |
- (double)readDouble; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
double value; | |
uint64_t intValue = 0; | |
size_t result = fread(&intValue, sizeof(uint64_t), 1, mFile); | |
AGBinaryStreamRaiseReadEOF(result, 1); | |
if (mLittleEndian != BS_Byte_Order) { | |
intValue = BS_Swap64(intValue); | |
} | |
value = *(double*)(&intValue); | |
return value; | |
} | |
- (float)readFloat; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
float value; | |
uint32_t intValue = 0; | |
size_t result = fread(&intValue, sizeof(uint32_t), 1, mFile); | |
AGBinaryStreamRaiseReadEOF(result, 1); | |
if (mLittleEndian != BS_Byte_Order) { | |
intValue = BS_Swap32(intValue); | |
} | |
value = *(float*)(&intValue); | |
return value; | |
} | |
- (BOOL)readBool; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
char value = 0; | |
size_t result = fread(&value, sizeof(char), 1, mFile); | |
AGBinaryStreamRaiseReadEOF(result, 1); | |
if (value != '\0') | |
return YES; | |
return NO; | |
} | |
- (int8_t)readInt8; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
int8_t value = 0; | |
size_t result = fread(&value, sizeof(int8_t), 1, mFile); | |
AGBinaryStreamRaiseReadEOF(result, 1); | |
return value; | |
} | |
- (int16_t)readInt16; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
int16_t value = 0; | |
size_t result = fread(&value, sizeof(int16_t), 1, mFile); | |
AGBinaryStreamRaiseReadEOF(result, 1); | |
if (mLittleEndian != BS_Byte_Order) value = BS_Swap16(value); | |
return value; | |
} | |
- (int32_t)readInt32; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
int32_t value = 0; | |
size_t result = fread(&value, sizeof(int32_t), 1, mFile); | |
AGBinaryStreamRaiseReadEOF(result, 1); | |
if (mLittleEndian != BS_Byte_Order) value = BS_Swap32(value); | |
return value; | |
} | |
- (int64_t)readInt64; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
int64_t value = 0; | |
size_t result = fread(&value, sizeof(int64_t), 1, mFile); | |
AGBinaryStreamRaiseReadEOF(result, 1); | |
if (mLittleEndian != BS_Byte_Order) value = BS_Swap64(value); | |
return value; | |
} | |
- (uint8_t)readUInt8; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
uint8_t value = 0; | |
size_t result = fread(&value, sizeof(uint8_t), 1, mFile); | |
AGBinaryStreamRaiseReadEOF(result, 1); | |
return value; | |
} | |
- (uint16_t)readUInt16; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
uint16_t value = 0; | |
size_t result = fread(&value, sizeof(uint16_t), 1, mFile); | |
AGBinaryStreamRaiseReadEOF(result, 1); | |
if (mLittleEndian != BS_Byte_Order) value = BS_Swap16(value); | |
return value; | |
} | |
- (uint32_t)readUInt32; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
uint32_t value = 0; | |
size_t result = fread(&value, sizeof(uint32_t), 1, mFile); | |
AGBinaryStreamRaiseReadEOF(result, 1); | |
if (mLittleEndian != BS_Byte_Order) value = BS_Swap32(value); | |
return value; | |
} | |
- (uint64_t)readUInt64; | |
{ | |
if (!mFile) [NSException raise:NSInternalInconsistencyException format:@"AGBinaryStream has no FILE"]; | |
uint64_t value = 0; | |
size_t result = fread(&value, sizeof(uint64_t), 1, mFile); | |
AGBinaryStreamRaiseReadEOF(result, 1); | |
if (mLittleEndian != BS_Byte_Order) value = BS_Swap64(value); | |
return value; | |
} | |
@end | |
This file contains hidden or 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
// | |
// AGBinaryStream.h | |
// Araelium Foundation | |
// | |
// Created by Seth Willits on 1/31/07. | |
// Copyright 2007 Araelium Group. All rights reserved. | |
// | |
#import <Cocoa/Cocoa.h> | |
NS_ASSUME_NONNULL_BEGIN | |
typedef enum { | |
AGBSOptionsRead = 1 << 1, | |
AGBSOptionsWrite = 1 << 2, | |
AGBSOptionsLittleEndian = 1 << 3, | |
AGBSOptionsBigEndian = 1 << 4, | |
AGBSOptionsDefault = AGBSOptionsRead, | |
AGBSOptionsDefaultL = AGBSOptionsRead | AGBSOptionsLittleEndian, | |
AGBSOptionsDefaultB = AGBSOptionsRead | AGBSOptionsBigEndian | |
} AGBinaryStreamOptions; | |
extern NSString * AGBinaryStreamEndOfStreamException; | |
extern NSString * AGBinaryStreamReadErrorException; | |
@interface AGBinaryStream : NSObject { | |
BOOL mLittleEndian; | |
} | |
@end | |
@interface AGBinaryStream (Methods) | |
- (instancetype)initWithFilePath:(NSString *)filePath; | |
- (instancetype)initWithData:(NSData * _Nullable)data; | |
- (BOOL)open:(NSInteger)options error:(NSError **)error; | |
- (void)close; | |
- (void)flush; | |
/// Returns nil if the stream was initialized with data and not a file path. | |
- (FILE * _Nullable)file; | |
/// Returns nil if the stream was initialized with a file path and not data. | |
- (NSData * _Nullable)data; | |
- (BOOL)isEndOfFile; | |
- (NSInteger)lastErrorCode; | |
- (uint64_t)length; | |
- (void)setLength:(uint64_t)length; | |
- (BOOL)isLittleEndian; | |
- (void)setLittleEndian:(BOOL)set; | |
- (off_t)position; | |
- (void)setPosition:(off_t)pos; | |
- (void)offsetPosition:(off_t)pos; | |
- (size_t)writeData:(const void *)data length:(unsigned long)length; | |
- (void)writeDouble:(double)data; | |
- (void)writeFloat:(float)data; | |
- (void)writeBool:(BOOL)data; | |
- (void)writeInt8:(int8_t)data; | |
- (void)writeInt16:(int16_t)data; | |
- (void)writeInt32:(int32_t)data; | |
- (void)writeInt64:(int64_t)data; | |
- (void)writeUInt8:(uint8_t)data; | |
- (void)writeUInt16:(uint16_t)data; | |
- (void)writeUInt32:(uint32_t)data; | |
- (void)writeUInt64:(uint64_t)data; | |
- (size_t)readData:(void *)data length:(unsigned long)length; | |
- (double)readDouble; | |
- (float)readFloat; | |
- (BOOL)readBool; | |
- (int8_t)readInt8; | |
- (int16_t)readInt16; | |
- (int32_t)readInt32; | |
- (int64_t)readInt64; | |
- (uint8_t)readUInt8; | |
- (uint16_t)readUInt16; | |
- (uint32_t)readUInt32; | |
- (uint64_t)readUInt64; | |
@end | |
@interface AGBinaryStream (Additions) | |
- (void)writeString:(NSString *)string; // always utf8 encoding | |
- (NSString * _Nullable)readString; // always utf8 encoding | |
- (NSData *)readDataOfLength:(unsigned long)length; | |
@end | |
// --------- Intended for internal use ------------ // | |
// Determines the Endianness of the Processor | |
#define BS_LITTLE_ENDIAN 1 | |
#define BS_BIG_ENDIAN 0 | |
#if defined(__LITTLE_ENDIAN__) | |
#define BS_Byte_Order BS_LITTLE_ENDIAN | |
#else | |
#define BS_Byte_Order BS_BIG_ENDIAN | |
#endif | |
// Byte swapping | |
#define BS_Swap16(arg) CFSwapInt16(arg) | |
#define BS_Swap32(arg) CFSwapInt32(arg) | |
#define BS_Swap64(arg) CFSwapInt64(arg) | |
#define AGBinaryStreamRaiseReadEOF(result, size) \ | |
if (result != size) {\ | |
mLastErrorCode = errno;\ | |
if (feof(mFile)) {\ | |
[NSException raise:AGBinaryStreamEndOfStreamException format:@"AGBinaryStream reached EOF"];\ | |
} else {\ | |
NSException * exception = [NSException exceptionWithName:AGBinaryStreamReadErrorException reason:NSSTRF(@"Error %d when reading", (int)mLastErrorCode) userInfo:@{@"errno" : @(mLastErrorCode)}];\ | |
[exception raise];\ | |
}\ | |
} else {\ | |
mLastErrorCode = 0;\ | |
} | |
NS_ASSUME_NONNULL_END |
This file contains hidden or 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
// | |
// AGBinaryStream.m | |
// Screenflick | |
// | |
// Created by Seth Willits on 1/31/07. | |
// Copyright 2007 Araelium Group. All rights reserved. | |
// | |
#import "AGBinaryStream.h" | |
//#import "AGBinaryFileStream.h" | |
//#import "AGBinaryDataStream.h" | |
NSString * AGBinaryStreamEndOfStreamException = @"AGBinaryStreamEndOfStreamException"; | |
NSString * AGBinaryStreamReadErrorException = @"AGBinaryStreamReadErrorException"; | |
@implementation AGBinaryStream | |
- (id)initWithFilePath:(NSString *)filePath; | |
{ | |
[self release]; | |
return [[NSClassFromString(@"AGBinaryFileStream") alloc] initWithFilePath:filePath]; | |
} | |
- (id)initWithData:(NSData *)data; | |
{ | |
[self release]; | |
return [[NSClassFromString(@"AGBinaryDataStream") alloc] initWithData:data]; | |
} | |
- (void)offsetPosition:(off_t)pos; | |
{ | |
[self setPosition:([self position] + pos)]; | |
} | |
@end | |
////////////////////////////////////////////////////////////////////////////////// | |
// | |
// Additions | |
// | |
////////////////////////////////////////////////////////////////////////////////// | |
#pragma mark | |
#pragma mark | |
@implementation AGBinaryStream (Additions) | |
- (void)writeString:(NSString *)string; // always utf8 encoding | |
{ | |
[self writeBool:(string != nil)]; | |
NSData * data = [string dataUsingEncoding:NSUTF8StringEncoding]; | |
uint32_t length = (uint32_t)[data length]; | |
[self writeUInt32:length]; | |
if (length > 0) { | |
[self writeData:[data bytes] length:length]; | |
} | |
} | |
- (NSString *)readString; | |
{ | |
BOOL isValid = [self readBool]; | |
if (!isValid) { | |
return nil; | |
} | |
uint32_t length = [self readUInt32]; | |
if (length == 0) { | |
return @""; | |
} | |
NSMutableData * data = [NSMutableData dataWithLength:length]; | |
[self readData:[data mutableBytes] length:length]; | |
return [[[NSString alloc] initWithBytes:[data bytes] length:length encoding:NSUTF8StringEncoding] autorelease]; | |
} | |
- (NSData *)readDataOfLength:(unsigned long)length; | |
{ | |
NSMutableData * data = [NSMutableData dataWithLength:length]; | |
[self readData:[data mutableBytes] length:length]; | |
return data; | |
} | |
@end | |
////////////////////////////////////////////////////////////////////////////////// | |
// | |
// Byte Swapping | |
// | |
////////////////////////////////////////////////////////////////////////////////// | |
#pragma mark | |
#pragma mark | |
#pragma mark Byte Swapping | |
#ifndef BS_Swap16 | |
static __inline__ uint16_t BS_Swap16(uint16_t D) { | |
return((D<<8)|(D>>8)); | |
} | |
#endif | |
#ifndef BS_Swap32 | |
static __inline__ uint32_t BS_Swap32(uint32_t D) { | |
return((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24)); | |
} | |
#endif | |
#ifndef BS_Swap64 | |
static __inline__ uint64_t BS_Swap64(uint64_t val) { | |
uint32_t hi, lo; | |
/* Separate into high and low 32-bit values and swap them */ | |
lo = (uint32_t)(val&0xFFFFFFFF); | |
val >>= 32; | |
hi = (uint32_t)(val&0xFFFFFFFF); | |
val = BS_Swap32(lo); | |
val <<= 32; | |
val |= BS_Swap32(hi); | |
return(val); | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment