File Coverage

blib/lib/Data/Recursive/Encode.pm
Criterion Covered Total %
statement 73 73 100.0
branch 19 20 95.0
condition 12 25 48.0
subroutine 18 18 100.0
pod 5 5 100.0
total 127 141 90.0


line stmt bran cond sub pod time code
1             package Data::Recursive::Encode;
2 6     6   103566 use 5.008001;
  6         17  
  6         185  
3 6     6   26 use strict;
  6         7  
  6         190  
4 6     6   23 use warnings FATAL => 'all';
  6         12  
  6         319  
5              
6             our $VERSION = '0.06';
7              
8 6     6   3361 use Encode ();
  6         57717  
  6         171  
9 6     6   46 use Carp ();
  6         7  
  6         121  
10 6     6   26 use Scalar::Util qw(blessed refaddr);
  6         9  
  6         677  
11 6     6   33 use B;
  6         8  
  6         4646  
12              
13             our $DO_NOT_PROCESS_NUMERIC_VALUE = 0;
14              
15             sub _apply {
16 60     60   68 my $code = shift;
17 60         62 my $seen = shift;
18              
19 60         58 my @retval;
20 60         93 for my $arg (@_) {
21 80 100       204 if(my $ref = ref $arg){
22 29         56 my $refaddr = refaddr($arg);
23 29         25 my $proto;
24              
25 29 100 66     132 if(defined($proto = $seen->{$refaddr})){
    100          
    100          
    100          
26             # noop
27             }
28             elsif($ref eq 'ARRAY'){
29 8         18 $proto = $seen->{$refaddr} = [];
30 8         10 @{$proto} = _apply($code, $seen, @{$arg});
  8         18  
  8         18  
31             }
32             elsif($ref eq 'HASH'){
33 8         20 $proto = $seen->{$refaddr} = {};
34 8         9 %{$proto} = _apply($code, $seen, %{$arg});
  8         20  
  8         30  
35             }
36             elsif($ref eq 'REF' or $ref eq 'SCALAR'){
37 4         4 $proto = $seen->{$refaddr} = \do{ my $scalar };
  4         10  
38 4         6 ${$proto} = _apply($code, $seen, ${$arg});
  4         4  
  4         11  
39             }
40             else{ # CODE, GLOB, IO, LVALUE etc.
41 8         11 $proto = $seen->{$refaddr} = $arg;
42             }
43              
44 29         54 push @retval, $proto;
45             }
46             else{
47 51 100 66     294 push @retval, defined($arg) && (! $DO_NOT_PROCESS_NUMERIC_VALUE || ! _is_number($arg)) ? $code->($arg) : $arg;
48             }
49             }
50              
51 60 100       648 return wantarray ? @retval : $retval[0];
52             }
53              
54             sub decode {
55 9     9 1 22510 my ($class, $encoding, $stuff, $check) = @_;
56 9   33     20 $encoding = Encode::find_encoding($encoding)
57             || Carp::croak("$class: unknown encoding '$encoding'");
58 9   50     124 $check ||= 0;
59 9     10   43 _apply(sub { $encoding->decode($_[0], $check) }, {}, $stuff);
  10         45  
60             }
61              
62             sub encode {
63 9     9 1 9836 my ($class, $encoding, $stuff, $check) = @_;
64 9   33     26 $encoding = Encode::find_encoding($encoding)
65             || Carp::croak("$class: unknown encoding '$encoding'");
66 9   50     136 $check ||= 0;
67 9     10   47 _apply(sub { $encoding->encode($_[0], $check) }, {}, $stuff);
  10         55  
68             }
69              
70             sub decode_utf8 {
71 9     9 1 7027 my ($class, $stuff, $check) = @_;
72 9     10   52 _apply(sub { Encode::decode_utf8($_[0], $check) }, {}, $stuff);
  10         32  
73             }
74              
75             sub encode_utf8 {
76 12     12 1 5806 my ($class, $stuff) = @_;
77 12         42 _apply(\&Encode::encode_utf8, {}, $stuff);
78             }
79              
80             sub from_to {
81 1     1 1 2631 my ($class, $stuff, $from_enc, $to_enc, $check) = @_;
82 1 50       7 @_ >= 4 or Carp::croak("Usage: $class->from_to(OCTET, FROM_ENC, TO_ENC[, CHECK])");
83 1   33     5 $from_enc = Encode::find_encoding($from_enc)
84             || Carp::croak("$class: unknown encoding '$from_enc'");
85 1   33     13 $to_enc = Encode::find_encoding($to_enc)
86             || Carp::croak("$class: unknown encoding '$to_enc'");
87 1     1   172 _apply(sub { Encode::from_to($_[0], $from_enc, $to_enc, $check) }, {}, $stuff);
  1         6  
88 1         7 return $stuff;
89             }
90              
91             sub _is_number {
92 14     14   23 my $value = shift;
93 14 100       36 return 0 unless defined $value;
94              
95 13         54 my $b_obj = B::svref_2object(\$value);
96 13         51 my $flags = $b_obj->FLAGS;
97 13 100 66     97 return $flags & ( B::SVp_IOK | B::SVp_NOK ) && !( $flags & B::SVp_POK ) ? 1 : 0;
98             }
99              
100             1;
101             __END__