File Coverage

blib/lib/Data/Dumper/AutoEncode.pm
Criterion Covered Total %
statement 87 97 89.6
branch 26 36 72.2
condition 14 25 56.0
subroutine 18 18 100.0
pod 2 2 100.0
total 147 178 82.5


line stmt bran cond sub pod time code
1             package Data::Dumper::AutoEncode;
2 5     5   371811 use strict;
  5         45  
  5         163  
3 5     5   28 use warnings;
  5         10  
  5         113  
4 5     5   26 use Carp ();
  5         9  
  5         60  
5 5     5   1903 use Encode ();
  5         31530  
  5         132  
6 5     5   32 use Scalar::Util qw(blessed refaddr);
  5         11  
  5         328  
7 5     5   36 use B;
  5         10  
  5         178  
8 5     5   3187 use Data::Dumper; # Dumper
  5         31357  
  5         731  
9              
10             our $VERSION = '1.00';
11              
12             our $ENCODING = '';
13             our $CHECK_ALREADY_ENCODED = 0;
14             our $DO_NOT_PROCESS_NUMERIC_VALUE = 1;
15             our $FLAG_STR = '';
16              
17             our $BEFORE_HOOK;
18             our $AFTER_HOOK;
19              
20             sub import {
21 5     5   56 my $class = shift;
22 5         15 my %args = map { $_ => 1 } @_;
  2         9  
23              
24 5 100       25 if (delete $args{'-dumper'}) {
25 5     5   41 no strict 'refs'; ## no critic
  5         12  
  5         423  
26 1         2 *{__PACKAGE__."::Dumper"} = *{__PACKAGE__."::eDumper"};
  1         4  
  1         3  
27             }
28              
29 5         17 my $export_all = !!(scalar(keys %args) == 0);
30              
31 5         12 my $pkg = caller;
32              
33 5         15 for my $f (qw/ Dumper eDumper /) {
34 10 50 66     46 if ( $export_all || (exists $args{$f} && $args{$f}) ) {
      66        
35 5     5   31 no strict 'refs'; ## no critic
  5         12  
  5         4300  
36 9         14 *{"${pkg}::${f}"} = \&{$f};
  9         3078  
  9         25  
37             }
38             }
39             }
40              
41             sub _dump {
42 12     12   62 my $d = Data::Dumper->new(\@_);
43 12         367 return $d->Dump;
44             }
45              
46             sub eDumper {
47 12     12 1 15933 my @args;
48 12         33 for my $arg (@_) {
49 13   100     84 push @args, encode($ENCODING || 'utf8', $arg);
50             }
51 12         36 _dump(@args);
52             }
53              
54             sub encode {
55 13     13 1 37 my ($encoding, $stuff, $check) = @_;
56 13   33     37 $encoding = Encode::find_encoding($encoding)
57             || Carp::croak("unknown encoding '$encoding'");
58 13   50     242 $check ||= 0;
59 13     12   72 _apply(sub { $encoding->encode($_[0], $check) }, {}, $stuff);
  12         54  
60             }
61              
62             # copied from Data::Recursive::Encode
63             sub _apply {
64 15     15   30 my $code = shift;
65 15         23 my $seen = shift;
66              
67 15         25 my @retval;
68 15         30 for my $arg (@_) {
69 17 100       46 if(my $ref = ref $arg){
70 2         6 my $refaddr = refaddr($arg);
71 2         3 my $proto;
72              
73 2 50 0     15 if(defined($proto = $seen->{$refaddr})){
    50          
    50          
    0          
74             # noop
75             }
76             elsif($ref eq 'ARRAY'){
77 0         0 $proto = $seen->{$refaddr} = [];
78 0         0 @{$proto} = _apply($code, $seen, @{$arg});
  0         0  
  0         0  
79             }
80             elsif($ref eq 'HASH'){
81 2         7 $proto = $seen->{$refaddr} = {};
82 2         4 %{$proto} = _apply($code, $seen, %{$arg});
  2         7  
  2         13  
83             }
84             elsif($ref eq 'REF' or $ref eq 'SCALAR'){
85 0         0 $proto = $seen->{$refaddr} = \do{ my $scalar };
  0         0  
86 0         0 ${$proto} = _apply($code, $seen, ${$arg});
  0         0  
  0         0  
87             }
88             else{ # CODE, GLOB, IO, LVALUE etc.
89 0         0 $proto = $seen->{$refaddr} = $arg;
90             }
91              
92 2         5 push @retval, $proto;
93             }
94             else{
95 15 100       40 if (_can_exec($arg)) {
96 12 100       50 push @retval, $FLAG_STR ? $FLAG_STR . _exec($code, $arg) : _exec($code, $arg);
97             }
98             else {
99 3         7 push @retval, $arg;
100             }
101             }
102             }
103              
104 15 50       111 return wantarray ? @retval : $retval[0];
105             }
106              
107             sub _exec {
108 12     12   27 my ($code, $arg) = @_;
109              
110 12 100       32 if (ref $BEFORE_HOOK eq 'CODE') {
111 1         4 $arg = $BEFORE_HOOK->($arg);
112             }
113              
114 12         36 my $result = $code->($arg);
115              
116 12 100       34 if (ref $AFTER_HOOK eq 'CODE') {
117 1         3 return $AFTER_HOOK->($result);
118             }
119              
120 11         35 return $result;
121             }
122              
123             # copied from Data::Recursive::Encode
124             sub _is_number {
125 15     15   44 my $value = shift;
126 15 50       31 return 0 unless defined $value;
127              
128 15         69 my $b_obj = B::svref_2object(\$value);
129 15         68 my $flags = $b_obj->FLAGS;
130 15 100 66     95 return $flags & ( B::SVp_IOK | B::SVp_NOK ) && !( $flags & B::SVp_POK ) ? 1 : 0;
131             }
132              
133             sub _can_exec {
134 15     15   30 my ($arg) = @_;
135              
136 15 50       41 return unless defined($arg);
137 15 100 66     52 return if $DO_NOT_PROCESS_NUMERIC_VALUE && _is_number($arg);
138 14 100       85 return 1 if Encode::is_utf8($arg);
139 3 50 66     13 return 1 if !$CHECK_ALREADY_ENCODED && !Encode::is_utf8($arg);
140              
141 2         5 return;
142             }
143              
144             1;
145              
146             __END__