File Coverage

lib/Data/HexDump.pm
Criterion Covered Total %
statement 86 110 78.1
branch 29 50 58.0
condition 21 39 53.8
subroutine 12 15 80.0
pod 0 8 0.0
total 148 222 66.6


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