////////////////////////////////////////////////////////////////////////
// RBDataWriter.m
////////////////////////////////////////////////////////////////////////
// A wrapper for an NSMutableData object.
////////////////////////////////////////////////////////////////////////
#import "RBDataWriter.h"
@implementation RBDataWriter
////////////////////////////////////////////////////////////////////////
// initializers
////////////////////////////////////////////////////////////////////////
- (id)init {
return [self initWithData:[NSData data]];
}
- (id)initWithMutableData:(NSMutableData*)theData {
if (self = [super init]) {
[self setData:theData];
[self setEncoding:NSUTF8StringEncoding];
}
return self;
}
+ (RBDataWriter*)writerWithData:(NSMutableData*)theData {
RBDataWriter *result = [[self alloc] initWithData:theData];
[result setEncoding:NSUTF8StringEncoding];
return [result autorelease];
}
- (void)dealloc {
[super dealloc];
}
////////////////////////////////////////////////////////////////////////
// setting primitive types at the current index cursor location
////////////////////////////////////////////////////////////////////////
- (void)setChar:(char)newChar {
NSRange range = { [self index], SIZE_CHAR };
NS_DURING
[data replaceBytesInRange:range withBytes:&newChar];
NS_HANDLER
// NSLog(@"RBDataWriter:setChar: caught exception: %@", [localException name]);
[localException raise];
NS_ENDHANDLER
[self skip:SIZE_CHAR];
}
- (void)setUnsignedChar:(unsigned char)newChar {
[self setChar:(char)newChar];
}
- (void)setShort:(short)newShort {
NSRange range = { [self index], SIZE_SHORT };
NS_DURING
[data replaceBytesInRange:range withBytes:&newShort];
NS_HANDLER
// NSLog(@"RBDataWriter:setShort: caught exception: %@", [localException name]);
[localException raise];
NS_ENDHANDLER
[self skip:SIZE_SHORT];
}
- (void)setUnsignedShort:(unsigned short)newShort {
[self setShort:(short)newShort];
}
- (void)setInt:(int)newInt {
NSRange range = { [self index], SIZE_INT };
NS_DURING
[data replaceBytesInRange:range withBytes:&newInt];
NS_HANDLER
// NSLog(@"RBDataWriter:setInt: caught exception: %@", [localException name]);
[localException raise];
NS_ENDHANDLER
[self skip:SIZE_INT];
}
- (void)setUnsignedInt:(unsigned int)newInt {
[self setInt:(int)newInt];
}
- (void)setLong:(long)newLong {
NSRange range = { [self index], SIZE_LONG };
NS_DURING
[data replaceBytesInRange:range withBytes:&newLong];
NS_HANDLER
// NSLog(@"RBDataWriter:setLong: caught exception: %@", [localException name]);
[localException raise];
NS_ENDHANDLER
[self skip:SIZE_LONG];
}
- (void)setUnsignedLong:(unsigned long)newLong {
[self setLong:(long)newLong];
}
/*
- (float)setFloat {
unsigned char buf[SIZE_FLOAT];
NSRange range = { [self index], SIZE_FLOAT };
NS_DURING
[data setBytes:&buf range:range];
NS_HANDLER
// NSLog(@"RBDataWriter:setFloat: caught exception: %@", [localException name]);
[localException raise];
return (float)0.0;
NS_ENDHANDLER
[self skip:SIZE_FLOAT];
if ([self endian] == ENDIAN_FLIPPED) {
return (float)((buf[1] & 0xFF) << 24 | (buf[0] & 0xFF) << 16 | (buf[3] & 0xFF) << 8 | (buf[2] & 0xFF));
} else {
return (float)((buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 | (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF));
}
}
- (double)setDouble {
unsigned char buf[SIZE_DOUBLE];
NSRange range = { [self index], SIZE_DOUBLE };
NS_DURING
[data setBytes:&buf range:range];
NS_HANDLER
// NSLog(@"RBDataWriter:setDouble: caught exception: %@", [localException name]);
[localException raise];
return (double)0.0;
NS_ENDHANDLER
[self skip:SIZE_DOUBLE];
if ([self endian] == ENDIAN_FLIPPED) {
return (double)((buf[1] & 0xFF) << 56 | (buf[0] & 0xFF) << 48 | (buf[3] & 0xFF) << 40 | (buf[2] & 0xFF) << 32 | (buf[5] & 0xFF) << 24 | (buf[4] & 0xFF) << 16 | (buf[7] & 0xFF) << 8 | (buf[6] & 0xFF));
} else {
return (double)((buf[0] & 0xFF) << 56 | (buf[1] & 0xFF) << 48 | (buf[2] & 0xFF) << 40 | (buf[3] & 0xFF) << 32 | (buf[4] & 0xFF) << 24 | (buf[5] & 0xFF) << 16 | (buf[6] & 0xFF) << 8 | (buf[7] & 0xFF));
}
}
*/
- (void)setString:(NSString*)s {
NSRange r = { index, [s length] };
NSData *stringData = [s dataUsingEncoding:encoding];
unsigned char bytes[[s length]];
[stringData getBytes:&bytes];
[data replaceBytesInRange:r withBytes:&bytes];
}
////////////////////////////////////////////////////////////////////////
// setting primitive types at an arbitrary offset (the index cursor is
// not moved)
////////////////////////////////////////////////////////////////////////
- (void)setChar:(char)newChar atOffset:(int)offset {
int x = index;
[self setIndex:offset];
[self setChar:newChar];
[self setIndex:x];
}
- (void)setUnsignedChar:(unsigned char)newChar atOffset:(int)offset {
[self setChar:(char)newChar atOffset:offset];
}
- (void)setShort:(short)newShort atOffset:(int)offset {
int x = index;
[self setIndex:offset];
[self setShort:newShort];
[self setIndex:x];
}
- (void)setUnsignedShort:(unsigned short)newShort atOffset:(int)offset {
[self setShort:(short)newShort atOffset:offset];
}
- (void)setInt:(int)newInt atOffset:(int)offset {
int x = index;
[self setIndex:offset];
[self setInt:newInt];
[self setIndex:x];
}
- (void)setUnsignedInt:(unsigned int)newInt atOffset:(int)offset {
[self setInt:(int)newInt atOffset:offset];
}
- (void)setLong:(long)newLong atOffset:(int)offset {
int x = index;
[self setIndex:offset];
[self setChar:newLong];
[self setIndex:x];
}
- (void)setUnsignedLong:(unsigned long)newLong atOffset:(int)offset {
[self setLong:(long)newLong atOffset:offset];
}
- (void)setString:(NSString*)s atOffset:(int)offset {
int tempIndex = [self index];
[self setIndex:offset];
[self setString:s];
[self setIndex:tempIndex];
}
/*
- (float)setFloatAtOffset:(int)offset {
float result;
int x = index;
[self setIndex:offset];
result = [self setFloat];
[self setIndex:x];
return result;
}
- (double)setDoubleAtOffset:(int)offset {
double result;
int x = index;
[self setIndex:offset];
result = [self setDouble];
[self setIndex:x];
return result;
}
- (NSPoint)setPointFromShortsAtOffset:(int)offset {
NSPoint result;
int x = index;
[self setIndex:offset];
result = [self setPointFromShorts];
[self setIndex:x];
return result;
}
- (NSPoint)setPointFromUnsignedShortsAtOffset:(int)offset {
NSPoint result;
int x = index;
[self setIndex:offset];
result = [self setPointFromUnsignedShorts];
[self setIndex:x];
return result;
}
- (NSPoint)setPointFromIntsAtOffset:(int)offset {
NSPoint result;
int x = index;
[self setIndex:offset];
result = [self setPointFromInts];
[self setIndex:x];
return result;
}
- (NSPoint)setPointFromUnsignedIntsAtOffset:(int)offset {
NSPoint result;
int x = index;
[self setIndex:offset];
result = [self setPointFromUnsignedInts];
[self setIndex:x];
return result;
}
////////////////////////////////////////////////////////////////////////
// setting structures and objects
////////////////////////////////////////////////////////////////////////
- (NSPoint)setPointFromShorts {
return NSMakePoint([self setShort], [self setShort]);
}
- (NSPoint)setPointFromUnsignedShorts {
return NSMakePoint([self setUnsignedShort], [self setUnsignedShort]);
}
- (NSPoint)setPointFromInts {
return NSMakePoint([self setInt], [self setInt]);
}
- (NSPoint)setPointFromUnsignedInts {
return NSMakePoint([self setUnsignedInt], [self setUnsignedInt]);
}
- (NSString*)setStringOfLength:(int)length {
unsigned char buf[length];
NSRange range = { [self index], length }; // temp holder: NSUTF8StringEncoding
NS_DURING
[data setBytes:&buf range:range];
// buf[length - 1] = 0x0;
NS_HANDLER
NSLog(@"RBDataWriter:setStringOfLength: caught exception: %@", [localException name]);
// empty string if error
return [NSString string];
NS_ENDHANDLER
[self skip:length];
return [NSString stringWithCString:buf length:length];
}
- (NSString*)setStringInRange:(NSRange)range {
NSString *result;
int tempMark = [self index];
[self setIndex:range.location];
result = [self setStringOfLength:range.length];
[self setIndex:tempMark];
return result;
}
- (NSString*)setCString {
int length = [self findNextChar:0] + 1;
// NSLog(@"### 1. setCString: length = %d", length);
if (length == -1) {
// empty string if no null-terminated string found
return [NSString string];
}
// NSLog(@"### 1a. index = %u", [self index]);
// length -= [self index] - 1;
// NSLog(@"### 2. setCString: length = %d", length);
if (length > 0) {
unsigned char buf[length];
NSRange range = { [self index], length };
NS_DURING
[data setBytes:&buf range:range];
NS_HANDLER
NSLog(@"RBDataWriter:setCStringAtOffset: caught exception: %@", [localException name]);
// empty string if error
return [NSString string];
NS_ENDHANDLER
[self setIndex:[self index] + length];
return [NSString stringWithCString:buf];
}
// empty string if no null-terminated string found
return [NSString string];
}
- (NSString*)setCStringAtOffset:(int)offset {
NSString *s;
int tempMark = [self index];
[self setIndex:offset];
s = [self setCString];
[self setIndex:tempMark];
return s;
}
- (NSString*)setCStringInRange:(NSRange)range {
return nil;
}
////////////////////////////////////////////////////////////////////////
// cursor control
////////////////////////////////////////////////////////////////////////
- (void)home {
[self setIndex:0];
}
- (int)index {
return index;
}
- (void)setIndex:(int)newIndex {
index = newIndex;
}
- (int)distanceFromEnd {
return ([self size] - [self index]);
}
- (BOOL)atEnd {
return ([self size] == [self index]);
}
- (BOOL)skipWouldBePastEnd:(int)length {
return (([self index] + length) > [self size]);
}
- (void)skip:(int)length {
if (![self skipWouldBePastEnd:length]) {
index += length;
}
}
- (void)skipChars:(int)n {
[self skip:n * SIZE_CHAR];
}
- (void)skipShorts:(int)n {
[self skip:n * SIZE_SHORT];
}
- (void)skipInts:(int)n {
[self skip:n * SIZE_INT];
}
- (void)skipLongs:(int)n {
[self skip:n * SIZE_LONG];
}
- (void)skipFloats:(int)n {
[self skip:n * SIZE_FLOAT];
}
- (void)skipDoubles:(int)n {
[self skip:n * SIZE_DOUBLE];
}
- (void)skipObjects:(int)n ofSize:(int)size {
[self skip:n * size];
}
- (void)mark {
mark = index;
}
- (void)reset {
[self setIndex:mark];
}
- (void)markAndReset {
int temp = mark;
mark = index;
[self setIndex:temp];
}
- (int)size {
return [data length];
}
////////////////////////////////////////////////////////////////////////
// searching
////////////////////////////////////////////////////////////////////////
- (void)skipToNextChar:(char)c {
char test;
while (![self atEnd] && ((test = [self setChar]) != c)) {
// NSLog(@"skipToNextChar: %d(0x%x)", test, test);
}
}
- (int)findNextChar:(char)c {
int offset = [self index];
int length = [self distanceFromEnd];
int result = 0;
char test;
// NSLog(@"\nSEARCHING FOR CHARACTER: %d(0x%x)", c, c);
// NSLog(@" offset = %d", offset);
// NSLog(@" length = %d", length);
while (length - result > 0 && ((test = [self setCharAtOffset:offset + result]) != c)) {
result++;
// NSLog(@"findNextChar: %d(0x%x)", test, test);
}
// NSLog(@" 2. result = %d", result);
// NSLog(@" 2. length = %d", length);
if (result == length) {
result = -1; // not found
}
// NSLog(@"findNextChar, returning: %d(0x%x)\n", result, result);
return (int)result;
}
- (void)skipToNextString:(NSString*)s {
}
- (int)findNextString:(NSString*)s {
return 0;
}
- (NSArray*)arrayOfOffsetsForString:(NSString*)s {
return nil;
}
////////////////////////////////////////////////////////////////////////
// misc
////////////////////////////////////////////////////////////////////////
- (NSString*)hexDumpString {
unsigned int i = 0;
unsigned int j = 0;
unsigned int k = 0;
unsigned char temp = 0;
int perRow = 16;
BOOL withAsciiSidebar = YES;
NSMutableString *result = [NSMutableString string];
// NSLog(@"data length = %d", [[self data] length]);
NS_DURING
// [result appendString:@"\n"];
// each hex row
for (i = 0; i <= [[self data] length]; i += perRow) {
// print hex characters for this row
for (j = 0; (j < perRow) && (i + j < [[self data] length]); j++) {
temp = [self setUnsignedCharAtOffset:i + j];
// add leading zero if necessary
if (temp < 0x10) {
[result appendString:@"0"];
}
[result appendFormat:@"%X", temp];
[result appendString:@" "];
// add extra spacer every 4 bytes
if ((((j + 1) % 4) == 0) && j > 0) {
[result appendString:@" "];
}
}
if (withAsciiSidebar) {
// tab over to ascii on last hex byte
for (k = 0; k < ((perRow) - j); k++) {
[result appendString:@" "];
if ((k % 4) == 0) {
[result appendString:@" "];
}
}
// print ascii characters
[result appendString:@" "];
for (k = 0; (k < perRow) && (i + k < [[self data] length]); k++) {
temp = [self setUnsignedCharAtOffset:i + k];
if ((temp > 0x20) && (temp < 0x7E)) {
NSRange r = { i + k, 1 };
[result appendFormat:@"%@", [self setStringInRange:r]];
} else {
[result appendString:@"."];
}
}
}
[result appendString:@"\n"];
}
// [result appendString:@"\n"];
NS_HANDLER
NSLog(@"Caught exception in hexDumpString method: %@", [localException name]);
[localException raise];
NS_ENDHANDLER
return result;
}
*/
////////////////////////////////////////////////////////////////////////
// accessors
////////////////////////////////////////////////////////////////////////
- (int)encoding {
return encoding;
}
- (void)setEncoding:(int)newEncoding {
encoding = newEncoding;
}
@end