File Coverage

blib/lib/Encode.pm
Criterion Covered Total %
statement 163 208 78.3
branch 62 94 65.9
condition 34 40 85.0
subroutine 29 35 82.8
pod 8 13 61.5
total 296 390 75.9


line stmt bran cond sub pod time code
1             #
2             # $Id: Encode.pm,v 2.91 2017/06/22 08:11:05 dankogai Exp dankogai $
3             #
4             package Encode;
5 40     40   344124 use strict;
  40         125  
  40         1341  
6 40     40   1093 use warnings;
  40         103  
  40         2109  
7 40     40   289 use constant DEBUG => !!$ENV{PERL_ENCODE_DEBUG};
  40         108  
  40         6662  
8             our $VERSION;
9             BEGIN {
10 40     40   596 $VERSION = sprintf "%d.%02d", q$Revision: 2.91 $ =~ /(\d+)/g;
11 40         331 require XSLoader;
12 40         27206 XSLoader::load( __PACKAGE__, $VERSION );
13             }
14              
15 40     40   364 use Exporter 5.57 'import';
  40         1061  
  40         8888  
16              
17             our @CARP_NOT = qw(Encode::Encoder);
18              
19             # Public, encouraged API is exported by default
20              
21             our @EXPORT = qw(
22             decode decode_utf8 encode encode_utf8 str2bytes bytes2str
23             encodings find_encoding find_mime_encoding clone_encoding
24             );
25             our @FB_FLAGS = qw(
26             DIE_ON_ERR WARN_ON_ERR RETURN_ON_ERR LEAVE_SRC
27             PERLQQ HTMLCREF XMLCREF STOP_AT_PARTIAL
28             );
29             our @FB_CONSTS = qw(
30             FB_DEFAULT FB_CROAK FB_QUIET FB_WARN
31             FB_PERLQQ FB_HTMLCREF FB_XMLCREF
32             );
33             our @EXPORT_OK = (
34             qw(
35             _utf8_off _utf8_on define_encoding from_to is_16bit is_8bit
36             is_utf8 perlio_ok resolve_alias utf8_downgrade utf8_upgrade
37             ),
38             @FB_FLAGS, @FB_CONSTS,
39             );
40              
41             our %EXPORT_TAGS = (
42             all => [ @EXPORT, @EXPORT_OK ],
43             default => [ @EXPORT ],
44             fallbacks => [ @FB_CONSTS ],
45             fallback_all => [ @FB_CONSTS, @FB_FLAGS ],
46             );
47              
48             # Documentation moved after __END__ for speed - NI-S
49              
50             our $ON_EBCDIC = ( ord("A") == 193 );
51              
52 40     40   19580 use Encode::Alias;
  40         170  
  40         6483  
53 40     40   22235 use Encode::MIME::Name;
  40         158  
  40         1896  
54              
55 40     40   30513 use Storable;
  40         156498  
  40         98190  
