File Coverage

blib/lib/Encoding/HandleUtf8.pm
Criterion Covered Total %
statement 60 64 93.7
branch 24 32 75.0
condition 10 17 58.8
subroutine 12 13 92.3
pod 2 2 100.0
total 108 128 84.3


line stmt bran cond sub pod time code
1             package Encoding::HandleUtf8;
2             # ABSTRACT: Fix the encoding for Perl value store (input) and general output (output) to a console or the web.
3             #
4             # This file is part of Encoding-HandleUtf8
5             #
6             # This software is Copyright (c) 2014 by BURNERSK .
7             #
8             # This is free software, licensed under:
9             #
10             # The MIT (X11) License
11             #
12 4     4   86550 use strict;
  4         8  
  4         141  
13 4     4   17 use warnings FATAL => 'all';
  4         5  
  4         184  
14              
15             BEGIN {
16 4     4   75 our $VERSION = '0.004'; # VERSION: generated by Dist::Zilla
17             }
18              
19 4     4   22 use Carp qw( carp croak );
  4         4  
  4         219  
20 4     4   2175 use Encoding::FixLatin qw( fix_latin );
  4         44122  
  4         224  
21 4     4   1897 use Clone 'clone';
  4         10090  
  4         291  
22 4     4   29 use List::Util qw( first );
  4         7  
  4         562  
23              
24             ############################################################################
25             # Prototype definition - required for the recursion, otherwise it will not
26             # find itself because it is not already in the internal symbol list.
27              
28             sub fix_encoding ($\[$@%];$);
29             sub fix_encoding_return ($$;$);
30              
31             ############################################################################
32             # Setup exporter.
33              
34             our @EXPORT_OK;
35             our @IGNORE_LIST;
36              
37             BEGIN {
38 4     4   22 use base 'Exporter';
  4         7  
  4         508  
39 4     4   13 @EXPORT_OK = qw( &fix_encoding &fix_encoding_return );
40 4 50       1919 @IGNORE_LIST = qw( Cpanel::JSON::XS::Boolean JSON::XS::Boolean JSON::PP::Boolean JSON::Boolean )
41             unless scalar @IGNORE_LIST;
42             }
43              
44             ############################################################################
45             # Utility function to fix the encoding for Perl value store (input) and
46             # general output (output) to a console or the web.
47             # Second parameter is the object indended which should be fixed. Due to
48             # prototypes it automatically turns into an reference.
49             sub fix_encoding ($\[$@%];$) {
50 140     140 1 19896 my ( $direction, $obj, $skip_latin ) = @_;
51              
52 140         181 my $ref = ref $obj;
53 140 100       246 my $obj_ref = $ref eq 'REF' ? ref ${$obj} : $ref;
  43         64  
54              
55             # Check encoding direction.
56 140 50 66     563 croak sprintf q{invalid direction '%s' (input or output)}, $direction
      33        
57             if !$direction || ( $direction ne 'input' && $direction ne 'output' );
58              
59             # If $obj is just a string everything is very basic.
60 140 100       266 if ( $ref eq 'SCALAR' ) {
    50          
    100          
    50          
61              
62             # Fix possible mixed encodings.
63 96 50       149 ${$obj} = fix_latin ${$obj} unless $skip_latin;
  96         6563  
  96         207  
64              
65             # Final encoding it to UTF-8 (output) or Unicode (input).
66 96 100       171 if ( $direction eq 'output' ) {
67 46 50 33     37 utf8::encode ${$obj} if defined ${$obj} && utf8::is_utf8 ${$obj};
  46         64  
  46         93  
  46         132  
68             }
69             else {
70 50 100 66     41 utf8::decode ${$obj} if defined ${$obj} && !utf8::is_utf8 ${$obj};
  2         7  
  50         107  
  50         169  
71             }
72             }
73              
74             # Iterate over an array reference.
75             elsif ( $ref eq 'ARRAY' ) {
76 0         0 fix_encoding $direction, $_ for ( @{$obj} );
  0         0  
77             }
78              
79             # Iterate over the keys of a hash reference.
80             elsif ( $ref eq 'HASH' ) {
81 1         1 fix_encoding $direction, $obj->{$_} for ( keys %{$obj} );
  1         8  
82             }
83              
84             # Otherwise if $obj is a reference we have to use some recursive magic.
85             elsif ( $ref eq 'REF' ) {
86              
87             # Iterate over an array reference.
88 43 100       107 if ( $obj_ref eq 'ARRAY' ) {
    100          
89 12         14 fix_encoding $direction, $_ for ( @{ ${$obj} } );
  12         12  
  12         37  
90             }
91              
92             # Iterate over the keys of a hash reference.
93             elsif ( $obj_ref eq 'HASH' ) {
94 29         22 fix_encoding $direction, ${$obj}->{$_} for ( keys %{ ${$obj} } );
  29         26  
  29         82  
  57         130  
95             }
96              
97             # Everything else is not supported.
98             else {
99             carp sprintf q{unsupported reference '%s'}, $obj_ref
100 2 100   2   20 unless first { $_ eq $obj_ref } @IGNORE_LIST;
  2         36  
101             }
102              
103             }
104              
105             # w00t - this shouldn't ever happen!
106             else {
107             carp sprintf q{unknown object reference '%s'}, $ref
108 0 0   0   0 unless first { $_ eq $ref } @IGNORE_LIST;
  0         0  
109             }
110              
111 139 100 100     384 return $ref eq 'REF' || $ref eq 'SCALAR' ? ${$obj} : $obj;
  138         286  
112             }
113              
114              
115             ############################################################################
116             # Does the same like fix_encoding but do not touches original reference.
117             sub fix_encoding_return ($$;$) {
118 27     27 1 24948 my ( $direction, $obj, $skip_latin ) = @_;
119 27         208 my $obj_cloned = clone $obj;
120 27   50     135 fix_encoding $direction, $obj_cloned, $skip_latin // 0;
121 27         100 return $obj_cloned;
122             }
123              
124              
125              
126             ############################################################################
127             1;
128             ############################################################################
129              
130             __END__