File Coverage

lib/App/colourhexdump/Formatter.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1 1     1   769 use 5.006; # our
  1         2  
  1         35  
2 1     1   4 use strict;
  1         1  
  1         30  
3 1     1   4 use warnings;
  1         1  
  1         82  
4              
5             package App::colourhexdump::Formatter;
6              
7             our $VERSION = '1.000001';
8              
9             # ABSTRACT: Colour-Highlight lines of data as hex.
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13 1     1   196 use Moose qw( has );
  0            
  0            
14             use String::RewritePrefix;
15             use Module::Runtime qw( require_module );
16             use Term::ANSIColor 3.00 qw( colorstrip );
17             use List::MoreUtils qw( natatime );
18              
19             use namespace::autoclean;
20              
21             has colour_profile => (
22             does => 'App::colourhexdump::ColourProfile',
23             is => 'rw',
24             lazy_build => 1,
25             init_arg => undef,
26             );
27              
28             has real_colour_profile_class => (
29             isa => 'Str',
30             is => 'rw',
31             lazy_build => 1,
32             init_arg => undef,
33             );
34              
35             has colour_profile_class => (
36             isa => 'Str',
37             is => 'rw',
38             init_arg => 'colour_profile',
39             default => 'DefaultColourProfile',
40             );
41              
42             has row_length => (
43             isa => 'Int',
44             is => 'ro',
45             default => 32,
46             );
47              
48             has chunk_length => (
49             isa => 'Int',
50             is => 'rw',
51             default => 4,
52             );
53              
54             has hex_row_length => (
55             isa => 'Int',
56             is => 'rw',
57             lazy_build => 1,
58             init_arg => undef,
59             );
60              
61             sub _build_hex_row_length {
62             my $self = shift;
63              
64             # Each byte takes 2 bytes to print.
65             #
66             if ( $self->chunk_length > $self->row_length ) {
67             $self->chunk_length( $self->row_length );
68             }
69             my $real_chunk_length = $self->chunk_length * 2;
70              
71             my $chunks = int( $self->row_length / $self->chunk_length );
72             my $extrachunk = 0;
73              
74             if ( ( $chunks * $self->chunk_length ) < $self->row_length ) {
75             $extrachunk = $self->row_length - ( $chunks * $self->chunk_length );
76             }
77              
78             my $whitespaces = $chunks - 1;
79             if ( $extrachunk > 0 ) {
80             $whitespaces++;
81             }
82              
83             return ( $chunks * $real_chunk_length ) + $whitespaces + $extrachunk;
84              
85             }
86              
87              
88              
89              
90              
91              
92              
93              
94              
95              
96             ## no critic ( Subroutines::RequireArgUnpacking )
97              
98             sub format_foreach_in_fh {
99             my ( $self, $fh, $callback ) = ( $_[0], $_[1], $_[2] );
100             my $offset = 0;
101             while ( read $fh, my $buffer, $self->row_length ) {
102             $callback->( $self->format_row( $buffer, $offset ) );
103             $offset += $self->row_length;
104             }
105             return 1;
106             }
107              
108              
109              
110              
111              
112              
113              
114             ## no critic ( Subroutines::RequireArgUnpacking )
115              
116             sub format_row_from_fh {
117             my ( $self, $fh, $offset ) = ( $_[0], $_[1], $_[2] );
118             read $fh, my $buffer, $self->row_length or return;
119             my $str = $self->format_row( $buffer, $offset );
120             $offset += $self->row_length;
121             return $str, $offset;
122             }
123              
124              
125              
126              
127              
128              
129              
130             sub format_row {
131             my ( $self, $row, $offset ) = @_;
132              
133             my $format = "%10s: %s %s\n";
134             my $offset_hex = _to_hex( pack q{N*}, $offset );
135              
136             my @chars = split //, $row;
137              
138             return sprintf $format, $offset_hex, $self->pad_hex_row( $self->hex_encode(@chars) ), $self->pretty_encode(@chars);
139             }
140              
141              
142              
143              
144              
145              
146              
147             sub hex_encode {
148             my ( $self, @chars ) = @_;
149             my $it = natatime $self->chunk_length, @chars;
150             my @out;
151             while ( my @vals = $it->() ) {
152             my $chunk;
153             for (@vals) {
154             $chunk .= $self->colour_profile->get_string_pre($_);
155             $chunk .= _to_hex($_);
156             $chunk .= $self->colour_profile->get_string_post($_);
157             }
158             push @out, $chunk;
159             }
160             return join q{ }, @out;
161             }
162              
163              
164              
165              
166              
167              
168              
169             sub pretty_encode {
170             my ( $self, @chars ) = @_;
171             my $output;
172             for (@chars) {
173             $output .= $self->colour_profile->get_string_pre($_);
174             $output .= $self->colour_profile->get_display_symbol_for($_);
175             $output .= $self->colour_profile->get_string_post($_);
176             }
177             return $output;
178             }
179              
180             sub _to_hex {
181             return join q{}, map { unpack q{H*}, $_ } @_;
182             }
183              
184              
185              
186              
187              
188              
189              
190             sub pad_hex_row {
191             my ( $self, $row ) = @_;
192             my $length = length colorstrip($row);
193             if ( $length > $self->hex_row_length ) {
194             return $row;
195             }
196             return $row . ( q{ } x ( $self->hex_row_length - $length ) );
197             }
198              
199             sub _build_colour_profile {
200             my $self = shift;
201             require_module( $self->real_colour_profile_class );
202             return $self->real_colour_profile_class->new();
203             }
204              
205             sub _build_real_colour_profile_class {
206             my $self = shift;
207             return String::RewritePrefix->rewrite( { q{} => 'App::colourhexdump::', q{=} => q{} }, $self->colour_profile_class );
208             }
209              
210             __PACKAGE__->meta->make_immutable;
211             no Moose;
212             1;
213              
214             __END__
215              
216             =pod
217              
218             =encoding UTF-8
219              
220             =head1 NAME
221              
222             App::colourhexdump::Formatter - Colour-Highlight lines of data as hex.
223              
224             =head1 VERSION
225              
226             version 1.000001
227              
228             =head1 METHODS
229              
230             =head2 format_foreach_in_fh
231              
232             $formatter->format_foreach_in_fh( $fh, sub {
233             my $formatted = shift;
234             print $formatted;
235             });
236              
237             =head2 format_row_from_fh
238              
239             my ( $formatted , $offset ) = $formatter->format_row_from_fh( $fh, $offset );
240              
241             =head2 format_row
242              
243             my $formatted = $formatter->format_row( "Some Characters", $offset );
244              
245             =head2 hex_encode
246              
247             my $hexes = $formatter->hex_encode( split //, "Some Characters" );
248              
249             =head2 pretty_encode
250              
251             my $nicetext = $formatter->pretty_encode( split //, "Some Characters" );
252              
253             =head2 pad_hex_row
254              
255             my $padded = $Formatter->pad_hex_row( $formatter->hex_enode( split //, "Some Characters" ) );
256              
257             =head1 AUTHOR
258              
259             Kent Fredric <kentnl@cpan.org>
260              
261             =head1 COPYRIGHT AND LICENSE
262              
263             This software is copyright (c) 2014 by Kent Fredric <kentnl@cpan.org>.
264              
265             This is free software; you can redistribute it and/or modify it under
266             the same terms as the Perl 5 programming language system itself.
267              
268             =cut