File Coverage

blib/lib/Data/Printer/Object.pm
Criterion Covered Total %
statement 363 412 88.1
branch 114 172 66.2
condition 54 101 53.4
subroutine 62 64 96.8
pod 15 15 100.0
total 608 764 79.5


line stmt bran cond sub pod time code
1 34     34   1465556 use strict;
  34         295  
  34         1010  
2 34     34   187 use warnings;
  34         86  
  34         947  
3 34     34   9692 use Data::Printer::Common;
  34         83  
  34         17340  
4              
5             package # hide from pause
6             Data::Printer::Object::ClassOptions;
7 23     23   177 sub parents { $_[0]->{'parents'} }
8 109     109   455 sub linear_isa { $_[0]->{'linear_isa'} }
9 144     144   574 sub universal { $_[0]->{'universal'} }
10 90     90   399 sub expand { $_[0]->{'expand'} }
11 51     51   276 sub stringify { $_[0]->{'stringify'} }
12 46     46   116 sub show_reftype { $_[0]->{'show_reftype'} }
13 38     38   123 sub show_overloads { $_[0]->{'show_overloads'} }
14 113     113   307 sub show_methods { $_[0]->{'show_methods'} }
15 68     68   309 sub sort_methods { $_[0]->{'sort_methods'} }
16 0     0   0 sub show_wrapped { $_[0]->{'show_wrapped'} }
17 37     37   77 sub inherited { $_[0]->{'inherited'} }
18 71     71   190 sub format_inheritance { $_[0]->{'format_inheritance'} }
19 94     94   263 sub parent_filters { $_[0]->{'parent_filters'} }
20 46     46   101 sub internals { $_[0]->{'internals'} }
21             sub new {
22 246     246   813 my ($class, $params) = @_;
23 246         626 my $self = {
24             'linear_isa' => Data::Printer::Common::_fetch_scalar_or_default($params, 'linear_isa', 'auto'),
25             'show_reftype' => Data::Printer::Common::_fetch_scalar_or_default($params, 'show_reftype', 0),
26             'show_overloads' => Data::Printer::Common::_fetch_scalar_or_default($params, 'show_overloads', 1),
27             'stringify' => Data::Printer::Common::_fetch_scalar_or_default($params, 'stringify', 1),
28             'expand' => Data::Printer::Common::_fetch_scalar_or_default($params, 'expand', 1),
29             'show_methods' => Data::Printer::Common::_fetch_anyof(
30             $params, 'show_methods', 'all', [qw(none all private public)]
31             ),
32             'inherited' => Data::Printer::Common::_fetch_anyof(
33             $params, 'inherited', 'public', [qw(none all private public)]
34             ),
35             'format_inheritance' => Data::Printer::Common::_fetch_anyof(
36             $params, 'format_inheritance', 'lines', [qw(string lines)]
37             ),
38             'parent_filters' => Data::Printer::Common::_fetch_scalar_or_default($params, 'parent_filters', 1),
39             'universal' => Data::Printer::Common::_fetch_scalar_or_default($params, 'universal', 0),
40             'sort_methods' => Data::Printer::Common::_fetch_scalar_or_default($params, 'sort_methods', 1),
41             'show_wrapped' => Data::Printer::Common::_fetch_scalar_or_default($params, 'show_wrapped', 1),
42             'internals' => Data::Printer::Common::_fetch_scalar_or_default($params, 'internals', 1),
43             'parents' => Data::Printer::Common::_fetch_scalar_or_default($params, 'parents', 1),
44             };
45 246         1095 return bless $self, $class;
46             }
47             1;
48              
49             package Data::Printer::Object;
50 34     34   276 use Scalar::Util ();
  34         81  
  34         832  
51 34     34   15412 use Data::Printer::Theme;
  34         88  
  34         1165  
52 34     34   13953 use Data::Printer::Filter::SCALAR; # also implements LVALUE
  34         92  
  34         1174  
53 34     34   14688 use Data::Printer::Filter::ARRAY;
  34         92  
  34         1098  
54 34     34   14271 use Data::Printer::Filter::HASH;
  34         88  
  34         1155  
55 34     34   13813 use Data::Printer::Filter::REF;
  34         121  
  34         1100  
56 34     34   13605 use Data::Printer::Filter::VSTRING;
  34         86  
  34         1148  
57 34     34   14246 use Data::Printer::Filter::GLOB;
  34         89  
  34         1091  
58 34     34   13075 use Data::Printer::Filter::FORMAT;
  34         89  
  34         1001  
59 34     34   13310 use Data::Printer::Filter::Regexp;
  34         87  
  34         1038  
60 34     34   14252 use Data::Printer::Filter::CODE;
  34         93  
  34         1082  
