NAME

Data::HexDump::Range - Hexadecial Range Dumper

SYNOPSIS

my $hdr = Data::HexDump::Range->new() ;

print $hdr->dump(['magic cookie', 12, 'red'], $data) ;

$hdr->gather(['magic cookie', 12, 'red'], $data) ; 
$hdr->gather(['image type', 2, 'green'], $other_data) ;
$hdr->gather(['image data ...', 100, 'yellow'], $more_data, 0, CONSUME_ALL_DATA) ;

print $hdr->dump_gathered() ;

$hdr->reset() ;

DESCRIPTION

Creates a dump from binary data and user defined range descriptions. The goal of this modules is to create an easy to understand dump of binary data. This achieved through:

  • Highlighted (colors) dump that is easier to understand than a monochrome blob of hex data

  • Multiple rendering modes with different output formats

  • The possibility to describe complex structures

DOCUMENTATION

The shortest perl dumper is perl -ne 'BEGIN{$/=\16} printf "%07x0: @{[unpack q{(H2)*}]}\n", $.-1', courtesy of a golfing session with Andrew Rodland <arodland@cpan.org> aka hobbs on #perl.

hexd from libma http://www.ioplex.com/~miallen/libmba/ is nice tools that inspired me to write this module. It may be a better alternative If you need very fast dump generation.

priodev, tm604, Khisanth and other helped with the html output.

Data::HexDump::Range splits binary data according to user defined ranges and rendered as a hex or/and decimal data dump. The data dump can be rendered in ANSI, ASCII or HTML.

Orientation

Vertical

In this orientation mode, each range displayed separately starting with the range name followed by the binary data dump.

