Hexy Little Thing

I’m working on an application now that uses a custom document format. Since my code manipulates this format and spits it back out to disk, I find myself frequently examining the resulting documents using Peter Ammon’s excellent Hex Fiend to examine the resulting files, and make sure the content is still format-compliant.

But while I’m debugging the code that actually does the manipulation, I find myself stuck doing stupid stuff like:

(gdb) p/x ((char*)[imageData bytes])[14]
$1 = 0x28

Ugh! That’s no way to win the software wars. It occurred to me today that what I really want is something like Hex Fiend built right into the debugger. Why shouldn’t I be able to hex-dump my NSData objects directly from the console? It turns out I wasn’t alone in this wish, because Dan Wood recently published a category on NSData that allows just that.

By simply compiling the NSData category into a given application, you give NSData’s debugging description superpowers. For instance, here’s me at the gdb console, examining the contents of the favicon.ico response I just received from NSURLConnection:

(gdb) po imageData
NSData 350 bytes:
00 00 01 00 01 00 10 10 10 00 00 00 00 00 28 01 | ..............(.
00 00 16 00 00 00 28 00 00 00 10 00 00 00 20 00 | ......(....... .
00 00 01 00 04 00 00 00 00 00 C0 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF | ................
FF 00 00 00 FF 00 00 00 EF 00 00 00 DE 00 00 00 | ................
CE 00 00 00 BD 00 00 00 AD 00 00 00 9C 00 00 00 | ................
8C 00 00 00 7B 00 00 00 52 00 00 00 42 00 00 00 | ....{...R...B...
29 00 00 00 10 00 00 00 00 00 00 00 00 00 11 11 | )...............
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 | ................
11 11 11 11 11 11 13 31 11 11 12 55 21 11 1B B1 | .......1...U!...
13 D8 7F FF FB 31 1B B1 6F D4 FB 65 9F D2 1B DB | ....1..o..e....
FB 21 84 11 15 F5 1B FF FC 41 12 78 8D D1 1B B1 | .!.......A.x....
3C C1 2D FF FB 51 1B B1 1A D1 5F 71 11 11 1B C5 | < .-..Q...._q....
BF 81 1C C7 58 61 1A FF C6 11 12 BF FF 81 12 54 | ....Xa.........T
11 11 11 13 52 11 11 11 11 11 11 11 11 11 11 11 | ....R...........
11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............
Current language: auto; currently objective-c
(gdb)

Dan’s code is pretty much perfect as-is, but I couldn’t resist tacking on some additional features. His category hardcodes the dumped data to 1024 bytes, but in my case there are times when I’m interested in seeing more. I added two category methods to the mix:

// startOffset may be negative, indicating offset from end of data
- (NSString *)descriptionFromOffset:(int)startOffset;
- (NSString *)descriptionFromOffset:(int)startOffset
limitingToByteCount:(unsigned int)maxBytes;

Now I can peek at a specific subrange, or expand the default limit of 1024 bytes. I can even peek at the end of a chunk of data, by specifying a negative offset:

(gdb) po [mDocumentData descriptionFromOffset:-11]
NSData 109 bytes (showing bytes 98 through 109):
02 43 41 54 41 54 4F 4E 49 43 00 | .CATATONIC.
(gdb)

Wow! This is a pretty huge addition to my debugging and development toolbelt. Many thanks to Dan Wood for providing the ready-made code to speed up my implementation.

NSData+RSHexDump is freely available to you, under an MIT license.