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