File Coverage

blib/lib/Data/Printer/Common.pm
Criterion Covered Total %
statement 1782 1782 100.0
branch 76 106 71.7
condition 15 29 51.7
subroutine 594 594 100.0
pod 0 2 0.0
total 2467 2513 98.1


line stmt bran cond sub pod time code
1             package Data::Printer::Common;
2             # Private library of shared Data::Printer code.
3 81     81   277678 use strict;
  81         222  
  81         1826  
4 81     81   850 use warnings;
  81         163  
  81         1601  
5 81     81   1262 use Scalar::Util;
  80         224  
  80         63989  
6              
7             my $mro_initialized = 0;
8             my $nsort_initialized;
9              
10              
11             sub _filter_category_for {
12 502     502   1115 my ($name) = @_;
13 502         995 my %core_types = map { $_ => 1 }
  4660         9374  
14             qw(SCALAR LVALUE ARRAY HASH REF VSTRING GLOB FORMAT Regexp CODE);
15 502 100       2820 return exists $core_types{$name} ? 'type_filters' : 'class_filters';
16             }
17              
18             # strings are tough to process: there are control characters like "\t",
19             # unicode characters to name or escape (or do nothing), max_string to
20             # worry about, and every single piece of that could have its own color.
21             # That, and hash keys and strings share this. So we put it all in one place.
22             sub _process_string {
23 261     261   597 my ($ddp, $string, $src_color) = @_;
24              
25             # colorizing messes with reduce_string because we are effectively
26             # adding new (invisible) characters to the string. So we need to
27             # handle reduction first. But! Because we colorize string_max
28             # *and* we should escape any colors already present, we need to
29             # do both at the same time.
30 261         1231 $string = _reduce_string($ddp, $string, $src_color);
31              
32             # now we escape all other control characters except for "\e", which was
33             # already escaped in _reduce_string(), and convert any chosen charset
34             # to the \x{} format. These could go in any particular order:
35 261         860 $string = _escape_chars($ddp, $string, $src_color);
36 261         625 $string = _print_escapes($ddp, $string, $src_color);
37              
38             # finally, send our wrapped string:
39 261         1403 return $ddp->maybe_colorize($string, $src_color);
40             }
41              
42             sub _colorstrip {
43 181     186   3223 my ($string) = @_;
44 178         315 $string =~ s{ \e\[ [\d;]* m }{}xmsg;
45 178         881 return $string;
46             }
47              
48             sub _reduce_string {
49 256     256   1246 my ($ddp, $string, $src_color) = @_;
50 252         633 my $max = $ddp->string_max;
51 252         986 my $str_len = length($string);
52 254 100 66     1846 if ($max && $str_len && $str_len > $max) {
      100        
53 35         81 my $preserve = $ddp->string_preserve;
54 35 100       480 my $skipped_chars = $str_len - ($preserve eq 'none' ? 0 : $max);
55 38         516 my $skip_message = $ddp->maybe_colorize(
56             $ddp->string_overflow,
57             'caller_info',
58             undef,
59             $src_color
60             );
61 36         92 $skip_message =~ s/__SKIPPED__/$skipped_chars/g;
62 36 100       512 if ($preserve eq 'end') {
    100          
    100          
    100          
63 34         1646 substr $string, 0, $skipped_chars, '';
64 33 50       12767 $string =~ s{\e}{$ddp->maybe_colorize('\\e', 'escaped', undef, $src_color)}ge
  32         507  
65             if $ddp->print_escapes;
66 33         1297 $string = $skip_message . $string;
67             }
68             elsif ($preserve eq 'begin') {
69 33         2783 $string = substr($string, 0, $max);
70 33 50       461 $string =~ s{\e}{$ddp->maybe_colorize('\\e', 'escaped', undef, $src_color)}ge
  32         1723  
71             if $ddp->print_escapes;
72 33         73 $string = $string . $skip_message;
73             }
74             elsif ($preserve eq 'extremes') {
75 33         466 my $leftside_chars = int($max / 2);
76 33         241 my $rightside_chars = $max - $leftside_chars;
77 33         78 my $leftside = substr($string, 0, $leftside_chars);
78 33         466 my $rightside = substr($string, -$rightside_chars);
79 32 50       217 if ($ddp->print_escapes) {
80 31         70 $leftside =~ s{\e}{$ddp->maybe_colorize('\\e', 'escaped', undef, $src_color)}ge;
  31         425  
81 30         220 $rightside =~ s{\e}{$ddp->maybe_colorize('\\e', 'escaped', undef, $src_color)}ge;
  30         63  
82             }
83 31         411 $string = $leftside . $skip_message . $rightside;
84             }
85             elsif ($preserve eq 'middle') {
86 31         229 my $string_middle = int($str_len / 2);
87 31         71 my $middle_substr = int($max / 2);
88 31         422 my $substr_begin = $string_middle - $middle_substr;
89 28         196 my $message_begin = $ddp->string_overflow;
90 28         64 $message_begin =~ s/__SKIPPED__/$substr_begin/gs;
91 28         431 my $chars_left = $str_len - ($substr_begin + $max);
92 28         206 my $message_end = $ddp->string_overflow;
93 28         63 $message_end =~ s/__SKIPPED__/$chars_left/gs;
94 28         390 $string = substr($string, $substr_begin, $max);
95 28 50       237 $string =~ s{\e}{$ddp->maybe_colorize('\\e', 'escaped', undef, $src_color)}ge
  27         65  
96             if $ddp->print_escapes;
97 28         409 $string = $ddp->maybe_colorize($message_begin, 'caller_info', undef, $src_color)
98             . $string
99             . $ddp->maybe_colorize($message_end, 'caller_info', undef, $src_color)
100             ;
101             }
102             else {
103             # preserving 'none' only shows the skipped message:
104 28         202 $string = $skip_message;
105             }
106             }
107             else {
108             # nothing to do? ok, then escape any colors already present:
109 243 100       655 $string =~ s{\e}{$ddp->maybe_colorize('\\e', 'escaped', undef, $src_color)}ge
  28         450  
110             if $ddp->print_escapes;
111             }
112 248         760 return $string;
113             }
114              
115              
116             # _escape_chars() replaces characters with their "escaped" versions.
117             # Because it may be called on scalars or (scalar) hash keys and they
118             # have different colors, we need to be aware of that.
119             sub _escape_chars {
120 248     256   525 my ($ddp, $scalar, $src_color) = @_;
121              
122 248         923 my $escape_kind = $ddp->escape_chars;
123 247         933 my %target_for = (
124             nonascii => '[^\x{00}-\x{7f}]+',
125             nonlatin1 => '[^\x{00}-\x{ff}]+',
126             );
127              
128 247 100       603 if ($ddp->unicode_charnames) {
    100          
129 29         1170 require charnames;
130 29 100       32312 if ($escape_kind eq 'all') {
131 27         81 $scalar = join('', map { sprintf '\N{%s}', charnames::viacode(ord $_) } split //, $scalar);
  30         751  
132 27         548 $scalar = $ddp->maybe_colorize($scalar, 'escaped');
133             }
134             else {
135 27 50       110 $scalar =~ s{($target_for{$escape_kind})}{$ddp->maybe_colorize( (join '', map { sprintf '\N{%s}', charnames::viacode(ord $_) } split //, $1), 'escaped', undef, $src_color)}ge if exists $target_for{$escape_kind};
  31         392  
  34         600  
136             }
137             }
138             elsif ($escape_kind eq 'all') {
139 26         69 $scalar = join('', map { sprintf '\x{%02x}', ord $_ } split //, $scalar);
  62         440  
140 26         189 $scalar = $ddp->maybe_colorize($scalar, 'escaped');
141             }
142             else {
143 242 100       640 $scalar =~ s{($target_for{$escape_kind})}{$ddp->maybe_colorize((join '', map { sprintf '\x{%02x}', ord $_ } split //, $1), 'escaped', undef, $src_color)}ge if exists $target_for{$escape_kind};
  31         354  
  34         290  
144             }
145 246         729 return $scalar;
146             }
147              
148             # _print_escapes() prints invisible chars if they exist on a string.
149             # Because it may be called on scalars or (scalar) hash keys and they
150             # have different colors, we need to be aware of that. Also, \e is
151             # deliberately omitted because it was escaped from the original
152             # string earlier, and the \e's we have now are our own colorized
153             # output.
154             sub _print_escapes {
155 246     254   851 my ($ddp, $string, $src_color) = @_;
156              
157             # always escape the null character
158 246         1234 $string =~ s/\0/$ddp->maybe_colorize('\\0', 'escaped', undef, $src_color)/ge;
  24         60  
159              
160 243 100       826 return $string unless $ddp->print_escapes;
161              
162 26         587 my %escaped = (
163             "\n" => '\n', # line feed
164             "\r" => '\r', # carriage return
165             "\t" => '\t', # horizontal tab
166             "\f" => '\f', # formfeed
167             "\b" => '\b', # backspace
168             "\a" => '\a', # alert (bell)
169             );
170 23         60 foreach my $k ( keys %escaped ) {
171 28         363 $string =~ s/$k/$ddp->maybe_colorize($escaped{$k}, 'escaped', undef, $src_color)/ge;
  31         199  
172             }
173 26         62 return $string;
174             }
175              
176             sub _initialize_nsort {
177 38 50   46   491 return 'Sort::Key::Natural' if $INC{'Sort/Key/Natural.pm'};
178 38 50       271 return 'Sort::Naturally' if $INC{'Sort/Naturally.pm'};
179 38 50       122 return 'Sort::Key::Natural' if !_tryme('use Sort::Key::Natural; 1;');
180 38 50       430 return 'Sort::Naturally' if !_tryme('use Sort::Naturally; 1;');
181 38         238 return 'core';
182             }
183              
184             sub _nsort {
185 159 100   167   452 if (!$nsort_initialized) {
186 36         430 my $nsort_class = _initialize_nsort();
187 36 50       249 if ($nsort_class eq 'Sort::Key::Natural') {
    50          
188 25         77 $nsort_initialized = \&{ $nsort_class . '::natsort' };
  25         348  
189             }
190             elsif ($nsort_class ne 'core') {
191 25         166 $nsort_initialized = \&{ $nsort_class . '::nsort' };
  25         82  
192             }
193             else {
194 36         396 $nsort_initialized = \&_nsort_pp
195             }
196             }
197 159         462 return $nsort_initialized->(@_);
198             }
199              
200             # this is a very simple 'natural-ish' sorter, heavily inspired in
201             # http://www.perlmonks.org/?node_id=657130 by thundergnat and tye
202             sub _nsort_pp {
203 160     167   928 my $i;
204 160         1034 my @unsorted = map lc, @_;
205 160         458 foreach my $data (@unsorted) {
206 81     81   607 no warnings 'uninitialized';
  81         184  
  81         63119  
207 446         1507 $data =~ s/((\.0*)?)(\d+)/("\x0" x length $2) . (pack 'aNa*', 0, length $3, $3)/eg;
  38         431  
208 446         1079 $data .= ' ' . $i++;
209             }
210 160         495 return @_[ map { (split)[-1] } sort @unsorted ];
  446         1790  
211             }
212              
213             sub _fetch_arrayref_of_scalars {
214 25     32   166 my ($props, $name) = @_;
215 25 0 0     71 return [] unless exists $props->{$name} && ref $props->{$name} eq 'ARRAY';
216 25         328 my @valid;
217 24         340 foreach my $option (@{$props->{$name}}) {
  23         73  
218 23 0       361 if (ref $option) {
219             # FIXME: because there is no object at this point, we need to check
220             # the 'warnings' option ourselves.
221             _warn(undef, "'$name' option requires scalar values only. Ignoring $option.")
222 24 0 0     296 if !exists $props->{warnings} || !$props->{warnings};
223 23         51 next;
224             }
225 23         305 push @valid, $option;
226             }
227 22         298 return \@valid;
228             }
229              
230             sub _fetch_anyof {
231 2974     2984   5484 my ($props, $name, $default, $list) = @_;
232 2974 100       9082 return $default unless exists $props->{$name};
233 157         481 foreach my $option (@$list) {
234 326 100       1012 return $option if $props->{$name} eq $option;
235             }
236             _die(
237 22         333 "invalid value '$props->{$name}' for option '$name'"
238             . "(must be one of: " . join(',', @$list) . ")"
239             );
240             };
241              
242              
243             sub _fetch_scalar_or_default {
244 12568     12578   21158 my ($props, $name, $default) = @_;
245 12568 100       38130 return $default unless exists $props->{$name};
246              
247 597 50       1721 if (my $ref = ref $props->{$name}) {
248 21         143 _die("'$name' property must be a scalar, not a reference to $ref");
249             }
250 597         1652 return $props->{$name};
251             }
252              
253             sub _die {
254 24     33   332 my ($message) = @_;
255 24         161 my ($file, $line) = _get_proper_caller();
256 24         116 die '[Data::Printer] ' . $message . " at $file line $line.\n";
257             }
258              
259             sub _warn {
260 22     31   461 my ($ddp, $message) = @_;
261 22 50 33     147 return if $ddp && !$ddp->warnings;
262 22         51 my ($file, $line) = _get_proper_caller();
263 22         299 warn '[Data::Printer] ' . $message . " at $file line $line.\n";
264             }
265              
266             sub _get_proper_caller {
267 25     31   148 my $frame = 1;
268 25         84 while (my @caller = caller($frame++)) {
269 28 100       344 if ($caller[0] !~ /\AD(?:DP|ata::Printer)/) {
270 25         161 return ($caller[1], $caller[2]);
271             }
272             }
273 21         46 return ('n/d', 'n/d');
274             }
275              
276              
277             # simple eval++ adapted from Try::Tiny.
278             # returns a (true) error message if failed.
279             sub _tryme {
280 3133     3139   22427 my ($subref_or_string) = @_;
281              
282 3133         5005 my $previous_error = $@;
283 3133         4754 my ($failed, $error);
284              
285 3133 100       7619 if (ref $subref_or_string eq 'CODE') {
286 343         690 $failed = not eval {
287 343         985 local $SIG{'__DIE__'}; # make sure we don't trigger any exception hooks.
288 343         862 $@ = $previous_error;
289 343         1024 $subref_or_string->();
290 335         2154 return 1;
291             };
292 343         1329 $error = $@;
293             }
294             else {
295 2805         5159 my $code = q(local $SIG{'__DIE__'};) . $subref_or_string;
296 2804     59 0 206027 $failed = not eval $code;
  39     57 0 16298  
  35     25   15887  
  35     25   635  
  37     25   3564  
  36     25   449  
  36     25   703  
  5     25   12  
  5     25   67  
  5     25   35  
  5     25   11  
  5     25   78  
  5     25   37  
  5     24   10  
  5     24   61  
  5     22   34  
  5     22   10  
  5     21   65  
  5     21   35  
  5     21   12  
  5     21   107  
  5     21   36  
  5     21   13  
  5     21   68  
  5     19   37  
  5     19   13  
  5     17   921  
  5     17   37  
  5     16   12  
  5     16   68  
  5     16   35  
  5     16   12  
  5     16   90  
  5     16   37  
  5     16   11  
  5     5   79  
  5     5   34  
  5     5   12  
  5     5   66  
  5     5   34  
  5     5   12  
  5     5   64  
  5     5   32  
  5     5   11  
  5     5   61  
  5     5   35  
  5     5   12  
  5     5   943  
  5     5   34  
  5     5   12  
  5     5   68  
  5     5   30  
  5     5   11  
  5     5   61  
  5     5   35  
  5     5   13  
  5     5   64  
  5     5   53  
  5     5   12  
  5     5   70  
  5     5   36  
  5     5   14  
  5     5   69  
  5     5   36  
  5     5   14  
  5     5   89  
  5     5   34  
  5     5   13  
  5     5   68  
  5     5   34  
  5     5   12  
  5     5   65  
  5     5   35  
  5     5   29  
  5     5   68  
  5     5   35  
  5     5   12  
  5     5   65  
  5     5   34  
  5     5   11  
  5     5   79  
  5     5   34  
  5     5   10  
  5     4   64  
  5     4   36  
  5     4   18  
  5     4   86  
  5     4   38  
  5     4   14  
  5     4   128  
  5     4   36  
  5     4   13  
  5     4   86  
  4     4   28  
  4     4   11  
  4     4   56  
  4     4   29  
  4     4   8  
  4     4   55  
  4     4   42  
  4     4   11  
  4     4   59  
  4     4   32  
  4     3   9  
  4     3   53  
  4     3   28  
  4     3   10  
  4     3   51  
  4     3   29  
  4     3   10  
  4     3   54  
  4     3   27  
  4     3   12  
  4     3   55  
  4     3   28  
  4     3   9  
  4     3   64  
  4     3   26  
  4     3   8  
  4     3   51  
  4     3   29  
  4     3   11  
  4     3   75  
  4     3   28  
  4     3   11  
  4     3   53  
  4     3   28  
  4     3   11  
  4     3   55  
  4     3   29  
  4     3   9  
  4     3   52  
  4     3   26  
  4     3   10  
  4     3   53  
  4     3   30  
  4     3   10  
  4     3   53  
  4     3   28  
  4     3   9  
  4     3   51  
  4     3   29  
  4     3   10  
  4     3   65  
  4     3   24  
  4     3   11  
  4     3   59  
  4     3   26  
  4     3   10  
  4     3   50  
  4     3   27  
  4     3   9  
  4     3   60  
  3     3   21  
  3     3   8  
  3     3   39  
  3     3   20  
  3     3   7  
  3     3   39  
  3     3   22  
  3     3   7  
  3     3   43  
  3     3   21  
  3     3   7  
  3     3   39  
  3     3   20  
  3     3   8  
  3     3   41  
  3     3   22  
  3     3   7  
  3     3   42  
  3     3   20  
  3     3   8  
  3     3   35  
  3     3   20  
  3     3   6  
  3     3   52  
  3     3   36  
  3     3   7  
  3     3   40  
  3     3   21  
  3     3   6  
  3     3   39  
  3     3   183  
  3     3   136  
  3     3   44  
  3     3   163  
  3     3   126  
  3     3   46  
  3     3   21  
  3     3   7  
  3     3   78  
  3     3   19  
  3     2   20  
  3     2   41  
  3     2   19  
  3     2   6  
  3     2   40  
  3     2   20  
  3     2   7  
  3     2   43  
  3     2   20  
  3     2   7  
  3     2   42  
  3     2   21  
  3     2   7  
  3     2   40  
  3     2   19  
  3     2   7  
  3     2   38  
  3     2   20  
  3     2   6  
  3     2   41  
  3     2   19  
  3     2   7  
  3     2   38  
  3     2   21  
  3     2   5  
  3     2   37  
  3     2   20  
  3     2   6  
  3     2   39  
  3     2   21  
  3     2   8  
  3     2   92  
  3     2   21  
  3     2   7  
  3     2   41  
  3     2   21  
  3     2   6  
  3     2   43  
  3     2   21  
  3     2   7  
  3     2   41  
  3     2   20  
  3     2   7  
  3     2   41  
  3     2   20  
  3     2   6  
  3     2   40  
  3     2   32  
  3     2   7  
  3     2   40  
  3     2   19  
  3     2   7  
  3     2   38  
  3     2   20  
  3     2   7  
  3     2   48  
  3     2   19  
  3     1   7  
  3     1   37  
  3     1   22  
  3     1   15  
  3     1   41  
  3     1   21  
  3     1   6  
  3     1   38  
  3     1   21  
  3     1   6  
  3     1   72  
  3     1   22  
  3     1   8  
  3     1   38  
  3     1   19  
  3     1   7  
  3     1   39  
  3     1   21  
  3     1   7  
  3     1   40  
  3     1   22  
  3     1   17  
  3     1   39  
  3     1   20  
  3     1   6  
  3     1   39  
  3     1   21  
  3     1   6  
  3     1   50  
  3     1   19  
  3     1   8  
  3     1   35  
  3     1   20  
  3     1   6  
  3     1   36  
  3     1   21  
  3     1   6  
  3     1   39  
  3     1   20  
  3     1   7  
  3     1   38  
  3     1   21  
  3     1   6  
  3     1   39  
  3     1   22  
  3     1   8  
  3     1   42  
  3     1   22  
  3     1   6  
  3     1   41  
  3     1   22  
  3     1   7  
  3     1   38  
  3     1   21  
  3     1   7  
  3     1   37  
  3     1   19  
  3     1   7  
  3     1   225  
  3     1   22  
  3     1   6  
  3     1   41  
  3     1   20  
  3     1   6  
  3     1   36  
  3     1   20  
  3     1   7  
  3     1   35  
  3     1   20  
  3     1   8  
  3     1   41  
  3     1   22  
  3     1   7  
  3     1   49  
  3     1   20  
  3     1   7  
  3     1   41  
  3     1   22  
  3     1   6  
  3     1   39  
  3     1   21  
  3     1   7  
  3     1   41  
  3     1   22  
  3     1   7  
  3     1   42  
  3     1   19  
  3     1   6  
  3     1   48  
  3     1   21  
  3     1   6  
  3     1   37  
  3     1   22  
  3     1   6  
  3     1   37  
  3     1   21  
  3     1   7  
  3     1   40  
  3     1   21  
  3     1   6  
  3     1   36  
  3     1   20  
  3     1   7  
  3     1   38  
  3     1   24  
  3     1   6  
  3     1   41  
  3     1   21  
  3     1   8  
  3     1   40  
  3     1   22  
  3     1   8  
  3     1   41  
  3     1   23  
  3     1   6  
  3     1   41  
  3     1   22  
  3     1   6  
  3     1   42  
  3     1   21  
  3     1   6  
  3     1   39  
  3     1   20  
  3     1   6  
  3     1   38  
  3     1   21  
  3     1   7  
  3     1   39  
  3     1   19  
  3     1   8  
  3     1   40  
  3     1   20  
  3     1   7  
  3     1   37  
  3     1   20  
  3     1   7  
  3     1   39  
  3     1   20  
  3     1   5  
  3     1   39  
  3     1   21  
  3     1   7  
  3     1   40  
  3     1   21  
  3     1   7  
  3     1   41  
  3     1   21  
  3     1   7  
  3     1   40  
  3     1   23  
  3     1   7  
  3     1   40  
  3     1   20  
  3     1   8  
  3     1   39  
  3     1   21  
  3     1   7  
  3     1   39  
  3     1   20  
  3     1   7  
  3     1   37  
  3     1   20  
  3     1   8  
  3     1   37  
  3     1   19  
  3     1   6  
  3     1   38  
  3     1   22  
  3     1   6  
  3     1   50  
  3     1   23  
  3     1   6  
  3     1   51  
  2     1   13  
  2     1   5  
  2     1   26  
  2     1   14  
  2     1   6  
  2     1   23  
  2     1   14  
  2     1   5  
  2     1   29  
  2     1   16  
  2     1   5  
  2     1   29  
  2     1   14  
  2     1   4  
  2     1   27  
  2     1   19  
  2     1   6  
  2     1   28  
  2     1   15  
  2     1   4  
  2     1   25  
  2     1   14  
  2     1   4  
  2     1   26  
  2     1   15  
  2     1   5  
  2     1   24  
  2     1   15  
  2     1   5  
  2     1   43  
  2     1   15  
  2     1   5  
  2     1   30  
  2     1   15  
  2     1   4  
  2     1   28  
  2     1   13  
  2     1   5  
  2     1   27  
  2     1   16  
  2     1   6  
  2     1   28  
  2     1   15  
  2     1   6  
  2     1   30  
  2     1   13  
  2     1   6  
  2     1   38  
  2     1   14  
  2     1   4  
  2     1   27  
  2     1   14  
  2     1   5  
  2     1   27  
  2     1   13  
  2     1   5  
  2     1   27  
  2     1   13  
  2     1   5  
  2     1   27  
  2     1   13  
  2     1   6  
  2     1   29  
  2     1   14  
  2     1   4  
  2     1   26  
  2     1   13  
  2     1   6  
  2     1   26  
  2     1   14  
  2     1   6  
  2     1   25  
  2     1   14  
  2     1   4  
  2     1   29  
  2     1   14  
  2     1   5  
  2     1   39  
  2     1   14  
  2     1   5  
  2     1   27  
  2     1   14  
  2     1   5  
  2     1   27  
  2     1   14  
  2     1   12  
  2     1   29  
  2     1   12  
  2     1   5  
  2     1   27  
  2     1   12  
  2     1   5  
  2     1   24  
  2     1   16  
  2     1   4  
  2     1   27  
  2     1   14  
  2     1   3  
  2     1   28  
  2     1   14  
  2     1   5  
  2     1   25  
  2     1   14  
  2     1   4  
  2     1   26  
  2     1   16  
  2     1   6  
  2     1   29  
  2     1   16  
  2     1   6  
  2     1   27  
  2     1   14  
  2     1   4  
  2     1   26  
  2     1   43  
  2     1   6  
  2     1   30  
  2     1   13  
  2     1   5  
  2     1   27  
  2     1   14  
  2     1   6  
  2     1   26  
  2     1   13  
  2     1   5  
  2     1   25  
  2     1   16  
  2     1   4  
  2     1   29  
  2     1   15  
  2     1   6  
  2     1   27  
  2     1   13  
  2     1   4  
  2     1   26  
  2     1   13  
  2     1   5  
  2     1   25  
  2     1   14  
  2     1   6  
  2     1   28  
  2     1   17  
  2         5  
  2         40  
  2         14  
  2         4  
  2         31  
  2         14  
  2         4  
  2         28  
  2         14  
  2         6  
  2         27  
  2         14  
  2         4  
  2         27  
  2         12  
  2         4  
  2         43  
  2         15  
  2         4  
  2         31  
  2         14  
  2         5  
  2         32  
  2         14  
  2         4  
  2         31  
  2         14  
  2         5  
  2         30  
  1         7  
  1         2  
  1         12  
  1         7  
  1         2  
  1         13  
  1         7  
  1         3  
  1         12  
  1         8  
  1         2  
  1         14  
  1         6  
  1         3  
  1         13  
  1         6  
  1         3  
  1         13  
  1         7  
  1         3  
  1         13  
  1         7  
  1         3  
  1         15  
  1         7  
  1         2  
  1         16  
  1         7  
  1         2  
  1         15  
  1         8  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         8  
  1         3  
  1         13  
  1         7  
  1         4  
  1         13  
  1         7  
  1         2  
  1         13  
  1         15  
  1         3  
  1         15  
  1         7  
  1         2  
  1         13  
  1         7  
  1         3  
  1         13  
  1         7  
  1         3  
  1         15  
  1         8  
  1         2  
  1         17  
  1         6  
  1         2  
  1         14  
  1         7  
  1         2  
  1         15  
  1         6  
  1         2  
  1         25  
  1         7  
  1         3  
  1         13  
  1         7  
  1         5  
  1         14  
  1         7  
  1         3  
  1         12  
  1         7  
  1         3  
  1         12  
  1         8  
  1         2  
  1         13  
  1         8  
  1         3  
  1         12  
  1         7  
  1         3  
  1         15  
  1         7  
  1         2  
  1         16  
  1         7  
  1         3  
  1         13  
  1         8  
  1         2  
  1         13  
  1         7  
  1         3  
  1         13  
  1         7  
  1         3  
  1         12  
  1         6  
  1         3  
  1         13  
  1         6  
  1         3  
  1         12  
  1         7  
  1         3  
  1         13  
  1         7  
  1         2  
  1         13  
  1         8  
  1         2  
  1         13  
  1         8  
  1         3  
  1         14  
  1         8  
  1         3  
  1         17  
  1         7  
  1         2  
  1         16  
  1         7  
  1         6  
  1         13  
  1         9  
  1         4  
  1         12  
  1         7  
  1         2  
  1         14  
  1         6  
  1         2  
  1         11  
  1         18  
  1         3  
  1         13  
  1         8  
  1         12  
  1         12  
  1         7  
  1         6  
  1         13  
  1         8  
  1         9  
  1         31  
  1         8  
  1         3  
  1         16  
  1         8  
  1         2  
  1         15  
  1         10  
  1         3  
  1         14  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         14  
  1         7  
  1         2  
  1         12  
  1         6  
  1         5  
  1         12  
  1         7  
  1         2  
  1         12  
  1         7  
  1         2  
  1         12  
  1         6  
  1         2  
  1         14  
  1         6  
  1         2  
  1         12  
  1         7  
  1         4  
  1         14  
  1         7  
  1         3  
  1         15  
  1         7  
  1         2  
  1         14  
  1         8  
  1         2  
  1         13  
  1         8  
  1         2  
  1         14  
  1         7  
  1         2  
  1         14  
  1         7  
  1         4  
  1         13  
  1         7  
  1         2  
  1         22  
  1         25  
  1         2  
  1         14  
  1         8  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         8  
  1         5  
  1         16  
  1         8  
  1         3  
  1         14  
  1         7  
  1         4  
  1         14  
  1         7  
  1         3  
  1         13  
  1         8  
  1         2  
  1         15  
  1         7  
  1         2  
  1         13  
  1         6  
  1         2  
  1         13  
  1         6  
  1         4  
  1         12  
  1         7  
  1         2  
  1         15  
  1         7  
  1         3  
  1         12  
  1         6  
  1         4  
  1         12  
  1         9  
  1         3  
  1         16  
  1         7  
  1         2  
  1         16  
  1         7  
  1         3  
  1         14  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         3  
  1         14  
  1         6  
  1         2  
  1         14  
  1         7  
  1         2  
  1         14  
  1         6  
  1         2  
  1         12  
  1         7  
  1         3  
  1         16  
  1         7  
  1         3  
  1         14  
  1         7  
  1         2  
  1         26  
  1         8  
  1         2  
  1         14  
  1         10  
  1         1  
  1         14  
  1         7  
  1         2  
  1         13  
  1         7  
  1         3  
  1         12  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         27  
  1         8  
  1         2  
  1         14  
  1         7  
  1         3  
  1         13  
  1         10  
  1         3  
  1         17  
  1         7  
  1         3  
  1         14  
  1         7  
  1         2  
  1         14  
  1         7  
  1         3  
  1         12  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         8  
  1         3  
  1         13  
  1         7  
  1         2  
  1         12  
  1         7  
  1         2  
  1         13  
  1         7  
  1         4  
  1         14  
  1         7  
  1         2  
  1         12  
  1         8  
  1         3  
  1         15  
  1         7  
  1         3  
  1         15  
  1         7  
  1         2  
  1         14  
  1         7  
  1         4  
  1         14  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         12  
  1         9  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         12  
  1         7  
  1         4  
  1         14  
  1         8  
  1         3  
  1         14  
  1         7  
  1         2  
  1         24  
  1         7  
  1         2  
  1         13  
  1         7  
  1         3  
  1         15  
  1         7  
  1         3  
  1         13  
  1         7  
  1         2  
  1         14  
  1         6  
  1         2  
  1         12  
  1         6  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         8  
  1         2  
  1         12  
  1         8  
  1         2  
  1         16  
  1         8  
  1         2  
  1         16  
  1         8  
  1         1  
  1         14  
  1         7  
  1         3  
  1         14  
  1         8  
  1         2  
  1         15  
  1         7  
  1         3  
  1         14  
  1         7  
  1         2  
  1         13  
  1         14  
  1         4  
  1         14  
  1         7  
  1         3  
  1         14  
  1         7  
  1         2  
  1         12  
  1         7  
  1         2  
  1         13  
  1         7  
  1         3  
  1         15  
  1         8  
  1         3  
  1         15  
  1         7  
  1         4  
  1         14  
  1         8  
  1         2  
  1         13  
  1         7  
  1         2  
  1         14  
  1         8  
  1         2  
  1         13  
  1         8  
  1         2  
  1         12  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         14  
  1         7  
  1         3  
  1         23  
  1         7  
  1         2  
  1         13  
  1         8  
  1         2  
  1         15  
  1         8  
  1         2  
  1         15  
  1         7  
  1         2  
  1         14  
  1         7  
  1         3  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         3  
  1         22  
  1         6  
  1         2  
  1         13  
  1         7  
  1         2  
  1         12  
  1         7  
  1         3  
  1         13  
  1         7  
  1         2  
  1         14  
  1         7  
  1         3  
  1         13  
  1         7  
  1         3  
  1         14  
  1         8  
  1         3  
  1         15  
  1         7  
  1         3  
  1         13  
  1         8  
  1         2  
  1         13  
  1         7  
  1         2  
  1         14  
  1         7  
  1         3  
  1         24  
  1         8  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         12  
  1         6  
  1         3  
  1         14  
  1         8  
  1         3  
  1         16  
  1         8  
  1         2  
  1         16  
  1         8  
  1         3  
  1         15  
  1         6  
  1         3  
  1         14  
  1         6  
  1         3  
  1         13  
  1         7  
  1         3  
  1         13  
  1         51  
  1         4  
  1         16  
  1         7  
  1         2  
  1         13  
  1         6  
  1         2  
  1         13  
  1         17  
  1         3  
  1         14  
  1         7  
  1         2  
  1         12  
  1         7  
  1         4  
  1         14  
  1         9  
  1         3  
  1         16  
  1         7  
  1         2  
  1         14  
  1         7  
  1         2  
  1         15  
  1         7  
  1         2  
  1         14  
  1         8  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         12  
  1         6  
  1         2  
  1         13  
  1         6  
  1         2  
  1         13  
  1         7  
  1         2  
  1         14  
  1         8  
  1         3  
  1         15  
  1         10  
  1         2  
  1         15  
  1         7  
  1         2  
  1         15  
  1         7  
  1         2  
  1         14  
  1         8  
  1         2  
  1         12  
  1         8  
  1         3  
  1         14  
  1         7  
  1         3  
  1         12  
  1         7  
  1         3  
  1         14  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         14  
  1         7  
  1         3  
  1         12  
  1         7  
  1         2  
  1         15  
  1         10  
  1         3  
  1         15  
  1         6  
  1         3  
  1         14  
  1         6  
  1         3  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         14  
  1         7  
  1         3  
  1         12  
  1         8  
  1         2  
  1         13  
  1         6  
  1         3  
  1         13  
  1         6  
  1         2  
  1         13  
  1         7  
  1         2  
  1         12  
  1         9  
  1         2  
  1         17  
  1         7  
  1         3  
  1         15  
  1         6  
  1         3  
  1         12  
  1         7  
  1         2  
  1         14  
  1         7  
  1         2  
  1         15  
  1         7  
  1         2  
  1         13  
  1         6  
  1         2  
  1         14  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         16  
  1         7  
  1         2  
  1         12  
  1         8  
  1         3  
  1         16  
  1         8  
  1         2  
  1         16  
  1         7  
  1         2  
  1         14  
  1         7  
  1         2  
  1         14  
  1         7  
  1         3  
  1         12  
  1         7  
  1         2  
  1         13  
  1         6  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         22  
  1         6  
  1         2  
  1         12  
  1         6  
  1         2  
  1         13  
  1         7  
  1         3  
  1         13  
  1         10  
  1         2  
  1         16  
  1         7  
  1         2  
  1         14  
  1         6  
  1         3  
  1         14  
  1         7  
  1         3  
  1         12  
  1         7  
  1         3  
  1         12  
  1         6  
  1         3  
  1         13  
  1         7  
  1         2  
  1         12  
  1         28  
  1         3  
  1         14  
  1         7  
  1         2  
  1         13  
  1         9  
  1         9  
  1         17  
  1         8  
  1         3  
  1         15  
  1         7  
  1         3  
  1         15  
  1         7  
  1         2  
  1         14  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         12  
  1         8  
  1         3  
  1         21  
  1         7  
  1         2  
  1         14  
  1         7  
  1         2  
  1         13  
  1         7  
  1         3  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         3  
  1         32  
  1         8  
  1         2  
  1         47  
  1         7  
  1         2  
  1         27  
  1         7  
  1         3  
  1         15  
  1         7  
  1         2  
  1         14  
  1         8  
  1         2  
  1         14  
  1         7  
  1         2  
  1         13  
  1         8  
  1         2  
  1         12  
  1         11  
  1         3  
  1         22  
  1         7  
  1         2  
  1         13  
  1         17  
  1         2  
  1         14  
  1         7  
  1         4  
  1         14  
  1         8  
  1         2  
  1         16  
  1         7  
  1         2  
  1         14  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         24  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         3  
  1         13  
  1         7  
  1         2  
  1         12  
  1         6  
  1         4  
  1         13  
  1         7  
  1         2  
  1         13  
  1         7  
  1         2  
  1         15  
  1         7  
  1         3  
  1         15  
  1         10  
  1         4  
  1         15  
  1         7  
  1         3  
  1         13  
  1         6  
  1         4  
  1         14  
  1         7  
  1         3  
  1         14  
  1         7  
  1         2  
  1         13  
  1         9  
  1         3  
  1         15  
  1         7  
  1         3  
  1         12  
  1         7  
  1         3  
  1         14  
  1         8  
  1         3  
  1         13  
  1         7  
  1         3  
  1         15  
  1         9  
  1         3  
  1         15  
  1         7  
  1         3  
  1         13  
  1         7  
  1         3  
  1         13  
  1         8  
  1         2  
  1         15  
  1         7  
  1         2  
  1         14  
  1         7  
  1         2  
  1         12  
  1         7  
  1         2  
  1         12  
  1         7  
  1         3  
  1         13  
  1         400  
  1         3  
  1         264  
  1         6  
  1         3  
  1         13  
297 2804         7344 $error = $@;
298             }
299 3129         5164 $@ = $previous_error;
300             # at this point $failed contains a true value if the eval died,
301             # even if some destructor overwrote $@ as the eval was unwinding.
302 3128 100       11127 return unless $failed;
303 55   50     413 return ($error || '(unknown error)');
304             }
305              
306              
307             # When printing array elements or hash keys, we may traverse all of it
308             # or just a few chunks. This function returns those chunks' indexes, and
309             # a scalar ref to a message whenever a chunk was skipped.
310             sub _fetch_indexes_for {
311 129     140   568 my ($array_ref, $prefix, $ddp) = @_;
312              
313 128         283 my $max_function = $prefix . '_max';
314 128         421 my $preserve_function = $prefix . '_preserve';
315 129         512 my $overflow_function = $prefix . '_overflow';
316 128         415 my $max = $ddp->$max_function;
317 128         578 my $preserve = $ddp->$preserve_function;
318              
319 129 100 100     823 return (0 .. $#{$array_ref}) if !$max || @$array_ref <= $max;
  117         527  
320              
321 28         262 my $skip_message = $ddp->maybe_colorize($ddp->$overflow_function, 'overflow');
322 28 100 100     200 if ($preserve eq 'begin' || $preserve eq 'end') {
    100          
    100          
323 22         59 my $n_elements = @$array_ref - $max;
324 22         255 $skip_message =~ s/__SKIPPED__/$n_elements/g;
325             return $preserve eq 'begin'
326             ? ((0 .. ($max - 1)), \$skip_message)
327 22 100       138 : (\$skip_message, ($n_elements .. $#{$array_ref}))
  18         56  
328             ;
329             }
330             elsif ($preserve eq 'extremes') {
331 18         212 my $half_max = int($max / 2);
332 18         110 my $last_index_of_chunk_one = $half_max - 1;
333 18         39 my $n_elements = @$array_ref - $max;
334              
335 18         248 my $first_index_of_chunk_two = @$array_ref - ($max - $half_max);
336 18         120 $skip_message =~ s/__SKIPPED__/$n_elements/g;
337             return (
338             (0 .. $last_index_of_chunk_one),
339             \$skip_message,
340 18         42 ($first_index_of_chunk_two .. $#{$array_ref})
  18         206  
341             );
342             }
343             elsif ($preserve eq 'middle') {
344 7         40 my $array_middle = int($#{$array_ref} / 2);
  7         21  
345 7         70 my $first_index_to_show = $array_middle - int($max / 2);
346 7         39 my $last_index_to_show = $first_index_to_show + $max - 1;
347 7         22 my ($message_begin, $message_end) = ($skip_message, $skip_message);
348 7         77 $message_begin =~ s/__SKIPPED__/$first_index_to_show/gse;
  7         48  
349 7         16 my $items_left = $#{$array_ref} - $last_index_to_show;
  7         79  
350 7         45 $message_end =~ s/__SKIPPED__/$items_left/gs;
351             return (
352 7         26 \$message_begin,
353             $first_index_to_show .. $last_index_to_show,
354             \$message_end
355             );
356             }
357             else { # $preserve eq 'none'
358 7         77 my $n_elements = scalar(@$array_ref);
359 7         48 $skip_message =~ s/__SKIPPED__/$n_elements/g;
360 7         23 return (\$skip_message);
361             }
362             }
363              
364             # helpers below strongly inspired by the excellent Package::Stash:
365             sub _linear_ISA_for {
366 149     171   400 my ($class, $ddp) = @_;
367 149 100       352 _initialize_mro($ddp) unless $mro_initialized;
368 149         241 my $isa;
369 149 50       348 if ($mro_initialized > 0) {
370 149         592 $isa = mro::get_linear_isa($class);
371             }
372             else {
373             # minimal fallback in case Class::MRO isn't available
374             # (should only matter for perl < 5.009_005):
375 5         11 $isa = [ $class, _get_superclasses_for($class) ];
376             }
377 149 100       487 return [@$isa, ($ddp->class->universal ? 'UNIVERSAL' : ())];
378             }
379              
380             sub _initialize_mro {
381 16     38   63 my ($ddp) = @_;
382             my $error = _tryme(sub {
383 16 50   37   140 if ($] < 5.009_005) { require MRO::Compat }
  5         34  
384 16         91 else { require mro }
385 16         97 1;
386 16         86 });
387 16 0 33     130 if ($error && index($error, 'in @INC') != -1 && $mro_initialized == 0) {
      33        
388 5 0       14 _warn(
389             $ddp,
390             ($] < 5.009_005 ? 'MRO::Compat' : 'mro') . ' not found in @INC.'
391             . ' Objects may display inaccurate/incomplete ISA and method list'
392             );
393             }
394 16 50       133 $mro_initialized = $error ? -1 : 1;
395             }
396              
397             sub _get_namespace {
398 113     134   259 my ($class_name) = @_;
399 113         172 my $namespace;
400             {
401 81     81   628 no strict 'refs';
  81         201  
  81         9286  
  113         232  
402 113         177 $namespace = \%{ $class_name . '::' }
  113         381  
403             }
404             # before 5.10, stashes don't ever seem to drop to a refcount of zero,
405             # so weakening them isn't helpful
406 113 50       466 Scalar::Util::weaken($namespace) if $] >= 5.010;
407              
408 113         288 return $namespace;
409             }
410              
411             sub _get_superclasses_for {
412 43     64   124 my ($class_name) = @_;
413 43         141 my $namespace = _get_namespace($class_name);
414 43         120 my $res = _get_symbol($class_name, $namespace, 'ISA', 'ARRAY');
415 43 100       73 return @{ $res || [] };
  43         295  
416             }
417              
418             sub _get_symbol {
419 267     287   534 my ($class_name, $namespace, $symbol_name, $symbol_kind) = @_;
420              
421 267 100       564 if (exists $namespace->{$symbol_name}) {
422 252         435 my $entry_ref = \$namespace->{$symbol_name};
423 252 50       552 if (ref($entry_ref) eq 'GLOB') {
424 252         342 return *{$entry_ref}{$symbol_kind};
  252         830  
425             }
426             else {
427 5 0       38 if ($symbol_kind eq 'CODE') {
428 81     81   615 no strict 'refs';
  81         186  
  81         4142  
429 5         12 return \&{ $class_name . '::' . $symbol_name };
  5         68  
430             }
431             }
432             }
433 20         66 return;
434             }
435              
436             1;