61 34     34   15090 use Data::Printer::Filter::GenericClass;
  34         98  
  34         2760  
62              
63             # create our basic accessors:
64             my @method_names =qw(
65             name show_tainted show_unicode show_readonly show_lvalue show_refcount
66             show_memsize memsize_unit print_escapes scalar_quotes escape_chars
67             caller_info caller_message caller_message_newline caller_message_position
68             string_max string_overflow string_preserve resolve_scalar_refs
69             array_max array_overflow array_preserve hash_max hash_overflow
70             hash_preserve unicode_charnames colored theme show_weak
71             max_depth index separator end_separator class_method class hash_separator
72             align_hash sort_keys quote_keys deparse return_value show_dualvar show_tied
73             warnings arrows coderef_stub coderef_undefined
74             );
75             foreach my $method_name (@method_names) {
76 34     34   266 no strict 'refs';
  34         77  
  34         159057  
77             *{__PACKAGE__ . "::$method_name"} = sub {
78 10266 100   10266   21113 $_[0]->{$method_name} = $_[1] if @_ > 1;
79 10266         36391 return $_[0]->{$method_name};
80             }
81             }
82 175     175 1 501 sub extra_config { $_[0]->{extra_config} }
83              
84 33     33 1 146 sub current_depth { $_[0]->{_depth} }
85 240     240 1 530 sub indent { $_[0]->{_depth}++ }
86 239     239 1 557 sub outdent { $_[0]->{_depth}-- }
87              
88             sub newline {
89 666     666 1 1138 my ($self) = @_;
90             return $self->{_linebreak}
91             . (' ' x ($self->{_depth} * $self->{_current_indent}))
92             . (' ' x $self->{_array_padding})
93 666         2939 ;
94             }
95              
96             sub current_name {
97 1532     1532 1 2700 my ($self, $new_value) = @_;
98 1532 100       2769 if (defined $new_value) {
99 598         941 $self->{_current_name} = $new_value;
100             }
101             else {
102 934 100       2181 $self->{_current_name} = $self->name unless defined $self->{_current_name};
103             }
104 1532         3630 return $self->{_current_name};
105             }
106              
107             sub _init {
108 246     246   446 my $self = shift;
109 246 100       972 my $props = { @_ == 1 ? %{$_[0]} : @_ };
  64         366  
110              
111 246         784 $self->{'_linebreak'} = "\n";
112 246         488 $self->{'_depth'} = 0;
113 246         457 $self->{'_position'} = 0; # depth is for indentation only!
114 246         556 $self->{'_array_padding'} = 0;
115 246         678 $self->{'_seen'} = {};
116 246         461 $self->{_refcount_base} = 3;
117 246         917 $self->{'warnings'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'warning', 1);
118 246         650 $self->{'indent'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'indent', 4);
119 246         665 $self->{'index'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'index', 1);
120 246         625 $self->{'name'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'name', 'var');
121 246         895 $self->{'arrows'} = Data::Printer::Common::_fetch_anyof(
122             $props,
123             'arrows',
124             'none',
125             [qw(none first all)]
126             );
127              
128 246         749 $self->{'show_tainted'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'show_tainted', 1);
129 246         589 $self->{'show_tied'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'show_tied', 1);
130 246         581 $self->{'show_weak'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'show_weak', 1);
131 246         577 $self->{'show_unicode'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'show_unicode', 0);
132 246         610 $self->{'show_readonly'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'show_readonly', 1);
133 246         620 $self->{'show_lvalue'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'show_lvalue', 1);
134 246         594 $self->{'show_refcount'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'show_refcount', 0);
135 246         576 $self->{'show_memsize'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'show_memsize', 0);
136 246         1400 $self->{'memsize_unit'} = Data::Printer::Common::_fetch_anyof(
137             $props,
138             'memsize_unit',
139             'auto',
140             [qw(auto b k m)]
141             );
142 246         669 $self->{'print_escapes'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'print_escapes', 0);
143 246         593 $self->{'scalar_quotes'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'scalar_quotes', q("));
144 246         932 $self->{'escape_chars'} = Data::Printer::Common::_fetch_anyof(
145             $props,
146             'escape_chars',
147             'none',
148             [qw(none nonascii nonlatin1 all)]
149             );
150 246         654 $self->{'caller_info'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'caller_info', 0);
151 246         565 $self->{'caller_message'} = Data::Printer::Common::_fetch_scalar_or_default(
152             $props,
153             'caller_message',
154             'Printing in line __LINE__ of __FILENAME__:'
155             );
156 246         578 $self->{'caller_message_newline'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'caller_message_newline', 1);
157 246         711 $self->{'caller_message_position'} = Data::Printer::Common::_fetch_anyof($props, 'caller_message_position', 'before', [qw(before after)]);
158 246         644 $self->{'resolve_scalar_refs'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'resolve_scalar_refs', 0);
159 246         587 $self->{'string_max'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'string_max', 4096);
160 246         828 $self->{'string_preserve'} = Data::Printer::Common::_fetch_anyof(
161             $props,
162             'string_preserve',
163             'begin',
164             [qw(begin end middle extremes none)]
165             );
166 246         655 $self->{'string_overflow'} = Data::Printer::Common::_fetch_scalar_or_default(
167             $props,
168             'string_overflow',
169             '(...skipping __SKIPPED__ chars...)'
170             );
171 246         554 $self->{'array_max'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'array_max', 100);
172 246         894 $self->{'array_preserve'} = Data::Printer::Common::_fetch_anyof(
173             $props,
174             'array_preserve',
175             'begin',
176             [qw(begin end middle extremes none)]
177             );
178 246         692 $self->{'array_overflow'} = Data::Printer::Common::_fetch_scalar_or_default(
179             $props,
180             'array_overflow',
181             '(...skipping __SKIPPED__ items...)'
182             );
183 246         575 $self->{'hash_max'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'hash_max', 100);
184 246         807 $self->{'hash_preserve'} = Data::Printer::Common::_fetch_anyof(
185             $props,
186             'hash_preserve',
187             'begin',
188             [qw(begin end middle extremes none)]
189             );
190 246         630 $self->{'hash_overflow'} = Data::Printer::Common::_fetch_scalar_or_default(
191             $props,
192             'hash_overflow',
193             '(...skipping __SKIPPED__ keys...)'
194             );
195 246         573 $self->{'unicode_charnames'} = Data::Printer::Common::_fetch_scalar_or_default(
196             $props,
197             'unicode_charnames',
198             0
199             );
200 246         584 $self->{'colored'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'colored', 'auto');
201 246         602 $self->{'max_depth'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'max_depth', 0);
202 246         560 $self->{'separator'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'separator', ',');
203 246         569 $self->{'end_separator'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'end_separator', 0);
204 246         603 $self->{'class_method'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'class_method', '_data_printer');
205 246         1385 $self->{'class'} = Data::Printer::Object::ClassOptions->new($props->{'class'});
206 246         739 $self->{'hash_separator'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'hash_separator', ' ');
207 246         617 $self->{'align_hash'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'align_hash', 1);
208 246         571 $self->{'sort_keys'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'sort_keys', 1);
209 246         559 $self->{'quote_keys'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'quote_keys', 'auto');
210 246         599 $self->{'deparse'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'deparse', 0);
211 246         587 $self->{'coderef_stub'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'coderef_stub', 'sub { ... }');
212 246         570 $self->{'coderef_undefined'} = Data::Printer::Common::_fetch_scalar_or_default($props, 'coderef_undefined', '');
213 246         744 $self->{'return_value'} = Data::Printer::Common::_fetch_anyof(
214             $props,
215             'return_value',
216             'pass',
217             [qw(pass dump void)]
218             );
219 246         848 $self->{'show_dualvar'} = Data::Printer::Common::_fetch_anyof(
220             $props,
221             'show_dualvar',
222             'lax',
223             [qw(lax strict off)]
224             );
225              
226 246 100       782 if (exists $props->{as}) {
227 1         3 my $msg = Data::Printer::Common::_fetch_scalar_or_default($props, 'as', '');
228 1         3 $self->{caller_info} = 1;
229 1         2 $self->{caller_message} = $msg;
230             }
231              
232             $self->multiline(
233 246         608 Data::Printer::Common::_fetch_scalar_or_default($props, 'multiline', 1)
234             );
235              
236 246         651 $self->fulldump(
237             Data::Printer::Common::_fetch_scalar_or_default($props, 'fulldump', 0)
238             );
239              
240 246 100       951 $self->output(defined $props->{output} ? $props->{output} : 'stderr');
241 246         758 $self->_load_colors($props);
242 246         795 $self->_load_filters($props);
243              
244 246         392 my %extra_config;
245 246         683 my %core_options = map { $_ => 1 }
  12792         22784  
246             (@method_names, qw(as multiline output colors filters));
247 246         1351 foreach my $key (keys %$props) {
248 765 100       1780 $extra_config{$key} = $props->{$key} unless exists $core_options{$key};
249             }
250 246         647 $self->{extra_config} = \%extra_config;
251              
252 246         4027 return $self;
253             }
254              
255             sub output {
256 250     250 1 517 my ($self, $new_output) = @_;
257 250 100       1035 if (@_ > 1) {
258 246         616 $self->_load_output_handle($new_output);
259             }
260 250         476 return $self->{output};
261             }
262              
263             sub _load_output_handle {
264 246     246   488 my ($self, $output) = @_;
265 246         1336 my %targets = ( stdout => *STDOUT, stderr => *STDERR );
266 246         432 my $error;
267 246         449 my $ref = ref $output;
268 246 100 100     1470 if (!$ref and exists $targets{ lc $output }) {
    100 100        
    50 100        
      66        
      66        
269 241         668 $self->{output} = lc $output;
270 241         723 $self->{output_handle} = $targets{ $self->{output} };
271             }
272             elsif ( ( $ref and $ref eq 'GLOB')
273             or (!$ref and \$output =~ /GLOB\([^()]+\)$/)
274             ) {
275 3         10 $self->{output} = 'handle';
276 3         10 $self->{output_handle} = $output;
277             }
278             elsif (!$ref or $ref eq 'SCALAR') {
279 2 50   1   78 if (open my $fh, '>>', $output) {
  1         8  
  1         3  
  1         7  
280 2         959 $self->{output} = 'file';
281 2         10 $self->{output_handle} = $fh;
282             }
283             else {
284 0         0 $error = "file '$output': $!";
285             }
286             }
287             else {
288 0         0 $error = 'unknown output data';
289             }
290 246 50       594 if ($error) {
291 0         0 Data::Printer::Common::_warn($self, "error opening custom output handle: $error");
292 0         0 $self->{output_handle} = $targets{'stderr'}
293             }
294 246         735 return;
295             }
296              
297             sub new {
298 246     246 1 99487 my $class = shift;
299 246         821 my $self = bless {}, $class;
300 246         831 return $self->_init(@_);
301             }
302              
303             sub multiline {
304 314     314 1 690 my ($self, $value) = @_;
305 314 100       797 if (defined $value) {
306 246         614 $self->{multiline} = !!$value;
307 246 100       608 if ($value) {
308 209         436 $self->{_linebreak} = "\n";
309 209         425 $self->{_current_indent} = $self->{indent};
310             $self->index( $self->{_original_index} )
311 209 50       538 if exists $self->{_original_index};
312             $self->hash_separator( $self->{_original_separator} )
313 209 50       521 if exists $self->{_original_separator};
314             $self->array_overflow( $self->{_original_array_overflow} )
315 209 50       500 if exists $self->{_original_array_overflow};
316             $self->hash_overflow( $self->{_original_hash_overflow} )
317 209 50       542 if exists $self->{_original_hash_overflow};
318             $self->string_overflow( $self->{_original_string_overflow} )
319 209 50       527 if exists $self->{_original_string_overflow};
320             }
321             else {
322 37         85 $self->{_original_index} = $self->index;
323 37         94 $self->index(0);
324 37         87 $self->{_original_separator} = $self->hash_separator;
325 37         113 $self->hash_separator(':');
326 37         84 $self->{_original_array_overflow} = $self->array_overflow;
327 37         98 $self->array_overflow('(...)');
328 37         81 $self->{_original_hash_overflow} = $self->hash_overflow;
329 37         90 $self->hash_overflow('(...)');
330 37         85 $self->{_original_string_overflow} = $self->string_overflow;
331 37         92 $self->string_overflow('(...)');
332 37         66 $self->{_linebreak} = ' ';
333 37         90 $self->{_current_indent} = 0;
334             }
335             }
336 314         738 return $self->{multiline};
337             }
338              
339             sub fulldump {
340 246     246 1 509 my ($self, $value) = @_;
341 246 50       650 if (defined $value) {
342 246         541 $self->{fulldump} = !!$value;
343 246 50       573 if ($value) {
344 0         0 $self->{_original_string_max} = $self->string_max;
345 0         0 $self->string_max(0);
346 0         0 $self->{_original_array_max} = $self->array_max;
347 0         0 $self->array_max(0);
348 0         0 $self->{_original_hash_max} = $self->hash_max;
349 0         0 $self->hash_max(0);
350             }
351             else {
352             $self->string_max($self->{_original_string_max})
353 246 50       596 if exists $self->{_original_string_max};
354             $self->array_max($self->{_original_array_max})
355 246 50       590 if exists $self->{_original_array_max};
356             $self->hash_max($self->{_original_hash_max})
357 246 50       694 if exists $self->{_original_hash_max};
358             }
359             }
360             }
361              
362             sub _load_filters {
363 246     246   519 my ($self, $props) = @_;
364              
365             # load our core filters (LVALUE is under the 'SCALAR' filter module)
366 246         765 my @core_filters = qw(SCALAR ARRAY HASH REF VSTRING GLOB FORMAT Regexp CODE GenericClass);
367 246         498 foreach my $class (@core_filters) {
368 2460         5456 $self->_load_external_filter($class);
369             }
370 246         419 my @filters;
371             # load any custom filters provided by the user
372 246 100       676 if (exists $props->{filters}) {
373 39 50       154 if (ref $props->{filters} eq 'HASH') {
    50          
374 0         0 Data::Printer::Common::_warn(
375             $self,
376             'please update your code: filters => { ... } is now filters => [{ ... }]'
377             );
378 0         0 push @filters, $props->{filters};
379             }
380             elsif (ref $props->{filters} eq 'ARRAY') {
381 39         60 @filters = @{ $props->{filters} };
  39         91  
382             }
383             else {
384 0         0 Data::Printer::Common::_warn($self, 'filters must be an ARRAY reference');
385             }
386             }
387 246         519 foreach my $filter (@filters) {
388 41         117 my $filter_reftype = Scalar::Util::reftype($filter);
389 41 100       109 if (!defined $filter_reftype) {
    50          
390 26         54 $self->_load_external_filter($filter);
391             }
392             elsif ($filter_reftype eq 'HASH') {
393 15         51 foreach my $k (keys %$filter) {
394 47 50       103 if ($k eq '-external') {
395 0         0 Data::Printer::Common::_warn(
396             $self,
397             'please update your code: '
398             . 'filters => { -external => [qw(Foo Bar)}'
399             . ' is now filters => [qw(Foo Bar)]'
400             );
401 0         0 next;
402             }
403 47 50       122 if (Scalar::Util::reftype($filter->{$k}) eq 'CODE') {
404 47         100 my $type = Data::Printer::Common::_filter_category_for($k);
405 47         72 unshift @{ $self->{$type}{$k} }, $filter->{$k};
  47         172  
406             }
407             else {
408 0         0 Data::Printer::Common::_warn(
409             $self,
410             'hash filters must point to a CODE reference'
411             );
412             }
413             }
414             }
415             else {
416 0         0 Data::Printer::Common::_warn($self, 'filters must be a name or { type => sub {...} }');
417             }
418             }
419 246         732 return;
420             }
421              
422             sub _load_external_filter {
423 2486     2486   5197 my ($self, $class) = @_;
424 2486         5084 my $module = "Data::Printer::Filter::$class";
425 2486         7017 my $error = Data::Printer::Common::_tryme("use $module; 1;");
426 2486 50       5710 if ($error) {
427 0         0 Data::Printer::Common::_warn($self, "error loading filter '$class': $error");
428 0         0 return;
429             }
430 2486         8336 my $from_module = $module->_filter_list;
431 2486         7702 foreach my $kind (keys %$from_module) {
432 2486         3721 foreach my $name (keys %{$from_module->{$kind}}) {
  2486         5904  
433 2974         4200 unshift @{ $self->{$kind}{$name} }, @{ $from_module->{$kind}{$name} };
  2974         7259  
  2974         9127  
434             }
435             }
436 2486         5906 return;
437             }
438              
439             sub _detect_color_level {
440 246     246   482 my ($self) = @_;
441 246         607 my $colored = $self->colored;
442 246         387 my $color_level;
443              
444             # first we honour ANSI_COLORS_DISABLED, colored and writing to files
445 246 100 33     808 if ( !$colored
      66        
      66        
446             || ($colored eq 'auto'
447             && (exists $ENV{ANSI_COLORS_DISABLED}
448             || $self->output eq 'handle'
449             || $self->output eq 'file'
450             )
451             )
452             ) {
453 241         426 $color_level = 0;
454             }
455             else {
456             # NOTE: we could try `tput colors` but it may not give
457             # the proper result, so instead we do what most terminals
458             # currently do and rely on environment variables.
459 5 50 33     96 if ($ENV{COLORTERM} && $ENV{COLORTERM} eq 'truecolor') {
    50 33        
    50 33        
    50 33        
    50 33        
    0 33        
460 0         0 $color_level = 3;
461             }
462             elsif ($ENV{TERM_PROGRAM} && $ENV{TERM_PROGRAM} eq 'iTerm.app') {
463 0   0     0 my $major_version = substr($ENV{TERM_PROGRAM_VERSION} || '0', 0, 1);
464 0 0       0 $color_level = $major_version >= 3 ? 3 : 2;
465             }
466             elsif ($ENV{TERM_PROGRAM} && $ENV{TERM_PROGRAM} eq 'Apple_Terminal') {
467 0         0 $color_level= 2;
468             }
469             elsif ($ENV{TERM} && $ENV{TERM} =~ /\-256(?:color)?\z/i) {
470 0         0 $color_level = 2;
471             }
472             elsif ($ENV{TERM}
473             && ($ENV{TERM} =~ /\A(?:screen|xterm|vt100|rxvt)/i
474             || $ENV{TERM} =~ /color|ansi|cygwin|linux/i)
475             ) {
476 5         13 $color_level = 1;
477             }
478             elsif ($ENV{COLORTERM}) {
479 0         0 $color_level = 1;
480             }
481             else {
482 0 0       0 $color_level = $colored eq 'auto' ? 0 : 1;
483             }
484             }
485 246         738 return $color_level;
486             }
487              
488             sub _load_colors {
489 246     246   512 my ($self, $props) = @_;
490              
491 246         601 $self->{_output_color_level} = $self->_detect_color_level;
492              
493 246         436 my $theme_object;
494 246         456 my $default_theme = 'Material';
495 246         781 my $theme_name = Data::Printer::Common::_fetch_scalar_or_default($props, 'theme', $default_theme);
496             $theme_object = Data::Printer::Theme->new(
497             name => $theme_name,
498             color_overrides => $props->{colors},
499             color_level => $self->{_output_color_level},
500 246         1479 ddp => $self,
501             );
502 246 50       817 if (!$theme_object) {
503 0 0       0 if ($theme_name ne $default_theme) {
504             $theme_object = Data::Printer::Theme->new(
505             name => $default_theme,
506             color_overrides => $props->{colors},
507             color_level => $self->{_output_color_level},
508 0         0 ddp => $self,
509             );
510             }
511 0 0       0 Data::Printer::Common::_die("Unable to load default theme. This should never happen - please contact the author") unless $theme_object;
512             }
513 246         714 $self->{theme} = $theme_object;
514             }
515              
516             sub _filters_for_type {
517 677     677   1280 my ($self, $type) = @_;
518 677 50       1556 return exists $self->{type_filters}{$type} ? @{ $self->{type_filters}{$type} } : ();
  677         1695  
519             }
520              
521             sub _filters_for_class {
522 879     879   1502 my ($self, $type) = @_;
523 879 100       2044 return exists $self->{class_filters}{$type} ? @{ $self->{class_filters}{$type} } : ();
  133         306  
524             }
525              
526             sub _filters_for_data {
527 638     638   1190 my ($self, $data) = @_;
528              
529             # we favour reftype() over ref() because you could have
530             # a HASH.pm (or ARRAY.pm or whatever) blessing any variable.
531 638         1436 my $ref_kind = Scalar::Util::reftype($data);
532 638 50       1347 $ref_kind = 'SCALAR' unless $ref_kind;
533              
534             # ref() returns 'Regexp' but reftype() returns 'REGEXP', so we picked one:
535 638 100       1387 $ref_kind = 'Regexp' if $ref_kind eq 'REGEXP';
536              
537 638         923 my @potential_filters;
538              
539             # first, try class name + full inheritance for a specific name.
540 638         1347 my $class = Scalar::Util::blessed($data);
541              
542             # a regular regexp is blessed, but in that case we want a
543             # regexp filter, not a class filter.
544 638 100 100     1707 if (defined $class && $class eq 'Regexp') {
545 5 50 0     19 if ($ref_kind eq 'Regexp' || ($] < 5.011 && $ref_kind eq 'SCALAR')) {
      33        
546 5         21 $ref_kind = 'Regexp';
547 5         10 undef $class;
548             }
549             }
550 638 100       1266 if (defined $class) {
551 94 100       239 if ($self->class->parent_filters) {
552 93         291 my $linear_ISA = Data::Printer::Common::_linear_ISA_for($class, $self);
553 93         210 foreach my $candidate_class (@$linear_ISA) {
554 146         285 push @potential_filters, $self->_filters_for_class($candidate_class);
555             }
556             }
557             else {
558 1         4 push @potential_filters, $self->_filters_for_class($class);
559             }
560             # next, let any '-class' filters have a go:
561 94         215 push @potential_filters, $self->_filters_for_class('-class');
562             }
563              
564             # then, try regular data filters
565 638         1434 push @potential_filters, $self->_filters_for_type($ref_kind);
566              
567             # finally, if it's neither a class nor a known core type,
568             # we must be in a future perl with some type we're unaware of:
569 638         1383 push @potential_filters, $self->_filters_for_class('-unknown');
570              
571 638         1552 return @potential_filters;
572             }
573              
574             # _see($data): marks data as seen if it was never seen it before.
575             # if we are showing refcounts, we return those. Initially we had
576             # this funcionallity separated, but refcounts increase as we find
577             # them again and because of that we were seeing weird refcounting.
578             # So now instead we store the refcount of the variable when we
579             # first see it.
580             # Finally, if we have already seen the data, we return its stringified
581             # position, like "var", "var{foo}[7]", etc. UNLESS $options{seen_override}
582             # is set. Why seen_override? Sometimes we want to print the same data
583             # twice, like the GenericClass filter, which prints the object's metadata
584             # via parse() and then the internal structure via parse_as(). But if we
585             # simply do that, we'd get the "seen" version (because we have already
586             # visited it!) The refcount is still calculated only once though :)
587             sub _see {
588 710     710   1446 my ($self, $data, %options) = @_;
589 710 100       1693 return {} unless ref $data;
590 708         2520 my $id = pack 'J', Scalar::Util::refaddr($data);
591 708 100       1782 if (!exists $self->{_seen}{$id}) {
592 635 100       1375 $self->{_seen}{$id} = {
593             name => $self->current_name,
594             refcount => ($self->show_refcount ? $self->_refcount($data) : 0),
595             };
596 635         2399 return { refcount => $self->{_seen}{$id}->{refcount} };
597             }
598 73 100       330 return { refcount => $self->{_seen}{$id}->{refcount} } if $options{seen_override};
599 33         79 return $self->{_seen}{$id};
600             }
601              
602             sub seen {
603 3     3 1 19 my ($self, $data) = @_;
604 3         10 my $id = pack 'J', Scalar::Util::refaddr($data);
605 3         12 return exists $self->{_seen}{$id};
606             }
607              
608             sub unsee {
609 20     20 1 33 my ($self, $data) = @_;
610 20 50 33     32 return unless ref $data && keys %{$self->{_seen}};
  20         61  
611              
612 20         49 my $id = pack 'J', Scalar::Util::refaddr($data);
613 20         43 delete $self->{_seen}{$id};
614 20         35 return;
615             }
616              
617             sub _refcount {
618 74     74   150 my ($self, $data) = @_;
619              
620 74         364 require B;
621 74         110 my $count;
622 74         315 my $rv = B::svref_2object(\$data)->RV;
623 74 100 66     322 if (ref($data) eq 'REF' && ref($$data)) {
624 25         100 $rv = B::svref_2object($data)->RV;
625             }
626              
627             # some SV's are special (represented by B::SPECIAL)
628             # and don't have a ->REFCNT (e.g. \undef)
629 74 50       332 return 0 unless $rv->can( 'REFCNT' );
630              
631             # 3 is our magical number: so we return the actual reference count
632             # minus the references we added as we were traversing:
633 74         403 return $rv->REFCNT - $self->{_refcount_base};
634             }
635              
636             sub parse_as {
637 39     39 1 93 my ($self, $type, $data) = @_;
638 39         131 return $self->parse($data, force_type => $type, seen_override => 1);
639             }
640              
641             # parse() must always receive a reference, never a regular copy, because
642             # that's the only way we are able to figure whether the source data
643             # is a weak ref or not.
644             sub parse {
645 710     710 1 23637 my $self = shift;
646 710         1664 my $str_weak = $self->_check_weak( $_[0] );
647              
648 710         1628 my ($data, %options) = @_;
649 710         1150 my $parsed_string = '';
650              
651             # if we've seen this structure before, we return its location
652             # instead of going through it again. This avoids infinite loops
653             # when parsing circular references:
654 710         2617 my $seen = $self->_see($data, %options);
655 710 100       1795 if (my $name = $seen->{name}) {
656 33 50 66     141 $parsed_string .= $self->maybe_colorize(
657             ((ref $data eq 'SCALAR' && $self->resolve_scalar_refs)
658             ? $$data
659             : $name
660             ),
661             'repeated'
662             );
663             # on repeated references, the only extra data we put
664             # is whether this reference is weak or not.
665 33         66 $parsed_string .= $str_weak;
666 33         133 return $parsed_string;
667             }
668 677         1120 $self->{_position}++;
669              
670             # Each filter type provides an array of potential parsers.
671             # Once we find the right kind, we go through all of them,
672             # from most precise match to most generic.
673             # The first filter that returns a defined value "wins"
674             # (even if it's an empty string)
675 677 100       1985 foreach my $filter (
676             exists $options{force_type}
677             ? $self->_filters_for_type($options{force_type})
678             : $self->_filters_for_data($data)
679             ) {
680 678 100       1945 if (defined (my $result = $filter->($data, $self))) {
681 677         1434 $parsed_string .= $result;
682 677         1217 last;
683             }
684             }
685              
686             # FIXME: because of prototypes, p(@data) becomes a ref (that we don't care about)
687             # to the data (that we do care about). So we should not show refcounts, memsize
688             # or readonly status for something guaranteed to be ephemeral.
689 677         1521 $parsed_string .= $self->_check_readonly($data);
690 677 100       1741 $parsed_string .= $str_weak if ref($data) ne 'REF';
691 677         1417 $parsed_string .= $self->_check_memsize($data);
692              
693 677 100 100     1407 if ($self->show_refcount && ref($data) ne 'SCALAR' && $seen->{refcount} > 1 ) {
      100        
694 20         69 $parsed_string .= ' (refcount: ' . $seen->{refcount} .')';
695             }
696              
697 677 100       1578 if (--$self->{'_position'} == 0) {
698 304         1120 $self->{'_seen'} = {};
699 304         572 $self->{'_refcount_base'} = 3;
700 304         498 $self->{'_position'} = 0;
701             }
702              
703 677         3393 return $parsed_string;
704             }
705              
706             sub _check_memsize {
707 677     677   1229 my ($self, $data) = @_;
708             return '' unless $self->show_memsize
709             && ( $self->show_memsize eq 'all'
710 677 50 0     1292 || $self->show_memsize >= $self->{_position});
      33        
711 0         0 my $size;
712             my $unit;
713             my $error = Data::Printer::Common::_tryme(sub {
714 0     0   0 require Devel::Size;
715 0         0 $size = Devel::Size::total_size($data);
716 0         0 $unit = uc $self->memsize_unit;
717 0 0 0     0 if ($unit eq 'M' || ($unit eq 'AUTO' && $size > 1024*1024)) {
    0 0        
      0        
      0        
718 0         0 $size = $size / (1024*1024);
719 0         0 $unit = 'M';
720             }
721             elsif ($unit eq 'K' || ($unit eq 'AUTO' && $size > 1024)) {
722 0         0 $size = $size / 1024;
723 0         0 $unit = 'K';
724             }
725             else {
726 0         0 $unit = 'B';
727             }
728 0         0 });
729 0 0       0 if ($error) {
730 0 0       0 if ($error =~ m{locate Devel/Size.pm}) {
731             Data::Printer::Common::_warn($self, "Devel::Size not found, show_memsize will be ignored")
732 0 0       0 if $self->{_position} == 1;
733             }
734             else {
735 0         0 Data::Printer::Common::_warn($self, "error fetching memory usage: $error");
736             }
737 0         0 return '';
738             }
739 0 0       0 return '' unless $size;
740 0 0       0 my $string = ' (' . ($size < 0 ? sprintf("%.2f", $size) : int($size)) . $unit . ')';
741 0         0 return $self->maybe_colorize($string, 'memsize');
742             }
743              
744             sub _check_weak {
745 710     710   1250 my ($self) = shift;
746 710 100       1487 return '' unless $self->show_weak;
747              
748 672         2198 my $realtype = Scalar::Util::reftype($_[0]);
749 672         980 my $isweak;
750 672 100 100     3189 if ($realtype && ($realtype eq 'REF' || $realtype eq 'SCALAR')) {
      66        
751 437         1089 $isweak = Scalar::Util::isweak($_[0]);
752             }
753             else {
754 235         611 $isweak = Scalar::Util::isweak($_[0]);
755             }
756 672 100       1812 return '' unless $isweak;
757 17         49 return ' ' . $self->maybe_colorize('(weak)', 'weak');
758             }
759              
760             sub _write_label {
761 61     61   120 my ($self) = @_;
762 61 100       154 return '' unless $self->caller_info;
763 2         19 my @caller = caller 1;
764              
765 2         15 my $message = $self->caller_message;
766              
767 2         7 $message =~ s/\b__PACKAGE__\b/$caller[0]/g;
768 2         18 $message =~ s/\b__FILENAME__\b/$caller[1]/g;
769 2         13 $message =~ s/\b__LINE__\b/$caller[2]/g;
770              
771 2 50       7 my $separator = $self->caller_message_newline ? "\n" : ' ';
772 2         7 $message = $self->maybe_colorize($message, 'caller_info');
773 2 100       5 $message = $self->caller_message_position eq 'before'
774             ? $message . $separator
775             : $separator . $message
776             ;
777 2         10 return $message;
778             }
779              
780             sub maybe_colorize {
781 1832     1832 1 16639 my ($self, $output, $color_type, $default_color, $end_color) = @_;
782              
783 1832 100 100     4119 if ($self->{_output_color_level} && defined $color_type) {
784 3         7 my $theme = $self->theme;
785 3         11 my $sgr_color = $theme->sgr_color_for($color_type);
786 3 100 100     15 if (!defined $sgr_color && defined $default_color) {
787 1         4 $sgr_color = $theme->_parse_color($default_color);
788             }
789 3 100       8 if ($sgr_color) {
790 1 50       7 $output = $sgr_color
791             . $output
792             . (defined $end_color
793             ? $theme->sgr_color_for($end_color)
794             : $theme->color_reset
795             );
796             }
797             }
798 1832         5129 return $output;
799             }
800              
801             sub _check_readonly {
802 677     677   1296 my ($self) = @_;
803 677 100 100     1307 return ' (read-only)' if $self->show_readonly && &Internals::SvREADONLY($_[1]);
804 670         1460 return '';
805             }
806              
807             42;
808             __END__