56              
57             # Make a %Encoding package variable to allow a certain amount of cheating
58             our %Encoding;
59             our %ExtModule;
60             require Encode::Config;
61             # See
62             # https://bugzilla.redhat.com/show_bug.cgi?id=435505#c2
63             # to find why sig handlers inside eval{} are disabled.
64             eval {
65             local $SIG{__DIE__};
66             local $SIG{__WARN__};
67             local @INC = @INC;
68             pop @INC if $INC[-1] eq '.';
69             require Encode::ConfigLocal;
70             };
71              
72             sub encodings {
73 4     4 1 146 my %enc;
74 4   100     28 my $arg = $_[1] || '';
75 4 100       21 if ( $arg eq ":all" ) {
76 3         279 %enc = ( %Encoding, %ExtModule );
77             }
78             else {
79 1         11 %enc = %Encoding;
80 1 0       5 for my $mod ( map { m/::/ ? $_ : "Encode::$_" } @_ ) {
  0         0  
81 0         0 DEBUG and warn $mod;
82 0         0 for my $enc ( keys %ExtModule ) {
83 0 0       0 $ExtModule{$enc} eq $mod and $enc{$enc} = $mod;
84             }
85             }
86             }
87 2152         4037 return sort { lc $a cmp lc $b }
88 4         64 grep { !/^(?:Internal|Unicode|Guess)$/o } keys %enc;
  383         1091  
89             }
90              
91             sub perlio_ok {
92 16 50   16 0 11221 my $obj = ref( $_[0] ) ? $_[0] : find_encoding( $_[0] );
93 16 50       689 $obj->can("perlio_ok") and return $obj->perlio_ok();
94 0         0 return 0; # safety net
95             }
96              
97             sub define_encoding {
98 1318     1318 0 3205 my $obj = shift;
99 1318         2866 my $name = shift;
100 1318         3663 $Encoding{$name} = $obj;
101 1318         2943 my $lc = lc($name);
102 1318 100       5044 define_alias( $lc => $obj ) unless $lc eq $name;
103 1318         4522 while (@_) {
104 0         0 my $alias = shift;
105 0         0 define_alias( $alias, $obj );
106             }
107 1318         2893 my $class = ref($obj);
108 1318 100       3021 push @Encode::CARP_NOT, $class unless grep { $_ eq $class } @Encode::CARP_NOT;
  6000         16459  
109 1318 100       2929 push @Encode::Encoding::CARP_NOT, $class unless grep { $_ eq $class } @Encode::Encoding::CARP_NOT;
  7318         18090  
110 1318         7202 return $obj;
111             }
112              
113             sub getEncoding {
114 61762     61762 0 134547 my ( $class, $name, $skip_external ) = @_;
115              
116 61762 100       163614 defined($name) or return;
117              
118 61743         178519 $name =~ s/\s+//g; # https://rt.cpan.org/Ticket/Display.html?id=65796
119              
120 61743 100 66     180812 ref($name) && $name->can('renew') and return $name;
121 61740 100       274228 exists $Encoding{$name} and return $Encoding{$name};
122 3278         7815 my $lc = lc $name;
123 3278 100       9030 exists $Encoding{$lc} and return $Encoding{$lc};
124              
125 3227         12093 my $oc = $class->find_alias($name);
126 3227 100       11858 defined($oc) and return $oc;
127 478 100       1915 $lc ne $name and $oc = $class->find_alias($lc);
128 478 50       1193 defined($oc) and return $oc;
129              
130 478 50       1156 unless ($skip_external) {
131 478 100 66     2593 if ( my $mod = $ExtModule{$name} || $ExtModule{$lc} ) {
132 81         520 $mod =~ s,::,/,g;
133 81         275 $mod .= '.pm';
134 81         250 eval { require $mod; };
  81         48517  
135 81 50       863 exists $Encoding{$name} and return $Encoding{$name};
136             }
137             }
138 397         1127 return;
139             }
140              
141             sub find_encoding($;$) {
142 61757     61757 1 661729 my ( $name, $skip_external ) = @_;
143 61757         175750 return __PACKAGE__->getEncoding( $name, $skip_external );
144             }
145              
146             sub find_mime_encoding($;$) {
147 50352     50352 1 161536 my ( $mime_name, $skip_external ) = @_;
148 50352         158129 my $name = Encode::MIME::Name::get_encode_name( $mime_name );
149 50352         135233 return find_encoding( $name, $skip_external );
150             }
151              
152             sub resolve_alias($) {
153 0     0 0 0 my $obj = find_encoding(shift);
154 0 0       0 defined $obj and return $obj->name;
155 0         0 return;
156             }
157              
158             sub clone_encoding($) {
159 0     0 0 0 my $obj = find_encoding(shift);
160 0 0       0 ref $obj or return;
161 0         0 return Storable::dclone($obj);
162             }
163              
164             sub encode($$;$) {
165 2285     2285 1 946885 my ( $name, $string, $check ) = @_;
166 2285 100       8048 return undef unless defined $string;
167 2152         8837 $string .= ''; # stringify;
168 2152   100     8667 $check ||= 0;
169 2152 50       5942 unless ( defined $name ) {
170 0         0 require Carp;
171 0         0 Carp::croak("Encoding name should not be undef");
172             }
173 2152         6032 my $enc = find_encoding($name);
174 2152 50       6593 unless ( defined $enc ) {
175 0         0 require Carp;
176 0         0 Carp::croak("Unknown encoding '$name'");
177             }
178             # For Unicode, warnings need to be caught and re-issued at this level
179             # so that callers can disable utf8 warnings lexically.
180 2152         4134 my $octets;
181 2152 100       6805 if ( ref($enc) eq 'Encode::Unicode' ) {
182 72         207 my $warn = '';
183             {
184 72     0   154 local $SIG{__WARN__} = sub { $warn = shift };
  72         623  
  0         0  
185 72         65094 $octets = $enc->encode( $string, $check );
186             }
187 70 50       378 warnings::warnif('utf8', $warn) if length $warn;
188             }
189             else {
190 2080         142810 $octets = $enc->encode( $string, $check );
191             }
192 2020 100 100     19305 $_[1] = $string if $check and !ref $check and !( $check & LEAVE_SRC );
      100        
193 2020         10846 return $octets;
194             }
195             *str2bytes = \&encode;
196              
197             sub decode($$;$) {
198 1528     1528 1 618397 my ( $name, $octets, $check ) = @_;
199 1528 100       5802 return undef unless defined $octets;
200 1395         10141 $octets .= '';
201 1395   100     6586 $check ||= 0;
202 1395         3561 my $enc = find_encoding($name);
203 1395 50       4135 unless ( defined $enc ) {
204 0         0 require Carp;
205 0         0 Carp::croak("Unknown encoding '$name'");
206             }
207             # For Unicode, warnings need to be caught and re-issued at this level
208             # so that callers can disable utf8 warnings lexically.
209 1395         2411 my $string;
210 1395 100       4423 if ( ref($enc) eq 'Encode::Unicode' ) {
211 61         138 my $warn = '';
212             {
213 61     3   119 local $SIG{__WARN__} = sub { $warn = shift };
  61         458  
  3         28  
214 61         49960 $string = $enc->decode( $octets, $check );
215             }
216 59 100       982 warnings::warnif('utf8', $warn) if length $warn;
217             }
218             else {
219 1334         92825 $string = $enc->decode( $octets, $check );
220             }
221 1261 100 100     6179 $_[1] = $octets if $check and !ref $check and !( $check & LEAVE_SRC );
      100        
222 1261         9465 return $string;
223             }
224             *bytes2str = \&decode;
225              
226             sub from_to($$$;$) {
227 2151     2151 1 1612354 my ( $string, $from, $to, $check ) = @_;
228 2151 50       7166 return undef unless defined $string;
229 2151   100     11614 $check ||= 0;
230 2151         5510 my $f = find_encoding($from);
231 2151 50       5809 unless ( defined $f ) {
232 0         0 require Carp;
233 0         0 Carp::croak("Unknown encoding '$from'");
234             }
235 2151         4896 my $t = find_encoding($to);
236 2151 50       5701 unless ( defined $t ) {
237 0         0 require Carp;
238 0         0 Carp::croak("Unknown encoding '$to'");
239             }
240              
241             # For Unicode, warnings need to be caught and re-issued at this level
242             # so that callers can disable utf8 warnings lexically.
243 2151         3835 my $uni;
244 2151 100       6630 if ( ref($f) eq 'Encode::Unicode' ) {
245 3         7 my $warn = '';
246             {
247 3     3   8 local $SIG{__WARN__} = sub { $warn = shift };
  3         23  
  3         27  
248 3         59 $uni = $f->decode($string);
249             }
250 3 50       675 warnings::warnif('utf8', $warn) if length $warn;
251             }
252             else {
253 2148         12359 $uni = $f->decode($string);
254             }
255              
256 2151 50       6670 if ( ref($t) eq 'Encode::Unicode' ) {
257 0         0 my $warn = '';
258             {
259 0     0   0 local $SIG{__WARN__} = sub { $warn = shift };
  0         0  
  0         0  
260 0         0 $_[0] = $string = $t->encode( $uni, $check );
261             }
262 0 0       0 warnings::warnif('utf8', $warn) if length $warn;
263             }
264             else {
265 2151         10922 $_[0] = $string = $t->encode( $uni, $check );
266             }
267              
268 2151 100 66     7075 return undef if ( $check && length($uni) );
269 2150 50       7684 return defined( $_[0] ) ? length($string) : undef;
270             }
271              
272             sub encode_utf8($) {
273 378     378 1 45809 my ($str) = @_;
274 378 100       1171 return undef unless defined $str;
275 376         1321 utf8::encode($str);
276 376         1460 return $str;
277             }
278              
279             my $utf8enc;
280              
281             sub decode_utf8($;$) {
282 19     19 1 25061 my ( $octets, $check ) = @_;
283 19 100       127 return undef unless defined $octets;
284 16         53 $octets .= '';
285 16   100     117 $check ||= 0;
286 16   66     103 $utf8enc ||= find_encoding('utf8');
287 16         189 my $string = $utf8enc->decode( $octets, $check );
288 14 50 66     110 $_[0] = $octets if $check and !ref $check and !( $check & LEAVE_SRC );
      66        
289 14         113 return $string;
290             }
291              
292             onBOOT;
293              
294             if ($ON_EBCDIC) {
295             package Encode::UTF_EBCDIC;
296 40     40   26066 use parent 'Encode::Encoding';
  40         13483  
  40         297  
297             my $obj = bless { Name => "UTF_EBCDIC" } => "Encode::UTF_EBCDIC";
298             Encode::define_encoding($obj, 'Unicode');
299             sub decode {
300 0     0   0 my ( undef, $str, $chk ) = @_;
301 0         0 my $res = '';
302 0         0 for ( my $i = 0 ; $i < length($str) ; $i++ ) {
303 0         0 $res .=
304             chr(
305             utf8::unicode_to_native( ord( substr( $str, $i, 1 ) ) )
306             );
307             }
308 0 0       0 $_[1] = '' if $chk;
309 0         0 return $res;
310             }
311             sub encode {
312 0     0   0 my ( undef, $str, $chk ) = @_;
313 0         0 my $res = '';
314 0         0 for ( my $i = 0 ; $i < length($str) ; $i++ ) {
315 0         0 $res .=
316             chr(
317             utf8::native_to_unicode( ord( substr( $str, $i, 1 ) ) )
318             );
319             }
320 0 0       0 $_[1] = '' if $chk;
321 0         0 return $res;
322             }
323             } else {
324             package Encode::Internal;
325 40     40   14738 use parent 'Encode::Encoding';
  40         120  
  40         252  
326             my $obj = bless { Name => "Internal" } => "Encode::Internal";
327             Encode::define_encoding($obj, 'Unicode');
328             sub decode {
329 3     3   7 my ( undef, $str, $chk ) = @_;
330 3         10 utf8::upgrade($str);
331 3 50       8 $_[1] = '' if $chk;
332 3         8 return $str;
333             }
334             *encode = \&decode;
335             }
336              
337             {
338             # https://rt.cpan.org/Public/Bug/Display.html?id=103253
339             package Encode::XS;
340 40     40   7205 use parent 'Encode::Encoding';
  40         130  
  40         229  
341             }
342              
343             {
344             package Encode::utf8;
345             BEGIN {
346 40     40   4875 $Encode::Encoding{utf8} = bless { Name => 'utf8' } => __PACKAGE__;
347             }
348 40     40   330 use parent 'Encode::Encoding';
  40         125  
  40         228  
349             my $strict_obj =
350             bless { Name => 'utf-8-strict', strict_utf8 => 1 } => __PACKAGE__;
351             Encode::define_encoding($strict_obj, 'utf-8-strict');
352             sub cat_decode {
353             # ($obj, $dst, $src, $pos, $trm, $chk)
354             # currently ignores $chk
355 32     32   136 my ( undef, undef, undef, $pos, $trm ) = @_;
356 32         124 my ( $rdst, $rsrc, $rpos ) = \@_[ 1, 2, 3 ];
357 40     40   35484 use bytes;
  40         735  
  40         272  
358 32 50       163 if ( ( my $npos = index( $$rsrc, $trm, $pos ) ) >= 0 ) {
359 32         236 $$rdst .=
360             substr( $$rsrc, $pos, $npos - $pos + length($trm) );
361 32         137 $$rpos = $npos + length($trm);
362 32         3363 return 1;
363             }
364 0           $$rdst .= substr( $$rsrc, $pos );
365 0           $$rpos = length($$rsrc);
366 0           return '';
367             }
368             }
369              
370             1;
371              
372             __END__