File Coverage

blib/lib/Data/Recursive/Encode.pm
Criterion Covered Total %
statement 74 76 97.3
branch 21 24 87.5
condition 12 25 48.0
subroutine 18 20 90.0
pod 5 5 100.0
total 130 150 86.6


line stmt bran cond sub pod time code
1             package Data::Recursive::Encode;
2 6     6   403819 use 5.008001;
  6         69  
3 6     6   33 use strict;
  6         11  
  6         145  
4 6     6   27 use warnings FATAL => 'all';
  6         12  
  6         306  
5              
6             our $VERSION = '0.07';
7              
8 6     6   3503 use Encode ();
  6         61431  
  6         140  
9 6     6   46 use Carp ();
  6         13  
  6         123  
10 6     6   32 use Scalar::Util qw(blessed refaddr);
  6         12  
  6         361  
11 6     6   40 use B;
  6         13  
  6         5555  
12              
13             our $DO_NOT_PROCESS_NUMERIC_VALUE = 0;
14              
15             sub _apply {
16 60     60   102 my $code = shift;
17 60         89 my $seen = shift;
18              
19 60         91 my @retval;
20 60         115 for my $arg (@_) {
21 80 100       334 if(my $ref = ref $arg){
22 29         82 my $refaddr = refaddr($arg);
23 29         42 my $proto;
24              
25 29 100 66     152 if(defined($proto = $seen->{$refaddr})){
    100          
    100          
    100          
26             # noop
27             }
28             elsif($ref eq 'ARRAY'){
29 8         23 $proto = $seen->{$refaddr} = [];
30 8         21 @{$proto} = _apply($code, $seen, @{$arg});
  8         27  
  8         19  
31             }
32             elsif($ref eq 'HASH'){
33 8         20 $proto = $seen->{$refaddr} = {};
34 8         20 %{$proto} = _apply($code, $seen, %{$arg});
  8         25  
  8         38  
35             }
36             elsif($ref eq 'REF' or $ref eq 'SCALAR'){
37 4         9 $proto = $seen->{$refaddr} = \do{ my $scalar };
  4         12  
38 4         9 ${$proto} = _apply($code, $seen, ${$arg});
  4         7  
  4         19  
39             }
40             else{ # CODE, GLOB, IO, LVALUE etc.
41 8         19 $proto = $seen->{$refaddr} = $arg;
42             }
43              
44 29         68 push @retval, $proto;
45             }
46             else{
47 51 100 66     331 push @retval, defined($arg) && (! $DO_NOT_PROCESS_NUMERIC_VALUE || ! _is_number($arg)) ? $code->($arg) : $arg;
48             }
49             }
50              
51 60 100       794 return wantarray ? @retval : $retval[0];
52             }
53              
54             sub decode {
55 9     9 1 26444 my ($class, $encoding, $stuff, $check) = @_;
56 9   33     25 $encoding = Encode::find_encoding($encoding)
57             || Carp::croak("$class: unknown encoding '$encoding'");
58 9   50     164 $check ||= 0;
59 9     10   47 _apply(sub { $encoding->decode($_[0], $check) }, {}, $stuff);
  10         46  
60             }
61              
62             sub encode {
63 9     9 1 11416 my ($class, $encoding, $stuff, $check) = @_;
64 9   33     26 $encoding = Encode::find_encoding($encoding)
65             || Carp::croak("$class: unknown encoding '$encoding'");
66 9   50     162 $check ||= 0;
67 9     10   43 _apply(sub { $encoding->encode($_[0], $check) }, {}, $stuff);
  10         47  
68             }
69              
70             sub decode_utf8 {
71 9     9 1 7524 my ($class, $stuff, $check) = @_;
72             my $cb = @_==3
73 0     0   0 ? sub { Encode::decode_utf8($_[0], $check) }
74 9 50   10   47 : sub { Encode::decode_utf8($_[0]) };
  10         36  
75 9         33 _apply($cb, {}, $stuff);
76             }
77              
78             sub encode_utf8 {
79 12     12 1 7427 my ($class, $stuff) = @_;
80 12         45 _apply(\&Encode::encode_utf8, {}, $stuff);
81             }
82              
83             sub from_to {
84 1     1 1 3219 my ($class, $stuff, $from_enc, $to_enc, $check) = @_;
85 1 50       6 @_ >= 4 or Carp::croak("Usage: $class->from_to(OCTET, FROM_ENC, TO_ENC[, CHECK])");
86 1   33     4 $from_enc = Encode::find_encoding($from_enc)
87             || Carp::croak("$class: unknown encoding '$from_enc'");
88 1   33     24 $to_enc = Encode::find_encoding($to_enc)
89             || Carp::croak("$class: unknown encoding '$to_enc'");
90             my $cb = @_==5
91 0     0   0 ? sub { Encode::from_to($_[0], $from_enc, $to_enc, $check) }
92 1 50   1   191 : sub { Encode::from_to($_[0], $from_enc, $to_enc) };
  1         6  
93 1         6 _apply($cb, {}, $stuff);
94 1         6 return $stuff;
95             }
96              
97             sub _is_number {
98 14     14   117 my $value = shift;
99 14 100       40 return 0 unless defined $value;
100              
101 13         55 my $b_obj = B::svref_2object(\$value);
102 13         61 my $flags = $b_obj->FLAGS;
103 13 100 66     102 return $flags & ( B::SVp_IOK | B::SVp_NOK ) && !( $flags & B::SVp_POK ) ? 1 : 0;
104             }
105              
106             1;
107             __END__