Printing a hex dump of a buffer

  • Follow


Hello,

I'm trying to print out a const char* buffer
by first printing 16 bytes as hex codes,
then printing them again as characters
or dots (if they aren't printable) and so on:

20 A5 96 74 00 00 00 00 05 AD 4A 7C D3 FF 70 00   ..t......J|..p.
31 B0 66 7F 9F 3D AC 00 9D FF C2 02 AB 10 28 76  1.f..=........(v
49 9A 5E 7C F7 3D E4 00 35 F9 3A 02 83 00 E0 76  I.^|.=..5.:....v

Right now it's too late here in Germany
and I have come up with this fugliness only:

void
dump_buffer(unsigned n, const unsigned char* buf)
{
        const unsigned char     *p, *end;
        unsigned                i, j;

        end = buf + n;

        for (i = 0; ; i += 16) {
                p = buf + i;
                for (j = 0; j < 16; j++) {
                        fprintf(stderr, "%02X ", p[j]);
                        if (p + j >= end)
                                goto BREAKOUT;
                }
                fprintf(stderr, " ");
                p = buf + i;
                for (j = 0; j < 16; j++) {
                        fprintf(stderr, "%c", isprint(p[j]) ? p[j] :
'.');
                        if (p + j >= end)
                                goto BREAKOUT;
                }
                fprintf(stderr, "\n");
        }
BREAKOUT:
        return;
}

I know that it's horrible. Maybe I'll do better tomorrow.

Does maybe any kind soul has a nice solution
for this probably often encountered problem?

I've looked at the Vim's xxd source code, but
it is too much for me to understand right now...

Thank you
Alex
0
Reply alexander.farber (98) 1/24/2008 10:10:39 PM

"A. Farber" <Alexander.Farber@gmail.com> wrote in message 
news:b1703211-25ca-4f9c-bf82-1e44ed79a998@v17g2000hsa.googlegroups.com...
> Hello,
>
> I'm trying to print out a const char* buffer
> by first printing 16 bytes as hex codes,
> then printing them again as characters
> or dots (if they aren't printable) and so on:
>
> 20 A5 96 74 00 00 00 00 05 AD 4A 7C D3 FF 70 00   ..t......J|..p.
> 31 B0 66 7F 9F 3D AC 00 9D FF C2 02 AB 10 28 76  1.f..=........(v
> 49 9A 5E 7C F7 3D E4 00 35 F9 3A 02 83 00 E0 76  I.^|.=..5.:....v
>
> Right now it's too late here in Germany
> and I have come up with this fugliness only:
>
> void
> dump_buffer(unsigned n, const unsigned char* buf)
> {
>        const unsigned char     *p, *end;
>        unsigned                i, j;
>
>        end = buf + n;
>
>        for (i = 0; ; i += 16) {
>                p = buf + i;
>                for (j = 0; j < 16; j++) {
>                        fprintf(stderr, "%02X ", p[j]);
>                        if (p + j >= end)
>                                goto BREAKOUT;
>                }
>                fprintf(stderr, " ");
>                p = buf + i;
>                for (j = 0; j < 16; j++) {
>                        fprintf(stderr, "%c", isprint(p[j]) ? p[j] :
> '.');
>                        if (p + j >= end)
>                                goto BREAKOUT;
>                }
>                fprintf(stderr, "\n");
>        }
> BREAKOUT:
>        return;
> }
>
> I know that it's horrible. Maybe I'll do better tomorrow.
>
> Does maybe any kind soul has a nice solution
> for this probably often encountered problem?
>
> I've looked at the Vim's xxd source code, but
> it is too much for me to understand right now...
>
> Thank you
> Alex

Untested but

void dumpbuff(char *buff,  int N)
{
  int i;

  for(i=0;i<N;i+=16
   if(i + 16 <= N)
     printline(data+i, 16);
   else
     printline(data+1, N - i);
}

void printline(char *data, int N)
{
   int i;

   for(i=0;i<N;i++)
      printf("%02x ", data[i]):
   printf("   ");
   for(i=0;i<N;i++)
      if(isgraph((unsigned) data[i]))
       printf("%c", data[i]);
      else
         printf(".");
    printf("\n");
}

As long as you break things up the right way the function can look nice and 
clean.

-- 
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

0
Reply regniztar (3128) 1/24/2008 10:26:52 PM


"A. Farber" <Alexander.Farber@gmail.com> writes:

> I'm trying to print out a const char* buffer
> by first printing 16 bytes as hex codes,
> then printing them again as characters
> or dots (if they aren't printable) and so on:
>
> 20 A5 96 74 00 00 00 00 05 AD 4A 7C D3 FF 70 00   ..t......J|..p.
> 31 B0 66 7F 9F 3D AC 00 9D FF C2 02 AB 10 28 76  1.f..=........(v
> 49 9A 5E 7C F7 3D E4 00 35 F9 3A 02 83 00 E0 76  I.^|.=..5.:....v
<snip>
> Does maybe any kind soul has a nice solution
> for this probably often encountered problem?

I'd do this:

void dump_buffer(unsigned n, const unsigned char* buf)
{
     int on_this_line = 0;
     while (n-- > 0) {
	  fprintf(stderr, "%02X ", *buf++);
	  on_this_line += 1;
	  if (on_this_line == 16 || n == 0) {
	       int i;
	       fputs(" ", stderr);
	       for (i = on_this_line; i < 16; i++)
		    fputs("   ", stderr);
	       for (i = on_this_line; i > 0; i--)
		    fputc(isprint(buf[-i]) ? buf[-i] : '.', stderr);
	       fputs("\n", stderr);
	       on_this_line = 0;
	  }
     }
}

-- 
Ben.
0
Reply ben.usenet (6515) 1/25/2008 12:23:36 AM

"A. Farber" <Alexander.Far...@gmail.com> wrote:
> Hello,
>
> I'm trying to print out a const char* buffer
> by first printing 16 bytes as hex codes,
> then printing them again as characters
> or dots (if they aren't printable) and so on:
>
> 20 A5 96 74 00 00 00 00 05 AD 4A 7C D3 FF 70 00 =A0 ..t......J|..p.
> 31 B0 66 7F 9F 3D AC 00 9D FF C2 02 AB 10 28 76 =A01.f..=3D........(v
> 49 9A 5E 7C F7 3D E4 00 35 F9 3A 02 83 00 E0 76 =A0I.^|.=3D..5.:....v
>
> Right now it's too late here in Germany
> and I have come up with this fugliness only:
>
> void
> dump_buffer(unsigned n, const unsigned char* buf)

Consider... [untested]

  #include <stdio.h>
  #include <limits.h>

  #define BYTES_PER_LINE 16
  #define DOT  '.'

  #define NIBBLES_PER_BYTE ((CHAR_BIT + 3) / 4)

  void dump_buffer(FILE *fp, const void *vp, size_t n)
  {
    const unsigned char *b =3D vp;

    while (n)
    {
      const unsigned char *p =3D b;
      size_t i, w =3D n < BYTES_PER_LINE ? n : BYTES_PER_LINE;

      for (i =3D 0; i < w; i++)
      {
        if (i !=3D 0) putc(' ', fp);
        printf("%0*X", NIBBLES_PER_BYTE, (unsigned) p[i]);
      }

      for (; i < BYTES_PER_LINE; i++)
      {
        printf("%*c", NIBBLES_PER_BYTE + 1, ' ');
      }

      fputs("  ", fp);

      for (i =3D 0; i < w; i++)
      {
        if (    p[i] =3D=3D ' '
             || (isprint(p[i]) && !isspace(p[i])) )
          putc(p[i], fp);
        else
          putc(DOT, fp);
      }

      putc('\n', fp);
      n -=3D w;
      b +=3D BYTES_PER_LINE;
    }
  }

<snip>
> fprintf(stderr, "%02X ", p[j]);

You're assuming 8 bit bytes (if you want good formatting).

<snip>
> fprintf(stderr, "%c", isprint(p[j]) ? p[j] : '.');

Note that isprint() for \n, \t, \b, \r, etc... are likely
to be true.

--
Peter
0
Reply airia (1802) 1/25/2008 1:55:40 AM

Thank you all!
0
Reply alexander.farber (98) 1/25/2008 7:34:10 AM

Peter Nilsson <airia@acay.com.au> writes:

> "A. Farber" <Alexander.Far...@gmail.com> wrote:
> <snip>
>> fprintf(stderr, "%c", isprint(p[j]) ? p[j] : '.');
>
> Note that isprint() for \n, \t, \b, \r, etc... are likely
> to be true.

That is at odds with my reading of the standard (specifically
paragraph 3 of 7.4).  Am I misunderstanding what you mean?

-- 
Ben.
0
Reply ben.usenet (6515) 1/25/2008 12:01:43 PM

Ben Bacarisse wrote:

> Peter Nilsson <airia@acay.com.au> writes:
> 
>> "A. Farber" <Alexander.Far...@gmail.com> wrote:
>> <snip>
>>> fprintf(stderr, "%c", isprint(p[j]) ? p[j] : '.');
>>
>> Note that isprint() for \n, \t, \b, \r, etc... are likely
>> to be true.
> 
> That is at odds with my reading of the standard (specifically
> paragraph 3 of 7.4).  Am I misunderstanding what you mean?

Certainly '\b', '\r' and possibly '\n' should be classified as control
characters as their function is to change the active position of the
device connected to the stream. There is nothing to be printed.

0
Reply santosh.k83 (3969) 1/25/2008 12:10:35 PM

Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> Peter Nilsson <ai...@acay.com.au> writes:
> > "A. Farber" <Alexander.Far...@gmail.com> wrote:
> > > fprintf(stderr, "%c", isprint(p[j]) ? p[j] : '.');
>
> > Note that isprint() for \n, \t, \b, \r, etc... are likely
> > to be true.
>
> That is at odds with my reading of the standard (specifically
> paragraph 3 of 7.4). =A0Am I misunderstanding what you mean?

No, I was wrong. Thanks for the correction.

--
Peter
0
Reply airia (1802) 1/26/2008 12:40:55 AM

7 Replies
33 Views

(page loaded in 0.454 seconds)

Similiar Articles:













7/27/2012 3:45:44 PM


Reply: