1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
|
# -*- mode: Perl -*-
##########################################################################
#
# HexDump.pm - Hexadecial Dumper
#
# Copyright (c) 1998, 1999, Fabien Tassin <fta@oleane.net>
##########################################################################
# ABSOLUTELY NO WARRANTY WITH THIS PACKAGE. USE IT AT YOUR OWN RISKS.
##########################################################################
package Data::HexDump;
$Data::HexDump::VERSION = '0.04';
use 5.006;
use strict;
use warnings;
use parent 'Exporter';
use Carp;
use FileHandle;
our @EXPORT = qw( HexDump );
sub new {
my $this = shift;
my $class = ref($this) || $this;
my $self = {};
bless $self, $class;
$self->{'readsize'} = 128;
return $self;
}
sub DESTROY {
my $self = shift;
$self->{'fh'}->close if defined $self->{'file'};
}
sub file {
my $self = shift;
my $file = shift;
$self->{'file'} = $file if defined $file;
$self->{'file'};
}
sub fh {
my $self = shift;
my $fh = shift;
$self->{'fh'} = $fh if defined $fh;
$self->{'fh'};
}
sub data {
my $self = shift;
my $data = shift;
$self->{'data'} = $data if defined $data;
$self->{'data'};
}
sub block_size {
my $self = shift;
my $bs = shift;
$self->{'blocksize'} = $bs if defined $bs;
$self->{'blocksize'};
}
sub dump {
my $self = shift;
my $out;
my $l;
$self->{'i'} = 0 unless defined $self->{'i'};
$self->{'j'} = 0 unless defined $self->{'j'};
my $i = $self->{'i'};
my $j = $self->{'j'};
unless ($i || $j) {
$out = " ";
$l = "";
for (my $i = 0; $i < 16; $i++) {
$out .= sprintf "%02X", $i;
$out .= " " if $i < 15;
$out .= "- " if $i == 7;
$l .= sprintf "%X", $i;
}
$i = $j = 0;
$out .= " $l\n\n";
}
return undef if $self->{'eod'};
$out .= sprintf "%08X ", $j * 16;
$l = "";
my $val;
while (($val = $self->get) ne '') {
while (length $val && defined (my $v = substr $val, 0, 1, '')) {
$out .= sprintf "%02X", ord $v;
$out .= " " if $i < 15;
$out .= "- " if $i == 7 &&
(length $val || !($self->{'eod'} || length $val));
$i++;
$l .= ord($v) >= 0x20 && ord($v) <= 0x7E ? $v : ".";
if ($i == 16) {
$i = 0;
$j++;
$out .= " " . $l;
$l = "";
$out .= "\n";
if (defined $self->{'blocksize'} && $self->{'blocksize'} &&
($j - $self->{'j'}) > $self->{'blocksize'} / 16) {
$self->{'i'} = $i;
$self->{'j'} = $j;
$self->{'val'} = $val;
return $out;
}
$out .= sprintf "%08X ", $j * 16 if length $val || !length $val &&
!$self->{'eod'};
}
}
}
if ($i || (!$i && !$j)) {
$out .= " " x (3 * (17 - $i) - 2 * ($i > 8));
$out .= "$l\n";
}
$self->{'i'} = $i;
$self->{'j'} = $j;
$self->{'val'} = $val;
return $out;
}
# get data from different sources (scalar, filehandle, file..)
sub get {
my $self = shift;
my $buf;
my $length = $self->{'readsize'};
undef $self->{'val'} if defined $self->{'val'} && ! length $self->{'val'};
if (defined $self->{'val'}) {
$buf = $self->{'val'};
undef $self->{'val'};
}
elsif (defined $self->{'data'}) {
$self->{'data_offs'} = 0 unless defined $self->{'data_offs'};
my $offset = $self->{'data_offs'};
$buf = substr $self->{'data'}, $offset, $length;
$self->{'data_offs'} += length $buf;
$self->{'eod'} = 1 if $self->{'data_offs'} == length $self->{'data'};
}
elsif (defined $self->{'fh'}) {
read $self->{'fh'}, $buf, $length;
$self->{'eod'} = eof $self->{'fh'};
}
elsif (defined $self->{'file'}) {
$self->{'fh'} = FileHandle->new($self->{'file'});
read $self->{'fh'}, $buf, $length;
$self->{'eod'} = eof $self->{'fh'};
}
else {
print "Not yet implemented\n";
}
$buf;
}
sub HexDump ($) {
my $val = shift;
my $f = Data::HexDump->new();
$f->data($val);
$f->dump;
}
1;
=head1 NAME
Data::HexDump - Hexadecial Dumper
=head1 SYNOPSIS
Functional interface:
use Data::HexDump;
print HexDump($data_string);
OO interface:
use Data::HexDump;
my $dumper = Data::HexDump->new();
print while $_ = $dumper->dump;
=head1 DESCRIPTION
This module will generate a hexadecimal dump of a data string or file.
You can either use the exported function,
as shown in the SYNOPSIS above,
or the OO interface, described below.
The second example from the SYNOPSIS generated this output:
00 01 02 03 04 05 06 07 - 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF
00000000 23 21 2F 75 73 72 2F 62 - 69 6E 2F 70 65 72 6C 0A #!/usr/bin/perl.
00000010 75 73 65 20 73 74 72 69 - 63 74 3B 0A 75 73 65 20 use strict;.use
00000020 77 61 72 6E 69 6E 67 73 - 3B 0A 0A 70 72 69 6E 74 warnings;..print
00000030 20 22 48 65 6C 6C 6F 2C - 20 77 6F 72 6C 64 5C 6E "Hello, world\n
00000040 22 3B 0A ";.
The result is returned in a string.
Each line of the result consists of the offset in the
source in the leftmost column of each line,
followed by one or more columns of data from the source in hexadecimal.
The rightmost column of each line shows the printable characters
(all others are shown as single dots).
=head2 Functional Interface
This module exports a single function, C<HexDump>,
which takes a scalar value and returns a string which
contains the hexdump of the passed data.
=head2 OO Interface
You first construct a C<Data::HexDump> object,
then tell it where to get the data from,
and then generate the hex dump:
my $dh = Data::HexDump->new();
$dh->data($scalar); # dump the data in this scalar
$dh->fh($fh); # read this filehandle
$dh->file($filename); # read this file and dump contents
print while $_ = $dh->dump;
The different potential sources for data are considered
in the order given above,
so if you pass to the C<data> method,
then any subsequent calls to C<fh()> or C<file()>
will have no effect.
=head1 SEE ALSO
L<Data::Hexify>, by Johan Vromans, is another simple option,
similar to this module. Last release in 2004.
L<Data::Hexdumper> (by David Cantrell, DCANTRELL)
is another hex dumper,
with more features than this module.
L<App::colourhexdump> (by Kent Fredric, RIP)
provides a script which gives colourised output
with character class highlighting.
L<Data::HexDump::Range> provides more functions, colour output,
and the ability to skip uninteresting parts of the input data.
L<Data::HexDump::XXD> provides hex dumps like xxd.
It doesn't say what xxd is, or provide a link,
and there's no example output.
But if you know and like xxd, this might be the one for you!
L<Devel::Hexdump> provides some configuration options,
but there are other more featured modules,
and this one doesn't have example output in the doc.
L<Data::Peek> is a collection of functions for displaying data,
including C<DHexDump> which generates a simple hex dump
from a string.
L<String::HexConvert> will convert ASCII strings to hex and reverse.
=head1 AUTHOR
Fabien Tassin E<lt>fta@oleane.netE<gt>
=head1 COPYRIGHT
Copyright (c) 1998-1999 Fabien Tassin. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=cut
|