magic cookie     00000000 00000000 0a 70 61 63 6b 61 67 65 20 44 61 74               .package Dat
padding          0000000c 00000000 61 3a 3a 48 65 78 44 75 6d 70 3a 3a 52 61 6e 67   a::HexDump::Rang
padding          0000001c 00000010 65 20 3b 0a 0a 75 73 65 20 73 74 72 69 63 74 3b   e ;..use strict;
data header      0000002c 00000000 0a 75 73 65 20                                    .use
data             00000031 00000000 77 61 72 6e 69 6e 67 73 20 3b 0a 75 73 65 20 43   warnings ;.use C
data             00000041 00000010 61 72 70 20                                       arp
extra data       00000045 00000000 3b 0a 0a 42 45 47 49 4e 20 0a 7b 0a               ;..BEGIN .{.
data header      00000051 00000000 0a 75 73 65 20                                    .use
data             00000056 00000000 53 75 62 3a 3a 45 78 70 6f 72 74 65 72 20 2d 73   Sub::Exporter -s
data             00000066 00000010 65 74 75 70                                       etup
footer           0000006a 00000000 20 3d 3e 20                                        =>

RANGE_NAME       OFFSET   CUMULATI HEX_DUMP                                         ASCII_DUMP        
                                   0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f   0123456789012345  
12:header        00000000 00000000 63 6f 6d 6d 69 74 20 37 34 39 30 39              commit 74909     
"comment" 
<0:zero> 
10:name          0000000c 00000000 63 37 36 35 37 65 64 62 38 39                    c7657edb89       
5:offset         00000016 00000000 34 65 66 61 65                                   4efae            
17:footer        0000001b 00000000 65 34 63 64 37 39 34 33 63 65 37 38 37 35 66 62  e4cd7943ce7875fb 
17:footer        0000002b 00000010 32                                               2                
5:something      0000002c 00000000 36 31 39 20 28                                   619 (            

Horizontal

In this mode, the data are packed together in the dump

00000000 0a 70 61 63 6b 61 67 65 20 44 61 74 61 3a 3a 48   .package Data::H magic cookie, padding,
00000010 65 78 44 75 6d 70 3a 3a 52 61 6e 67 65 20 3b 0a   exDump::Range ;. padding,
00000020 0a 75 73 65 20 73 74 72 69 63 74 3b 0a 75 73 65   .use strict;.use padding, data header,
00000030 20 77 61 72 6e 69 6e 67 73 20 3b 0a 75 73 65 20    warnings ;.use  data header, data,
00000040 43 61 72 70 20 3b 0a 0a 42 45 47 49 4e 20 0a 7b   Carp ;..BEGIN .{ data, extra data,
00000050 0a 0a 75 73 65 20 53 75 62 3a 3a 45 78 70 6f 72   ..use Sub::Expor extra data, data header, data,
00000060 74 65 72 20 2d 73 65 74 75 70 20 3d 3e 20         ter -setup =>    data, footer,

Rendered fields

You can choose which fields are rendered by setting options when creating a Data::HexDump::Range object. The default rendering corresponds to the following object construction:

  Data::HexDump::Range->new
	(
	FORMAT => 'ANSI',
	COLOR => 'cycle',
	
	ORIENTATION => 'horizontal',
	
	DISPLAY_RANGE_NAME => 1 ,
	
	DISPLAY_OFFSET  => 1 ,
	OFFSET_FORMAT => 'hex',
	
	DISPLAY_HEX_DUMP => 1,
	DISPLAY_ASCII_DUMP => 1,
	
	DATA_WIDTH => 16,
	) ;

See new.

Range definition

my $simple_range = ['magic cookie', 12, 'red'] ;

Ranges are Array references containing four (4) elements:

  • name - a string

  • size - an integer

  • color - a string or undef

  • user information - a very short string descibing the range

Any of the three first elements can be replaced by a subroutine reference. See "Dynamic range definition" below.

You can also declare the ranges in a string. The string use the format used by the hdr command line range dumper that was installed by this module.

Example:

hdr -r 'header,12:name,10:xx, 2:yy,2:offset,4:BITMAP,4,bright_yellow,hi:ff,x2b2:fx,b32:f0,b16: \
     field,x8b8:field2, b17:footer,17:something,5'  \
     -col -display_ruler -display_range_size 1 -show_dec_dump 1 -o ver my_data_file

TODO: document string range format

Coloring

Ranges and ranges names are displayed according to the color field in the range definition.

The color definition is one of:

  • A user defined color name found in COLOR_NAMES (see new)

  • An ansi color definition - 'blue on_yellow'

  • undef - will be repaced by a white color or picked from a cyclic color list (see COLOR in new).

Linear ranges

For simple data formats, your can put all the your range descriptions in a array:

  my $image_ranges =
	[
	  ['magic cookie', 12, 'red'],
	  ['size', 10, 'yellow'],
	  ['data', 10, 'blue on_yellow'],
	  ['timestamp', 5, 'green'],
	] ;

Structured Ranges

  my $data_range = # definition to re-use
	[
	  ['data header', 5, 'blue on_yellow'],
	  ['data', 100, 'blue'],
	] ;
			
  my $structured_range = 
	[
	  [
	    ['magic cookie', 12, 'red'],
	    ['padding', 88, 'yellow'],
	    $data_range, 
	  ],
		
	  [
	    ['extra data', 12, undef],
	    [
	      $data_range, 
	      ['footer', 4, 'yellow on_red'],
	    ]
	  ],
	]
	

Comment ranges

If the size of a range is the string '#', the whole range is considered a comment

  my $range_defintion_with_comments = 
	[
	  ['comment text', '#', 'optional color for meta range'],
	  ['magic cookie', 12, 'red'],
	  ['padding', 88, 'yellow'],
	    
	  [
	    ['another comment', '#'],
	    ['data header', 5, 'blue on_yellow'],
	    ['data', 100, 'blue'],
	  ],
	] ;

Bitfields

Bitfields can be up to 32 bits long and can overlap each other. Bitfields are applied on the previously defined range.

hdr -r 'BITMAP,4,bright_yellow:ff,x2b2:fx,3b17:f0,7b13' -col -o ver ~/my_file

In the hdr example above, four bitfields ff, fx, f0 are defined. They will be applied on the data defined by the BITMAP range.

             .------------.                      .--------------.
             | data range |                      | data hexdump |
             '------------'                      '--------------'
                    |                                    |
                    |                                    |
       RANGE_NAME   |   OFFSET   CUMULATI HEX_DUMP       |                                 ASCII_DUMP     
       BITMAP  <----'   00000000 00000000 63 6f 6d 6d <--'                                 comm           
   .-> .ff              02 .. 03          -- -- -- 02 --10----------------------------     .bitfield: ---.
   .-> .fx              03 .. 19          -- 00 36 f6 ---00011011011110110------------     .bitfield: -.6?
   .-> .f0              07 .. 17          -- -- 05 bd -------10110111101--------------     .bitfield: --.?
   |                        ^                   ^                   ^                            ^
   |                        |                   |                   |                            |
.-----------.     .-------------------.         |       .----------------------.      .---------------------.
| bitfields |     | start and end bit |         |       | bitfield binary dump |      | bitfield ascci dump |
'-----------'     '-------------------'         |       '----------------------'      '---------------------'
                                      .-------------------.
                                      | bitfields hexdump |
                                      '-------------------'

The definiton follows the format an optional "x (for offset) + offset" + "b (for bits) + number of bits".

The dump with colors:


RANGE_NAME       OFFSET   CUMULATI HEX_DUMP                                         ASCII_DUMP        
BITMAP           00000000 00000000 63 6f 6d 6d                                      comm             
.ff              02 .. 03          -- -- -- 02 --10----------------------------     .bitfield: ---.  
.fx              03 .. 19          -- 00 36 f6 ---00011011011110110------------     .bitfield: -.6ö  
.f0              07 .. 19          -- -- 16 f6 -------1011011110110------------     .bitfield: --.ö  

Dynamic range definition

The whole range can be replaced by a subroutine reference or elements of the range can be replaced by a subroutine definition.

  my $dynamic_range =
	[
	  [\&name, \&size, \&color ],
	  [\&define_range] # returns a range definition
	] ;

'name' sub ref

sub cloth_size
{
my ($data, $offset, $size) = @_ ;
my %types = (O => 'S', 1 => 'M', 2 => 'L',) ;
return 'size:' . ($types{$data} // '?') ;
}

$hdr->dump([\&cloth_size, 1, 'yellow'], $data) ;

'size' sub ref

sub cloth_size
{
my ($data, $offset, $size) = @_ ;
return unpack "a", $data ;
}

$hdr->dump(['data', \&get_size, 'yellow'], $data) ;

'color' sub ref

my $flip_flop = 1 ;
my @colors = ('green', 'red') ;

sub alternate_color {$flip_flop ^= 1 ; return $colors[$flip_flop] }

$hdr->dump(['data', 100, \&alternate_color], $data) ;

'range' sub ref

sub whole_range(['whole range', 5, 'on_yellow']}

$hdr->dump([\&whole_range], $data) ; #note this is very different from L<User defined range generator>

User defined range generator

A subroutine reference can be passed as a range definition. The cubroutine will be called repetitively till the data is exhausted or the subroutine returns undef.

sub my_parser 
	{
	my ($data, $offset) = @_ ;
	
	my $first_byte = unpack ("x$offset C", $data) ;
	
	$offset < length($data)
		?  $first_byte == ord(0)
			? ['from odd', 5, 'blue on_yellow']
			: ['from even', 3, 'green']
		: undef ;
	}

my $hdr = Data::HexDump::Range->new() ;
print $hdr->dump(\&my_parser, '01' x 50) ;

my_parser($data, $offset)

Returns a range description for the next range to dump

Arguments - See gather

  • $data - Binary string - the data passed to the dump method

  • $offset - Integer - current offset in $data

Returns -

  • $range - An array reference containing a name, size and color

    OR

  • undef - Done parsing

EXAMPLES

See HDR.html

OTHER IDEAS

- allow pack format as range size pack in array context returns the amount of fields processed fixed format can be found with a length of unpack

- hook with Convert::Binary::C to automatically create ranges

SUBROUTINES/METHODS

Subroutines prefixed with [P] are not part of the public API and shall not be used directly.

new(NAMED_ARGUMENTS)

Create a Data::HexDump::Range object.

  my $hdr = Data::HexDump::Range->new() ; # use default setup
  
  my $hdr = Data::HexDump::Range->new
		(
		FORMAT => 'ANSI'|'ASCII'|'HTML',
		COLOR => 'bw' | 'cycle',
		OFFSET_FORMAT => 'hex' | 'dec',
		DATA_WIDTH => 16 | 20 | ... ,
		DISPLAY_RANGE_NAME => 1 ,
		MAXIMUM_RANGE_NAME_SIZE => 16,
		DISPLAY_COLUMN_NAMES => 0,
		DISPLAY_RULER => 0,
		DISPLAY_OFFSET  => 1 ,
		DISPLAY_CUMULATIVE_OFFSET  => 1 ,
		DISPLAY_ZERO_SIZE_RANGE_WARNING => 1,
		DISPLAY_ZERO_SIZE_RANGE => 1,
		DISPLAY_RANGE_SIZE => 1,
		DISPLAY_ASCII_DUMP => 1 ,
		DISPLAY_HEX_DUMP => 1,
		DISPLAY_DEC_DUMP => 1,
		COLOR_NAMES => {},
		ORIENTATION => 'horizontal',
		) ;

Arguments - All arguments are optional. Default values are listed below.

  • NAME - String - Name of the Data::HexDump::Range object, set to 'Anonymous' by default

  • INTERACTION - Hash reference - Set of subs that are used to display information to the user

    Useful if you use Data::HexDump::Range in an application without terminal.

  • VERBOSE - Boolean - Display information about the creation of the object. Default is false

  • FORMAT - String - format of the dump string generated by Data::HexDump::Range.

    Default is ANSI which allows for colors. Other formats are 'ASCII' and 'HTML'.

  • COLOR - String 'bw' or 'cycle'.

    Ranges for which no color has been defined, in 'ANSI' or 'HTML' format mode, will be rendered in black and white or with a color picked from a cyclic color list. Default is 'bw'.

  • OFFSET_FORMAT - String - 'hex' or 'dec'

    If set to 'hex', the offset will be displayed in base 16. When set to 'dec' the offset is displayed in base 10. Default is 'hex'.

  • DATA_WIDTH - Integer - Number of elements displayed per line. Default is 16.

  • DISPLAY_RANGE_NAME - Boolean - If set, range names are displayed in the dump.

  • MAXIMUM_RANGE_NAME_SIZE - Integer - maximum size of a range name (horizontal mode). Default size is 16.

  • DISPLAY_COLUMN_NAMES - Boolean - If set, the column names are displayed. Default false

  • DISPLAY_RULER - Boolean - if set, a ruler is displayed above the dump, Default is false

  • DISPLAY_OFFSET - Boolean - If set, the offset column is displayed. Default true

  • DISPLAY_CUMULATIVE_OFFSET - Boolean - If set, the cumulative offset column is displayed in 'vertical' rendering mode. Default is true

  • DISPLAY_ZERO_SIZE_RANGE - Boolean - if set, ranges that do not consume data are displayed. default is true

  • DISPLAY_ZERO_SIZE_RANGE_WARNING - Boolean - if set, a warning is emitted if ranges that do not consume data. Default is true

  • DISPLAY_RANGE_SIZE - Bolean - if set the range size is prepended to the name. Default false

  • DISPLAY_ASCII_DUMP - Boolean - If set, the ASCII representation of the binary data is displayed. Default is true

  • DISPLAY_HEX_DUMP - Boolean - If set, the hexadecimal dump column is displayed. Default is true

  • DISPLAY_DEC_DUMP - Boolean - If set, the decimall dump column is displayed. Default is false

  • COLOR_NAMES - A hash reference

      {
      ANSI =>
    	{
    	header => 'yellow on_blue',
    	data => 'yellow on_black',
    	},
    	
      HTML =>
    	{
    	header => 'FFFF00 0000FF',
    	data => 'FFFF00 000000',
    	},
      }
  • ORIENTATION - String - 'vertical' or 'horizontal' (the default).

Returns - Nothing

Exceptions - Dies if an unsupported option is passed.

[P] Setup(...)

Helper sub called by new. This is a private sub.

[P] CheckOptionNames(...)

Verifies the named options passed to the members of this class. Calls {INTERACTION}{DIE} in case of error.

gather($range_description, $data, $offset, $size)

Dump the data, up to $size, according to the description. The data dump is kept in the object so you can merge multiple gathered dumps and get a single rendering.

$hdr->gather($range_description, $data, $offset, $size)
$hdr->gather($range_description, $more_data)

print $hdr->dump_gathered() ;

Arguments

  • $range_description - See "Range definition"

  • $data - A string - binary data to dump

  • $offset - dump data from offset

    • undef - start from first byte

  • $size - amount of data to dump

    • undef - use range description

    • CONSUME_ALL_DATA - apply range descritption till all data is consumed

Returns - An integer - the number of processed bytes

Exceptions - See _gather

dump_gathered()

Returns the dump string for the gathered data.

$hdr->gather($range_description, $data, $size)
$hdr->gather($range_description, $data, $size)

print $hdr->dump_gathered() ;

Arguments - None

Returns - A string - the binary data formated according to the rnage descriptions

Exceptions - None

dump($range_description, $data, $offset, $size)

Dump the data, up to $size, according to the description

Arguments - See gather

Returns - A string - the formated dump

Exceptions - dies if the range description is invalid

[P] add_information($split_data)

Add information, according to the options passed to the constructor, to the internal data.

Arguments - See gather

  • $split_data - data returned by _gather()

Returns - Nothing

Exceptions - None

get_dump_and_consumed_data_size($range_description, $data, $offset, $size)

Dump the data, from $offset up to $size, according to the $range_description

Arguments - See gather

Returns -

  • A string - the formated dump

  • An integer - the number of bytes consumed by the range specification

Exceptions - dies if the range description is invalid

reset()

Clear the gathered dump

Arguments - None

Returns - Nothing

Exceptions - None

[P] _gather($range_description, $data, $offset, $size)

Creates an internal data structure from the data to dump.

$hdr->_gather($container, $range_description, $data, $size)

Arguments - See gather

  • $container - an array reference or undef - where the gathered data

  • $range_description - See gather

  • $data - See gather

  • $offset - See gather

  • $size - See gather

Returns -

  • $container - the gathered data

  • $used_data - integer - the location in the data where the dumping ended

Exceptions dies if passed invalid parameters

[P] create_ranges($range_description)

transforms the user supplied ranges into an internal format

Arguments -

  • $range_description - See gather

Returns - Nothing

Exceptions - Croaks with an error messge if the input data is invalid

[P] create_ranges_from_string($range_description)

transforms the user supplied ranges into an internal format

Arguments -

  • $range_description - A string - See gather

Returns - Nothing

Exceptions - Croaks with an error messge if the input data is invalid

[P] create_ranges_from_array_ref($range_description)

transforms the user supplied ranges into an internal format

Arguments -

  • $range_description - An array reference - See gather

Returns - Nothing

Exceptions - Croaks with an error messge if the input data is invalid

[P] flatten($range_description)

transforms the user supplied ranges into an internal format

Arguments -

  • $range_description - See gather

Returns - Nothing

Exceptions - Croaks with an error messge if the input data is invalid

[P] split($collected_data)

Split the collected data into lines

Arguments -

  • $container - Collected data

Returns - Nothing

Exceptions

[P] get_default_color()

Returns a color to use with a range that has none

my $default_color = $self->get_default_color() ;

Arguments - None

Returns - A string - a color according to the COLOR option and FORMAT

Exceptions - None

[P] format($line_data)

Transform the line data into ANSI, ASCII or HTML

Arguments -

Returns - A dump in ANSI, ASCII or HTML.

BUGS AND LIMITATIONS

None so far.

AUTHOR

Nadim ibn hamouda el Khemir
CPAN ID: NKH
mailto: nadim@cpan.org

COPYRIGHT & LICENSE

Copyright 2010 Nadim Khemir.

This program is free software; you can redistribute it and/or modify it under the terms of either:

  • the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or

  • the Artistic License version 2.0.

SUPPORT

You can find documentation for this module with the perldoc command.

perldoc Data::HexDump::Range

You can also look for information at:

SEE ALSO

Data::Hexdumper, Data::ParseBinary, Convert::Binary::C, Parse::Binary

1 POD Error

The following errors were encountered while parsing the POD:

Around line 308:

Non-ASCII character seen before =encoding in '-.6ö'. Assuming CP1252