File Coverage

blib/lib/Data/HexDump/Range/Object.pm
Criterion Covered Total %
statement 63 86 73.2
branch 16 42 38.1
condition 16 46 34.7
subroutine 9 11 81.8
pod 0 2 0.0
total 104 187 55.6


line stmt bran cond sub pod time code
1              
2             package Data::HexDump::Range ; ## no critic (Modules::RequireFilenameMatchesPackage)
3              
4 2     2   10 use strict;
  2         4  
  2         94  
5 2     2   10 use warnings ;
  2         4  
  2         131  
6 2     2   11 use Carp ;
  2         3  
  2         144  
7              
8             BEGIN
9 2     2   1154 {
10              
11 2         25 use Sub::Exporter -setup =>
12             {
13             exports => [ qw() ],
14             groups =>
15             {
16             all => [ qw() ],
17             }
18 2     2   9 };
  2         2  
19             }
20              
21             #-------------------------------------------------------------------------------
22              
23 2     2   15 use English qw( -no_match_vars ) ;
  2         4  
  2         14  
24              
25 2     2   734 use Readonly ;
  2         4  
  2         2305  
26             Readonly my $EMPTY_STRING => q{} ;
27              
28             #-------------------------------------------------------------------------------
29              
30             =head1 NAME
31              
32             Data::HexDump::Range::Object - Hexadecial Range Dumper object creation support methods
33              
34             =head1 SYNOPSIS
35              
36             =head1 DESCRIPTION
37              
38             The main goal of this module is to remove non public APIs from the module documentation
39              
40             =head1 DOCUMENTATION
41              
42             =head1 SUBROUTINES/METHODS
43              
44             Subroutines prefixed with B<[P]> are not part of the public API and shall not be used directly.
45              
46             =cut
47              
48              
49             #-------------------------------------------------------------------------------
50              
51             Readonly my $NEW_ARGUMENTS =>
52             [
53             qw(
54             NAME INTERACTION VERBOSE
55            
56             DUMP_RANGE_DESCRIPTION
57             DUMP_ORIGINAL_RANGE_DESCRIPTION
58             GATHERED_CHUNK
59            
60             FORMAT
61             COLOR
62             START_COLOR
63             OFFSET_FORMAT
64             OFFSET_START
65             DATA_WIDTH
66             DISPLAY_COLUMN_NAMES
67             DISPLAY_RULER
68             DISPLAY_OFFSET
69             DISPLAY_CUMULATIVE_OFFSET
70             DISPLAY_ZERO_SIZE_RANGE_WARNING
71             DISPLAY_ZERO_SIZE_RANGE
72             DISPLAY_COMMENT_RANGE
73            
74             DISPLAY_RANGE_NAME
75             MAXIMUM_RANGE_NAME_SIZE
76             DISPLAY_RANGE_SIZE
77            
78             DISPLAY_ASCII_DUMP
79             DISPLAY_HEXASCII_DUMP
80             DISPLAY_HEX_DUMP
81             DISPLAY_DEC_DUMP
82            
83             DISPLAY_USER_INFORMATION
84             MAXIMUM_USER_INFORMATION_SIZE
85            
86             DISPLAY_BITFIELDS
87             DISPLAY_BITFIELD_SOURCE
88             MAXIMUM_BITFIELD_SOURCE_SIZE
89            
90             BIT_ZERO_ON_LEFT
91             COLOR_NAMES
92             ORIENTATION
93             )] ;
94              
95             #-------------------------------------------------------------------------------
96              
97             sub Setup
98             {
99              
100             =head2 [P] Setup()
101              
102             Helper sub called by new. This is a private sub.
103              
104             =cut
105              
106 2     2 0 6 my ($self, $package, $file_name, $line, @setup_data) = @_ ;
107              
108 2 50       10 if (@setup_data % 2)
109             {
110 0         0 croak "Invalid number of argument '$file_name, $line'!" ;
111             }
112              
113 2   50 0   39 $self->{INTERACTION}{INFO} ||= sub {print @_} ;
  0         0  
114 2   50     16 $self->{INTERACTION}{WARN} ||= \&Carp::carp ;
115 2   50     11 $self->{INTERACTION}{DIE} ||= \&Carp::croak ;
116 2         4 $self->{NAME} = 'Anonymous';
117 2         5 $self->{FILE} = $file_name ;
118 2         5 $self->{LINE} = $line ;
119              
120 2         8 $self->CheckOptionNames($NEW_ARGUMENTS, @setup_data) ;
121              
122 2         70 %{$self} =
  2         13  
123             (
124 26         50 %{$self},
125            
126             VERBOSE => 0,
127             DUMP_RANGE_DESCRIPTION => 0,
128             DUMP_ORIGINAL_RANGE_DESCRIPTION => 0,
129            
130             FORMAT => 'ANSI',
131            
132             COLOR => 'cycle',
133             CURRENT_COLOR_INDEX => 0,
134             START_COLOR => undef,
135            
136             # --color bw will use the last defined color as color
137             COLORS =>
138             {
139             ASCII => [],
140 26         46 ANSI => [map {"bright_$_"} 'green', 'yellow', 'cyan', 'magenta', 'blue', 'red', 'green', 'yellow', 'cyan', 'magenta', 'blue', 'red', 'white', ],
141 2         3 HTML => [map {"bright_$_"} 'green', 'yellow', 'cyan', 'magenta', 'blue', 'red', 'green', 'yellow', 'cyan', 'magenta', 'blue', 'red', 'white', ],
142             },
143            
144             OFFSET_FORMAT => 'hex',
145             OFFSET_START => 0,
146            
147             DATA_WIDTH => 16,
148            
149             DISPLAY_ZERO_SIZE_RANGE_WARNING => 1,
150             DISPLAY_ZERO_SIZE_RANGE => 1,
151             DISPLAY_COMMENT_RANGE => 1,
152            
153             DISPLAY_RANGE_NAME => 1,
154             MAXIMUM_RANGE_NAME_SIZE => 16,
155             DISPLAY_RANGE_SIZE => 1,
156            
157             DISPLAY_COLUMN_NAMES => 0 ,
158             DISPLAY_RULER => 0,
159            
160             DISPLAY_OFFSET => 1,
161             DISPLAY_CUMULATIVE_OFFSET => 1,
162              
163             DISPLAY_HEXASCII_DUMP => 0,
164              
165             DISPLAY_HEX_DUMP => 1,
166             DISPLAY_DEC_DUMP => 0,
167             DISPLAY_ASCII_DUMP => 1,
168             DISPLAY_USER_INFORMATION => 0,
169             MAXIMUM_USER_INFORMATION_SIZE => 20,
170              
171             DISPLAY_BITFIELDS => undef,
172             DISPLAY_BITFIELD_SOURCE => 1,
173             MAXIMUM_BITFIELD_SOURCE_SIZE => 8,
174             BIT_ZERO_ON_LEFT => 0,
175            
176             ORIENTATION => 'horizontal',
177            
178             GATHERED => [],
179             @setup_data,
180             ) ;
181              
182 2   50 0   14 $self->{INTERACTION}{INFO} ||= sub {print @_} ;
  0         0  
183 2   50     5 $self->{INTERACTION}{WARN} ||= \&Carp::carp ;
184 2   50     6 $self->{INTERACTION}{DIE} ||= \&Carp::croak ;
185              
186 2         7 my $location = "$self->{FILE}:$self->{LINE}" ;
187              
188 2 50       5 if($self->{VERBOSE})
189             {
190 0         0 $self->{INTERACTION}{INFO}('Creating ' . ref($self) . " '$self->{NAME}' at $location.\n") ;
191             }
192              
193 2 50       6 $self->{MAXIMUM_RANGE_NAME_SIZE} = 4 if$self->{MAXIMUM_RANGE_NAME_SIZE} < 4 ;
194              
195 2 50       35 $self->{FIELD_LENGTH} =
    50          
196             {
197             OFFSET => $self->{OFFSET_FORMAT} =~ /^hex/ ? 8 : 10,
198             CUMULATIVE_OFFSET => $self->{OFFSET_FORMAT} =~ /^hex/ ? 8 : 10,
199             RANGE_NAME => $self->{MAXIMUM_RANGE_NAME_SIZE},
200             ASCII_DUMP => $self->{DATA_WIDTH},
201             HEX_DUMP => $self->{DATA_WIDTH} * 3,
202             DEC_DUMP => $self->{DATA_WIDTH} * 4,
203             HEXASCII_DUMP => $self->{DATA_WIDTH} * 5,
204             USER_INFORMATION => 20,
205             BITFIELD_SOURCE => 8 ,
206             } ;
207              
208 2 50       6 $self->{OFFSET_FORMAT} = $self->{OFFSET_FORMAT} =~ /^hex/ ? "%08x" : "%010d" ;
209              
210 2 50       7 if($self->{ORIENTATION} =~ /^hor/)
211             {
212 2 50       7 $self->{DISPLAY_BITFIELDS} = 0 unless defined $self->{DISPLAY_BITFIELDS} ;
213 2 50       6 $self->{DISPLAY_BITFIELD_SOURCE} = 0 unless $self->{DISPLAY_BITFIELDS} ;
214            
215 2         4 my @fields = qw(OFFSET) ;
216 2 50       4 push @fields, 'BITFIELD_SOURCE' if $self->{DISPLAY_BITFIELD_SOURCE} ;
217 2         7 push @fields, qw( HEX_DUMP HEXASCII_DUMP DEC_DUMP ASCII_DUMP RANGE_NAME) ;
218            
219 2         5 $self->{FIELDS_TO_DISPLAY} = \@fields ;
220             }
221             else
222             {
223 0 0       0 $self->{DISPLAY_BITFIELDS} = 1 unless defined $self->{DISPLAY_BITFIELDS} ;
224            
225 0         0 $self->{FIELDS_TO_DISPLAY} =
226             [qw(RANGE_NAME OFFSET CUMULATIVE_OFFSET HEX_DUMP HEXASCII_DUMP DEC_DUMP ASCII_DUMP USER_INFORMATION)] ;
227             }
228              
229             #Todo: verify FORMAT
230              
231 2 0 33     13 if(! defined $self->{COLOR} || ($self->{COLOR} ne 'cycle' && $self->{COLOR} ne 'no_cycle' && $self->{COLOR} ne 'bw'))
      33        
      33        
232             {
233 0   0     0 $self->{COLOR} ||= 'error!' ;
234 0         0 $self->{INTERACTION}{DIE}("Error: Invalid color format. Valid formats are 'cycle', 'no_cycle' and 'bw'.\n") ;
235             }
236              
237 2 0 33     11 if(! defined $self->{FORMAT} || ($self->{FORMAT} ne 'ANSI' && $self->{FORMAT} ne 'HTML' && $self->{FORMAT} ne 'ASCII'))
      33        
      33        
238             {
239 0   0     0 $self->{FORMAT} ||= 'error!' ;
240 0         0 $self->{INTERACTION}{DIE}("Error: Invalid output format. Valid formats are 'ANSI', 'HTML', and 'ASCII'.\n") ;
241             }
242              
243 2 50 33     7 if(defined $self->{GATHERED_CHUNK} && 'CODE' ne ref($self->{GATHERED_CHUNK}))
244             {
245 0         0 $self->{INTERACTION}{DIE}("Error: GATHERED_CHUNK is not a code reference.\n") ;
246             }
247              
248 2 50       5 if(defined $self->{START_COLOR})
249             {
250 0         0 my $index = 0 ;
251            
252 0         0 for my $color_name (@{$self->{COLORS}{$self->{FORMAT}}})
  0         0  
253             {
254 0 0       0 last if $color_name eq $self->{START_COLOR} ;
255 0         0 $index++ ;
256             }
257            
258 0         0 $self->{CURRENT_COLOR_INDEX} = $index ;
259             }
260              
261 2         6 return ;
262             }
263              
264             #-------------------------------------------------------------------------------
265              
266             sub CheckOptionNames
267             {
268              
269             =head2 [P] CheckOptionNames()
270              
271             Verifies the named options passed to the members of this class. Calls B<{INTERACTION}{DIE}> in case
272             of error.
273              
274             =cut
275              
276 2     2 0 14 my ($self, $valid_options, @options) = @_ ;
277              
278 2 50       19 if (@options % 2)
279             {
280 0         0 $self->{INTERACTION}{DIE}->('Invalid number of argument!') ;
281             }
282              
283 2 50       11 if('HASH' eq ref $valid_options)
    50          
284             {
285             # OK
286             }
287             elsif('ARRAY' eq ref $valid_options)
288             {
289 2         2 $valid_options = { map{$_ => 1} @{$valid_options} } ;
  68         176  
  2         7  
290             }
291             else
292             {
293 0         0 $self->{INTERACTION}{DIE}->("Invalid argument '$valid_options'!") ;
294             }
295              
296 2         12 my %options = @options ;
297              
298 2         11 for my $option_name (keys %options)
299             {
300 0 0       0 unless(exists $valid_options->{$option_name})
301             {
302 0         0 $self->{INTERACTION}{DIE}->
303             (
304             "$self->{NAME}: Invalid Option '$option_name' at '$self->{FILE}:$self->{LINE}'\nValid options:\n\t"
305 0         0 . join("\n\t", sort keys %{$valid_options}) . "\n"
306             );
307             }
308             }
309              
310 2 50 33     27 if
      33        
      33        
311             (
312             (defined $options{FILE} && ! defined $options{LINE})
313             || (!defined $options{FILE} && defined $options{LINE})
314             )
315             {
316 0         0 $self->{INTERACTION}{DIE}->("$self->{NAME}: Incomplete option FILE::LINE!") ;
317             }
318              
319 2         13 return(1) ;
320             }
321              
322             #-------------------------------------------------------------------------------
323              
324             1 ;
325              
326             =head1 BUGS AND LIMITATIONS
327              
328             None so far.
329              
330             =head1 AUTHOR
331              
332             Nadim ibn hamouda el Khemir
333             CPAN ID: NKH
334             mailto: nadim@cpan.org
335              
336             =head1 COPYRIGHT AND LICENSE
337              
338             Copyright Nadim Khemir 2010.
339              
340             This program is free software; you can redistribute it and/or
341             modify it under the terms of either:
342              
343             =over 4
344              
345             =item * the GNU General Public License as published by the Free
346             Software Foundation; either version 1, or (at your option) any
347             later version, or
348              
349             =item * the Artistic License version 2.0.
350              
351             =back
352              
353             =head1 SUPPORT
354              
355             You can find documentation for this module with the perldoc command.
356              
357             perldoc Data::HexDump::Range
358              
359             You can also look for information at:
360              
361             =over 4
362              
363             =item * AnnoCPAN: Annotated CPAN documentation
364              
365             L
366              
367             =item * RT: CPAN's request tracker
368              
369             Please report any bugs or feature requests to L .
370              
371             We will be notified, and then you'll automatically be notified of progress on
372             your bug as we make changes.
373              
374             =item * Search CPAN
375              
376             L
377              
378             =back
379              
380             =head1 SEE ALSO
381              
382             L, L, L, L
383              
384             =cut