Off-The-Shelf C++ Hex Dump Code

Off-the-Shelf C++ Hex Dump Code

The unix tool xxd is distributed as part of vim, and according to http://www.vmunix.com/vim/util.html#xxd, the source for xxd is ftp://ftp.uni-erlangen.de:21/pub/utilities/etc/xxd-1.10.tar.gz. It was written in C and is about 721 lines. The only licensing information given for it is this:

* Distribute freely and credit me,
* make money and share with me,
* lose money and don't ask me.

The unix tool hexdump is available from http://gd.tuwien.ac.at/softeng/Aegis/hexdump.html. It was written in C and can be compiled from source. It's quite a bit bigger than xxd, and is distributed under the GPL.

how to get hexdump of a structure data

The following code will give you a hex dump of arbitrary memory from within your code.

#include <stdio.h>

// Usage:
// hexDump(desc, addr, len, perLine);
// desc: if non-NULL, printed as a description before hex dump.
// addr: the address to start dumping from.
// len: the number of bytes to dump.
// perLine: number of bytes on each output line.

void hexDump (
const char * desc,
const void * addr,
const int len,
int perLine
) {
// Silently ignore silly per-line values.

if (perLine < 4 || perLine > 64) perLine = 16;

int i;
unsigned char buff[perLine+1];
const unsigned char * pc = (const unsigned char *)addr;

// Output description if given.

if (desc != NULL) printf ("%s:\n", desc);

// Length checks.

if (len == 0) {
printf(" ZERO LENGTH\n");
return;
}
if (len < 0) {
printf(" NEGATIVE LENGTH: %d\n", len);
return;
}

// Process every byte in the data.

for (i = 0; i < len; i++) {
// Multiple of perLine means new or first line (with line offset).

if ((i % perLine) == 0) {
// Only print previous-line ASCII buffer for lines beyond first.

if (i != 0) printf (" %s\n", buff);

// Output the offset of current line.

printf (" %04x ", i);
}

// Now the hex code for the specific character.

printf (" %02x", pc[i]);

// And buffer a printable ASCII character for later.

if ((pc[i] < 0x20) || (pc[i] > 0x7e)) // isprint() may be better.
buff[i % perLine] = '.';
else
buff[i % perLine] = pc[i];
buff[(i % perLine) + 1] = '\0';
}

// Pad out last line if not exactly perLine characters.

while ((i % perLine) != 0) {
printf (" ");
i++;
}

// And print the final ASCII buffer.

printf (" %s\n", buff);
}

// Very simple test harness.

int main (int argc, char *argv[]) {
char my_str[] = "a char string greater than 16 chars";
hexDump ("my_str", &my_str, sizeof (my_str), 16);
return 0;
}

You pass into hexDump a description, memory address, length, and how many bytes you want on each line.

It will output a hex dump (including character data) for examination. When you run it with the included main, the output is:

my_str:
0000 61 20 63 68 61 72 20 73 74 72 69 6e 67 20 67 72 a char string gr
0010 65 61 74 65 72 20 74 68 61 6e 20 31 36 20 63 68 eater than 16 ch
0020 61 72 73 00 ars.

Problem reading hexadecimal buffer from C socket

My suggestion would be to first check what's going on on the wire with a sniffer like tcpdump or wireshark. Check that the bytes sent conform to any SMPP PDU. If that is OK, then dump the buffer read with SDLNet_TCP_Recv() using the hexdump(3) and see if it matches.

Some notes on the code:

  • I don't see ip initialized anywhere, but I'm guessing you just skipped that part when pasting the code.
  • int bufSize = 1024; char message[bufSize]; is only valid in C99. Assuming GCC, always compile with at least -Wall -pedantic to catch all warnings.
  • The buffer is on the stack, so if you pass it to any function up the call chain, the result is Undefined Behavior.

I would also try reproducing this with plain Berkeley sockets, which are not that much more difficult then SDL, but much more fun :)

Why are offsets in hex dump 10 more than previous?

00, 10, and 20 are byte offsets in hex. So an offset of "10" is an offset of 16 bytes.

xxd examples

You can specify the byte count per line with xxd's -c flag. Using 16 mimics default behavior:

$ printf "The quick brown fox jumps over the lazy dog" | xxd -c 16
00000000: 5468 6520 7175 6963 6b20 6272 6f77 6e20 The quick brown
00000010: 666f 7820 6a75 6d70 7320 6f76 6572 2074 fox jumps over t
00000020: 6865 206c 617a 7920 646f 67 he lazy dog

Example with 12

Using an offset of 12 instead results in increments of 12 bytes (in hex).

$ printf "The quick brown fox jumps over the lazy dog" | xxd -c 12
00000000: 5468 6520 7175 6963 6b20 6272 The quick br
0000000c: 6f77 6e20 666f 7820 6a75 6d70 own fox jump
00000018: 7320 6f76 6572 2074 6865 206c s over the l
00000024: 617a 7920 646f 67 azy dog

Converting the offsets, we get the expected result:

0x0c = 12
0x18 = 24
0x24 = 36

Print Hexadecimal Numbers Of a File At C And C++

To print hex:

std::cout << std::hex << 123 << std::endl;

but yes, use the od tool :-)
A good file reading/writing tutorial is here. You will have to read the file into a buffer then loop over each byte/word of the file.

Converting .raw file into Hex

The problem is you pass the name of the file to hexdump() which treats it like data. The following corrects that and applies other relatively minor fixes to your code (and seems to work in my limited testing):

try:
xrange
except NameError: # Python3
xrange = range

def hexdump(filename, length=16, sep='.'):
result = []

with open(filename, 'rb') as file:
src = file.read() # Read whole file into memory

for i in xrange(0, len(src), length):
subSrc = src[i:i+length]
hexa = ''
isMiddle = False;
for h in xrange(0,len(subSrc)):
if h == length/2:
hexa += ' '
h = subSrc[h]
if not isinstance(h, int):
h = ord(h)
h = hex(h).replace('0x','')
if len(h) == 1:
h = '0'+h;
hexa += h+' '
hexa = hexa.strip(' ')
text = ''
for c in subSrc:
if not isinstance(c, int):
c = ord(c)
if 0x20 <= c < 0x7F:
text += chr(c)
else:
text += sep;
result.append(('%08X: %-'+str(length*(2+1)+1)+'s |%s|') %
(i, hexa, text))

return '\n'.join(result)

if __name__ == "__main__":
import sys

filename = sys.argv[1]
print(hexdump(filename, length=16, sep='.'))


Related Topics



Leave a reply



Submit