#!/usr/bin/perl -w

use strict ;
use warnings ;
use Carp ;

=head1 NAME 

 $> hdr - hexdump range

=head1 USAGE

 $> hdr -r range_definitions file_to_dump
 
 $> hdr file_to_dump -r 'header,40, yellow:padding,24:magic,16,red:size,4:data,100:footer,16' -o ver

head1 OPTIONS

 range_description|r           file name containing a description
                               or a string description formated as:
			          'color:name,size:name,size,color:...'
					      
 orientation|o                 'horizontal' or 'vertical'
 display_column_names          1 == display columns names
 format|f                      'ANSI' or 'ASCII' or 'HTML' 
 color                         'bw' or 'cycle',
 data_width                    number of bytes per dump line
 
 offset_format                 'hex' or 'dec' 
 show_offset                   0 == no the offset display
 show_cumulative_offset        0 == no cumulative offset display
 show_zero_size_range          0 == no display of range with size 0
 show_zero_size_range_warning  0 == no warnings about ranges with size 0
 
 show_range_name               1 == display of the range name
 maximum_range_name_size       truncate range name if longer
 display_range_size            1 == prepend the range size to the name
 
 show_hex_dump                 1 == display of the hexadecimal dump
 show_dec_dump                 1 == display of the decimal dump
 show_ascii_dump               1 == display of the ASCII dump
 
 h|help                        display this scripts help page

=head1 EXIT STATUS


=head1 AUTHOR

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

=cut

#------------------------------------------------------------------------------------------------------------------------

use Getopt::Long ;
use English qw( -no_match_vars ) ;

use Data::HexDump::Range qw() ;

our $VERSION = '0.02' ;

#------------------------------------------------------------------------------------------------------------------------

display_help() unless 
	GetOptions
		(
		'range_description|r=s' => \ my $range_description,
		'offset=i' =>  \my $offset,
		'orientation|o=s' => \my $orientation,
		'display_column_names' => \my $display_column_names,
		'format|f=s' => \my $format,
		'color=s' => \my $color,
		'data_width=i' =>  \my $data_width,
		
		'offset_format=s' => \my $offset_format,
		'show_offset=i' => \my $show_offset,
		'show_cumulative_offset=i' => \my $show_cumulative_offset,
		'show_zero_size_range=i' => \my $show_zero_size_range,
		'show_zero_size_range_warning=i' => \my $show_zero_size_range_warning,

		'show_range_name=i' => \my $show_range_name,
		'maximum_range_name_size=i' => \my$maximum_range_name_size,
		'display_range_size=i' => \my $display_range_size,
		
		'show_hex_dump=i' => \my $show_hex_dump,
		'show_dec_dump=i' => \my $show_dec_dump,
		'show_ascii_dump=i' => \my $show_ascii_dump,
		
		'h|help' => \&display_help, 
		) ;

$offset ||= 0 ;
$range_description ||= 'dumping all file' ;

my $hdr = Data::HexDump::Range->new
			(
			ORIENTATION => $orientation || 'horizontal',
			DISPLAY_COLUMN_NAMES => defined $display_column_names ? $display_column_names : 0,
			FORMAT => $format || 'ANSI',
			COLOR => defined $color ? $color : 'cycle',
			
			OFFSET_FORMAT => $offset_format || 'hex',
			DATA_WIDTH => $data_width || 16,
			
			DISPLAY_RANGE_NAME => defined $show_range_name ? $show_range_name : 1 ,
			MAXIMUM_RANGE_NAME_SIZE => defined $maximum_range_name_size ? $maximum_range_name_size : 16,
			DISPLAY_RANGE_SIZE => defined $display_range_size ? $display_range_size : 0,
			
			DISPLAY_OFFSET  => defined $show_offset ? $show_offset : 1 ,
			DISPLAY_CUMULATIVE_OFFSET  => defined $show_cumulative_offset ? $show_cumulative_offset : 1 ,
			DISPLAY_HEX_DUMP => defined $show_hex_dump ? $show_hex_dump : 1,
			DISPLAY_DEC_DUMP => defined $show_dec_dump ? $show_dec_dump : 0,
			DISPLAY_ASCII_DUMP => defined $show_ascii_dump ? $show_ascii_dump :  1 ,
			
			DISPLAY_ZERO_SIZE_RANGE => defined $show_zero_size_range ? $show_zero_size_range : 1,
			DISPLAY_ZERO_SIZE_RANGE_WARNING => defined  $show_zero_size_range_warning ? $show_zero_size_range_warning : 1,
			) ;


use File::Slurp ;
use IO::Select ;

my $data ;

my $io_select = IO::Select->new(\*STDIN) ;
if($io_select->can_read(0))
	{
	$/ = undef ;
	$data =  <STDIN> ; ## no critic (InputOutput::ProhibitExplicitStdin)
	}
else
	{
	display_help() unless @ARGV ;
	$data = read_file shift @ARGV ;
	}

my $range ;

if($range_description =~ /,/)
	{
	$range = $range_description ;
	}
else
	{
	# a file
	$range  = do $range_description || ['no range defined', length($data) ] ;
	}

print $hdr->dump( $range, $data, $offset ) ;

#------------------------------------------------------------------------------------------------------------------------

sub display_help
{

#~ =head2 display_help()

#~ I<Arguments> - None

#~ I<Returns> - Nothing

#~ I<Exceptions> - exits with status code B<1>

#~ =cut

my ($this_script) = ($PROGRAM_NAME =~m/(.*)/sxm ) ;

print {*STDERR} `perldoc $this_script`  or croak 'Error: Can\'t display help!' ; ## no critic (InputOutput::ProhibitBacktickOperators)
exit(1) ;
}
