OLD | NEW |
(Empty) | |
| 1 // -*- mode: ObjC -*- |
| 2 |
| 3 // This file is part of class-dump, a utility for examining the Objective-C seg
ment of Mach-O files. |
| 4 // Copyright (C) 1997-1998, 2000-2001, 2004-2010 Steve Nygard. |
| 5 |
| 6 #import "CDDataCursor.h" |
| 7 |
| 8 @implementation CDDataCursor |
| 9 |
| 10 - (id)initWithData:(NSData *)someData; |
| 11 { |
| 12 if ([super init] == nil) |
| 13 return nil; |
| 14 |
| 15 data = [someData retain]; |
| 16 offset = 0; |
| 17 byteOrder = CDByteOrderLittleEndian; |
| 18 |
| 19 return self; |
| 20 } |
| 21 |
| 22 - (void)dealloc; |
| 23 { |
| 24 [data release]; |
| 25 |
| 26 [super dealloc]; |
| 27 } |
| 28 |
| 29 - (NSData *)data; |
| 30 { |
| 31 return data; |
| 32 } |
| 33 |
| 34 - (const void *)bytes; |
| 35 { |
| 36 return [data bytes]; |
| 37 } |
| 38 |
| 39 - (NSUInteger)offset; |
| 40 { |
| 41 return offset; |
| 42 } |
| 43 |
| 44 // Return NO on failure. |
| 45 - (void)setOffset:(NSUInteger)newOffset; |
| 46 { |
| 47 if (newOffset <= [data length]) { |
| 48 offset = newOffset; |
| 49 } else { |
| 50 [NSException raise:NSRangeException format:@"Trying to seek past end of
data."]; |
| 51 } |
| 52 } |
| 53 |
| 54 - (void)advanceByLength:(NSUInteger)length; |
| 55 { |
| 56 [self setOffset:offset + length]; |
| 57 } |
| 58 |
| 59 - (NSUInteger)remaining; |
| 60 { |
| 61 return [data length] - offset; |
| 62 } |
| 63 |
| 64 - (uint8_t)readByte; |
| 65 { |
| 66 const uint8_t *ptr; |
| 67 |
| 68 ptr = [data bytes] + offset; |
| 69 offset += 1; |
| 70 |
| 71 return *ptr; |
| 72 } |
| 73 |
| 74 - (uint16_t)readLittleInt16; |
| 75 { |
| 76 uint16_t result; |
| 77 |
| 78 if (offset + sizeof(result) <= [data length]) { |
| 79 result = OSReadLittleInt16([data bytes], offset); |
| 80 offset += sizeof(result); |
| 81 } else { |
| 82 [NSException raise:NSRangeException format:@"Trying to read past end in
%s", _cmd]; |
| 83 result = 0; |
| 84 } |
| 85 |
| 86 return result; |
| 87 } |
| 88 |
| 89 - (uint32_t)readLittleInt32; |
| 90 { |
| 91 uint32_t result; |
| 92 |
| 93 if (offset + sizeof(result) <= [data length]) { |
| 94 result = OSReadLittleInt32([data bytes], offset); |
| 95 offset += sizeof(result); |
| 96 } else { |
| 97 [NSException raise:NSRangeException format:@"Trying to read past end in
%s", _cmd]; |
| 98 result = 0; |
| 99 } |
| 100 |
| 101 return result; |
| 102 } |
| 103 |
| 104 - (uint64_t)readLittleInt64; |
| 105 { |
| 106 uint64_t result; |
| 107 |
| 108 if (offset + sizeof(result) <= [data length]) { |
| 109 result = OSReadLittleInt64([data bytes], offset); |
| 110 offset += sizeof(result); |
| 111 } else { |
| 112 [NSException raise:NSRangeException format:@"Trying to read past end in
%s", _cmd]; |
| 113 result = 0; |
| 114 } |
| 115 |
| 116 return result; |
| 117 } |
| 118 |
| 119 - (uint16_t)readBigInt16; |
| 120 { |
| 121 uint16_t result; |
| 122 |
| 123 if (offset + sizeof(result) <= [data length]) { |
| 124 result = OSReadBigInt16([data bytes], offset); |
| 125 offset += sizeof(result); |
| 126 } else { |
| 127 [NSException raise:NSRangeException format:@"Trying to read past end in
%s", _cmd]; |
| 128 result = 0; |
| 129 } |
| 130 |
| 131 return result; |
| 132 } |
| 133 |
| 134 - (uint32_t)readBigInt32; |
| 135 { |
| 136 uint32_t result; |
| 137 |
| 138 if (offset + sizeof(result) <= [data length]) { |
| 139 result = OSReadBigInt32([data bytes], offset); |
| 140 offset += sizeof(result); |
| 141 } else { |
| 142 [NSException raise:NSRangeException format:@"Trying to read past end in
%s", _cmd]; |
| 143 result = 0; |
| 144 } |
| 145 |
| 146 return result; |
| 147 } |
| 148 |
| 149 - (uint64_t)readBigInt64; |
| 150 { |
| 151 uint64_t result; |
| 152 |
| 153 if (offset + sizeof(result) <= [data length]) { |
| 154 result = OSReadBigInt64([data bytes], offset); |
| 155 offset += sizeof(result); |
| 156 } else { |
| 157 [NSException raise:NSRangeException format:@"Trying to read past end in
%s", _cmd]; |
| 158 result = 0; |
| 159 } |
| 160 |
| 161 return result; |
| 162 } |
| 163 |
| 164 - (float)readLittleFloat32; |
| 165 { |
| 166 uint32_t val; |
| 167 |
| 168 val = [self readLittleInt32]; |
| 169 return *(float *)&val; |
| 170 } |
| 171 |
| 172 - (float)readBigFloat32; |
| 173 { |
| 174 uint32_t val; |
| 175 |
| 176 val = [self readBigInt32]; |
| 177 return *(float *)&val; |
| 178 } |
| 179 |
| 180 - (double)readLittleFloat64; |
| 181 { |
| 182 uint32_t v1, v2, *ptr; |
| 183 double dval; |
| 184 |
| 185 v1 = [self readLittleInt32]; |
| 186 v2 = [self readLittleInt32]; |
| 187 ptr = (uint32_t *)&dval; |
| 188 *ptr++ = v1; |
| 189 *ptr = v2; |
| 190 |
| 191 return dval; |
| 192 } |
| 193 |
| 194 - (void)appendBytesOfLength:(NSUInteger)length intoData:(NSMutableData *)targetD
ata; |
| 195 { |
| 196 if (offset + length <= [data length]) { |
| 197 [targetData appendBytes:[data bytes] + offset length:length]; |
| 198 offset += length; |
| 199 } else { |
| 200 [NSException raise:NSRangeException format:@"Trying to read past end in
%s", _cmd]; |
| 201 } |
| 202 } |
| 203 |
| 204 - (void)readBytesOfLength:(NSUInteger)length intoBuffer:(void *)buf; |
| 205 { |
| 206 if (offset + length <= [data length]) { |
| 207 memcpy(buf, [data bytes] + offset, length); |
| 208 offset += length; |
| 209 } else { |
| 210 [NSException raise:NSRangeException format:@"Trying to read past end in
%s", _cmd]; |
| 211 } |
| 212 } |
| 213 |
| 214 - (BOOL)isAtEnd; |
| 215 { |
| 216 return offset >= [data length]; |
| 217 } |
| 218 |
| 219 - (CDByteOrder)byteOrder; |
| 220 { |
| 221 return byteOrder; |
| 222 } |
| 223 |
| 224 - (void)setByteOrder:(CDByteOrder)newByteOrder; |
| 225 { |
| 226 byteOrder = newByteOrder; |
| 227 } |
| 228 |
| 229 // |
| 230 // Read using the current byteOrder |
| 231 // |
| 232 |
| 233 - (uint16_t)readInt16; |
| 234 { |
| 235 if (byteOrder == CDByteOrderLittleEndian) |
| 236 return [self readLittleInt16]; |
| 237 |
| 238 return [self readBigInt16]; |
| 239 } |
| 240 |
| 241 - (uint32_t)readInt32; |
| 242 { |
| 243 if (byteOrder == CDByteOrderLittleEndian) |
| 244 return [self readLittleInt32]; |
| 245 |
| 246 return [self readBigInt32]; |
| 247 } |
| 248 |
| 249 - (uint64_t)readInt64; |
| 250 { |
| 251 if (byteOrder == CDByteOrderLittleEndian) |
| 252 return [self readLittleInt64]; |
| 253 |
| 254 return [self readBigInt64]; |
| 255 } |
| 256 |
| 257 - (uint32_t)peekInt32; |
| 258 { |
| 259 NSUInteger savedOffset; |
| 260 uint32_t val; |
| 261 |
| 262 savedOffset = offset; |
| 263 val = [self readInt32]; |
| 264 offset = savedOffset; |
| 265 |
| 266 return val; |
| 267 } |
| 268 |
| 269 - (NSString *)readCString; |
| 270 { |
| 271 return [self readStringOfLength:strlen([data bytes] + offset) encoding:NSASC
IIStringEncoding]; |
| 272 } |
| 273 |
| 274 - (NSString *)readStringOfLength:(NSUInteger)length encoding:(NSStringEncoding)e
ncoding; |
| 275 { |
| 276 if (offset + length <= [data length]) { |
| 277 NSString *str; |
| 278 |
| 279 if (encoding == NSASCIIStringEncoding) { |
| 280 char *buf; |
| 281 |
| 282 // Jump through some hoops if the length is padded with zero bytes,
as in the case of 10.5's Property List Editor and iSync Plug-in Maker. |
| 283 buf = malloc(length + 1); |
| 284 if (buf == NULL) { |
| 285 NSLog(@"Error: malloc() failed."); |
| 286 return nil; |
| 287 } |
| 288 |
| 289 strncpy(buf, [data bytes] + offset, length); |
| 290 buf[length] = 0; |
| 291 |
| 292 str = [[[NSString alloc] initWithBytes:buf length:strlen(buf) encodi
ng:encoding] autorelease]; |
| 293 offset += length; |
| 294 free(buf); |
| 295 return str; |
| 296 } else { |
| 297 str = [[[NSString alloc] initWithBytes:[data bytes] + offset length:
length encoding:encoding] autorelease];; |
| 298 offset += length; |
| 299 return str; |
| 300 } |
| 301 } else { |
| 302 [NSException raise:NSRangeException format:@"Trying to read past end in
%s", _cmd]; |
| 303 } |
| 304 |
| 305 return nil; |
| 306 } |
| 307 |
| 308 @end |
OLD | NEW |