hexdump.c
#define EX_UTILS_NO_FUNCS 1
#include "ex_utils.h"
#include "hexdump.h"
#define CHRS_PER_LINE 16
#ifndef CONF_USE_FAST_NUM_PRINT
#define CONF_USE_FAST_NUM_PRINT 1
#endif
#define APOS() (apos + ((s1)->len - orig_len))
#if !CONF_USE_FAST_NUM_PRINT
# define EX_HEXDUMP_X8(s1, num) \
vstr_add_fmt(s1, APOS(), "0x%08X:", (num))
# define EX_HEXDUMP_X2X2(s1, num1, num2) \
vstr_add_fmt(s1, APOS(), " %02X%02X", (num1), (num2))
# define EX_HEXDUMP_X2__(s1, num1) \
vstr_add_fmt(s1, APOS(), " %02X ", (num1))
#else
static const char *hexnums = "0123456789ABCDEF";
# define EX_HEXDUMP_BYTE(buf, b) do { \
(buf)[1] = hexnums[((b) >> 0) & 0xf]; \
(buf)[0] = hexnums[((b) >> 4) & 0xf]; \
} while (FALSE)
# define EX_HEXDUMP_UINT(buf, i) do { \
EX_HEXDUMP_BYTE((buf) + 6, (i) >> 0); \
EX_HEXDUMP_BYTE((buf) + 4, (i) >> 8); \
EX_HEXDUMP_BYTE((buf) + 2, (i) >> 16); \
EX_HEXDUMP_BYTE((buf) + 0, (i) >> 24); \
} while (FALSE)
# define EX_HEXDUMP_X8(s1, num) do { \
unsigned char xbuf[9]; \
\
xbuf[8] = ':'; \
EX_HEXDUMP_UINT(xbuf, num); \
vstr_add_buf(s1, APOS(), xbuf, sizeof(xbuf)); \
} while (FALSE)
# define EX_HEXDUMP_X2X2(s1, num1, num2) do { \
unsigned char xbuf[5]; \
\
xbuf[0] = ' '; \
EX_HEXDUMP_BYTE(xbuf + 3, num2); \
EX_HEXDUMP_BYTE(xbuf + 1, num1); \
vstr_add_buf(s1, APOS(), xbuf, sizeof(xbuf)); \
} while (FALSE)
# define EX_HEXDUMP_X2__(s1, num1) do { \
unsigned char xbuf[5]; \
\
xbuf[4] = ' '; \
xbuf[3] = ' '; \
EX_HEXDUMP_BYTE(xbuf + 1, num1); \
xbuf[0] = ' '; \
vstr_add_buf(s1, APOS(), xbuf, sizeof(xbuf)); \
} while (FALSE)
#endif
static unsigned int addr = 0;
void ex_hexdump_reset(void)
{
addr = 0;
}
int ex_hexdump_process(Vstr_base *s1, size_t apos,
Vstr_base *s2, size_t fpos, size_t flen,
unsigned int prnt_type, size_t max_sz, int del, int last)
{
size_t orig_len = s1->len;
unsigned int flags = VSTR_FLAG02(CONV_UNPRINTABLE_ALLOW, COMMA, DOT);
unsigned int flags_sp = VSTR_FLAG04(CONV_UNPRINTABLE_ALLOW,
COMMA, DOT, _, SP);
unsigned int flags_hsp = VSTR_FLAG06(CONV_UNPRINTABLE_ALLOW,
COMMA, DOT, _, SP, HSP, HIGH);
unsigned char buf[CHRS_PER_LINE];
switch (prnt_type)
{
case PRNT_HIGH: flags = flags_hsp; break;
case PRNT_SPAC: flags = flags_sp; break;
case PRNT_NONE: break;
default: ASSERT(FALSE); break;
}
if (s1->len > max_sz)
return (FALSE);
while (flen >= CHRS_PER_LINE)
{
unsigned int count = 0;
size_t tmp = 0;
vstr_export_buf(s2, fpos, CHRS_PER_LINE, buf, sizeof(buf));
EX_HEXDUMP_X8(s1, addr);
while (count < CHRS_PER_LINE)
{
EX_HEXDUMP_X2X2(s1, buf[count], buf[count + 1]);
count += 2;
}
vstr_add_rep_chr(s1, APOS(), ' ', 2);
tmp = APOS();
if (vstr_add_vstr(s1, tmp, s2, fpos, CHRS_PER_LINE,
VSTR_TYPE_ADD_ALL_BUF))
vstr_conv_unprintable_chr(s1, tmp + 1, CHRS_PER_LINE, flags, '.');
vstr_add_rep_chr(s1, APOS(), '\n', 1);
addr += CHRS_PER_LINE;
flen -= CHRS_PER_LINE;
if (del)
vstr_del(s2, fpos, CHRS_PER_LINE);
else
fpos += CHRS_PER_LINE;
if (s1->len > max_sz)
return (TRUE);
}
if (last && flen)
{
size_t got = flen;
size_t missing = CHRS_PER_LINE - flen;
const unsigned char *ptr = buf;
size_t tmp = 0;
missing -= (missing % 2);
vstr_export_buf(s2, fpos, flen, buf, sizeof(buf));
EX_HEXDUMP_X8(s1, addr);
while (got >= 2)
{
EX_HEXDUMP_X2X2(s1, ptr[0], ptr[1]);
got -= 2;
ptr += 2;
}
if (got)
{
EX_HEXDUMP_X2__(s1, ptr[0]);
got -= 2;
}
vstr_add_rep_chr(s1, APOS(), ' ', (missing * 2) + (missing / 2) + 2);
tmp = APOS();
if (vstr_add_vstr(s1, tmp, s2, fpos, flen, VSTR_TYPE_ADD_ALL_BUF))
vstr_conv_unprintable_chr(s1, tmp + 1, flen, flags, '.');
vstr_add_cstr_buf(s1, APOS(), "\n");
addr += flen;
if (del)
vstr_del(s2, fpos, flen);
return (TRUE);
}
return (FALSE);
}