File Coverage

blib/lib/Encode.pm
Criterion Covered Total %
statement 158 209 75.6
branch 61 94 64.8
condition 34 40 85.0
subroutine 29 36 80.5
pod 8 15 53.3
total 290 394 73.6


line stmt bran cond sub pod time code
1             #
2             # $Id: Encode.pm,v 2.93 2017/10/06 22:21:33 dankogai Exp $
3             #
4             package Encode;
5 35     35   853781 use strict;
  35         406  
  35         1035  
6 35     35   168 use warnings;
  35         72  
  35         1296  
7 35     35   175 use constant DEBUG => !!$ENV{PERL_ENCODE_DEBUG};
  35         55  
  35         4256  
8             our $VERSION;
9             BEGIN {
10 35     35   436 $VERSION = sprintf "%d.%02d", q$Revision: 2.93 $ =~ /(\d+)/g;
11 35         195 require XSLoader;
12 35         14896 XSLoader::load( __PACKAGE__, $VERSION );
13             }
14              
15 35     35   259 use Exporter 5.57 'import';
  35         673  
  35         6128  
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 35     35   10112 use Encode::Alias ();
  35         101  
  35         1018  
53 35     35   10191 use Encode::MIME::Name;
  35         100  
  35         1211  
54              
55 35     35   14838 use Storable;
  35         95126  
  35         58267  
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 296 my %enc;
74 4   100     21 my $arg = $_[1] || '';
75 4 100       22 if ( $arg eq ":all" ) {
76 3         180 %enc = ( %Encoding, %ExtModule );
77             }
78             else {
79 1         9 %enc = %Encoding;
80 1 0       4 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 2153         2879 return sort { lc $a cmp lc $b }
88 4         62 grep { !/^(?:Internal|Unicode|Guess)$/o } keys %enc;
  383         799  
89             }
90              
91             sub perlio_ok {
92 16 50   16 0 8768 my $obj = ref( $_[0] ) ? $_[0] : find_encoding( $_[0] );
93 16 50       620 $obj->can("perlio_ok") and return $obj->perlio_ok();
94 0         0 return 0; # safety net
95             }
96              
97             sub define_encoding {
98 1214     1214 0 1947 my $obj = shift;
99 1214         1591 my $name = shift;
100 1214         2224 $Encoding{$name} = $obj;
101 1214         1827 my $lc = lc($name);
102 1214 100       2539 define_alias( $lc => $obj ) unless $lc eq $name;
103 1214         2255 while (@_) {
104 0         0 my $alias = shift;
105 0         0 define_alias( $alias, $obj );
106             }
107 1214         1763 my $class = ref($obj);
108 1214 100       1734 push @Encode::CARP_NOT, $class unless grep { $_ eq $class } @Encode::CARP_NOT;
  5664         10060  
109 1214 100       1708 push @Encode::Encoding::CARP_NOT, $class unless grep { $_ eq $class } @Encode::Encoding::CARP_NOT;
  6878         11102  
110 1214         4667 return $obj;
111             }
112              
113             sub getEncoding {
114 61726     61726 0 92815 my ( $class, $name, $skip_external ) = @_;
115              
116 61726 100       106753 defined($name) or return;
117              
118 61707         107164 $name =~ s/\s+//g; # https://rt.cpan.org/Ticket/Display.html?id=65796
119              
120 61707 100 66     107132 ref($name) && $name->can('renew') and return $name;
121 61704 100       172042 exists $Encoding{$name} and return $Encoding{$name};
122 3266         5600 my $lc = lc $name;
123 3266 100       6305 exists $Encoding{$lc} and return $Encoding{$lc};
124              
125 3215         6240 my $oc = $class->find_alias($name);
126 3215 100       9190 defined($oc) and return $oc;
127 473 100       1250 $lc ne $name and $oc = $class->find_alias($lc);
128 473 50       875 defined($oc) and return $oc;
129              
130 473 50       857 unless ($skip_external) {
131 473 100 66     1914 if ( my $mod = $ExtModule{$name} || $ExtModule{$lc} ) {
132 76         332 $mod =~ s,::,/,g;
133 76         187 $mod .= '.pm';
134 76         135 eval { require $mod; };
  76         28282  
135 76 50       590 exists $Encoding{$name} and return $Encoding{$name};
136             }
137             }
138 397         1009 return;
139             }
140              
141             # HACK: These two functions must be defined in Encode and because of
142             # cyclic dependency between Encode and Encode::Alias, Exporter does not work
143             sub find_alias {
144 3499     3499 0 12184 goto &Encode::Alias::find_alias;
145             }
146             sub define_alias {
147 332     332 0 1041 goto &Encode::Alias::define_alias;
148             }
149              
150             sub find_encoding($;$) {
151 61721     61721 1 387582 my ( $name, $skip_external ) = @_;
152 61721         113447 return __PACKAGE__->getEncoding( $name, $skip_external );
153             }
154              
155             sub find_mime_encoding($;$) {
156 50354     50354 1 110228 my ( $mime_name, $skip_external ) = @_;
157 50354         87271 my $name = Encode::MIME::Name::get_encode_name( $mime_name );
158 50354         88313 return find_encoding( $name, $skip_external );
159             }
160              
161             sub resolve_alias($) {
162 0     0 0 0 my $obj = find_encoding(shift);
163 0 0       0 defined $obj and return $obj->name;
164 0         0 return;
165             }
166              
167             sub clone_encoding($) {
168 0     0 0 0 my $obj = find_encoding(shift);
169 0 0       0 ref $obj or return;
170 0         0 return Storable::dclone($obj);
171             }
172              
173             sub encode($$;$) {
174 2284     2284 1 644277 my ( $name, $string, $check ) = @_;
175 2284 100       5114 return undef unless defined $string;
176 2151         6191 $string .= ''; # stringify;
177 2151   100     5192 $check ||= 0;
178 2151 50       3415 unless ( defined $name ) {
179 0         0 require Carp;
180 0         0 Carp::croak("Encoding name should not be undef");
181             }
182 2151         3374 my $enc = find_encoding($name);
183 2151 50       3794 unless ( defined $enc ) {
184 0         0 require Carp;
185 0         0 Carp::croak("Unknown encoding '$name'");
186             }
187             # For Unicode, warnings need to be caught and re-issued at this level
188             # so that callers can disable utf8 warnings lexically.
189 2151         2372 my $octets;
190 2151 100       4161 if ( ref($enc) eq 'Encode::Unicode' ) {
191 72         116 my $warn = '';
192             {
193 72     0   100 local $SIG{__WARN__} = sub { $warn = shift };
  72         471  
  0         0  
194 72         53168 $octets = $enc->encode( $string, $check );
195             }
196 70 50       284 warnings::warnif('utf8', $warn) if length $warn;
197             }
198             else {
199 2079         125395 $octets = $enc->encode( $string, $check );
200             }
201 2019 100 100     12103 $_[1] = $string if $check and !ref $check and !( $check & LEAVE_SRC );
      100        
202 2019         6564 return $octets;
203             }
204             *str2bytes = \&encode;
205              
206             sub decode($$;$) {
207 1530     1530 1 402845 my ( $name, $octets, $check ) = @_;
208 1530 100       4348 return undef unless defined $octets;
209 1397         7234 $octets .= '';
210 1397   100     4776 $check ||= 0;
211 1397         2586 my $enc = find_encoding($name);
212 1397 50       2770 unless ( defined $enc ) {
213 0         0 require Carp;
214 0         0 Carp::croak("Unknown encoding '$name'");
215             }
216             # For Unicode, warnings need to be caught and re-issued at this level
217             # so that callers can disable utf8 warnings lexically.
218 1397         1752 my $string;
219 1397 100       3125 if ( ref($enc) eq 'Encode::Unicode' ) {
220 61         91 my $warn = '';
221             {
222 61     3   84 local $SIG{__WARN__} = sub { $warn = shift };
  61         367  
  3         18  
223 61         38938 $string = $enc->decode( $octets, $check );
224             }
225 59 100       668 warnings::warnif('utf8', $warn) if length $warn;
226             }
227             else {
228 1336         82934 $string = $enc->decode( $octets, $check );
229             }
230 1263 100 100     4265 $_[1] = $octets if $check and !ref $check and !( $check & LEAVE_SRC );
      100        
231 1263         7068 return $string;
232             }
233             *bytes2str = \&decode;
234              
235             sub from_to($$$;$) {
236 2151     2151 1 1332942 my ( $string, $from, $to, $check ) = @_;
237 2151 50       5220 return undef unless defined $string;
238 2151   100     7977 $check ||= 0;
239 2151         3956 my $f = find_encoding($from);
240 2151 50       4114 unless ( defined $f ) {
241 0         0 require Carp;
242 0         0 Carp::croak("Unknown encoding '$from'");
243             }
244 2151         3458 my $t = find_encoding($to);
245 2151 50       4034 unless ( defined $t ) {
246 0         0 require Carp;
247 0         0 Carp::croak("Unknown encoding '$to'");
248             }
249              
250             # For Unicode, warnings need to be caught and re-issued at this level
251             # so that callers can disable utf8 warnings lexically.
252 2151         2540 my $uni;
253 2151 100       4742 if ( ref($f) eq 'Encode::Unicode' ) {
254 3         6 my $warn = '';
255             {
256 3     3   4 local $SIG{__WARN__} = sub { $warn = shift };
  3         15  
  3         20  
257 3         38 $uni = $f->decode($string);
258             }
259 3 50       395 warnings::warnif('utf8', $warn) if length $warn;
260             }
261             else {
262 2148         8531 $uni = $f->decode($string);
263             }
264              
265 2151 50       4728 if ( ref($t) eq 'Encode::Unicode' ) {
266 0         0 my $warn = '';
267             {
268 0     0   0 local $SIG{__WARN__} = sub { $warn = shift };
  0         0  
  0         0  
269 0         0 $_[0] = $string = $t->encode( $uni, $check );
270             }
271 0 0       0 warnings::warnif('utf8', $warn) if length $warn;
272             }
273             else {
274 2151         7660 $_[0] = $string = $t->encode( $uni, $check );
275             }
276              
277 2151 100 66     5080 return undef if ( $check && length($uni) );
278 2150 50       5772 return defined( $_[0] ) ? length($string) : undef;
279             }
280              
281             sub encode_utf8($) {
282 380     380 1 25673 my ($str) = @_;
283 380 100       773 return undef unless defined $str;
284 378         1114 utf8::encode($str);
285 378         1183 return $str;
286             }
287              
288             my $utf8enc;
289              
290             sub decode_utf8($;$) {
291 19     19 1 16166 my ( $octets, $check ) = @_;
292 19 100       85 return undef unless defined $octets;
293 16         45 $octets .= '';
294 16   100     81 $check ||= 0;
295 16   66     59 $utf8enc ||= find_encoding('utf8');
296 16         117 my $string = $utf8enc->decode( $octets, $check );
297 14 50 66     64 $_[0] = $octets if $check and !ref $check and !( $check & LEAVE_SRC );
      66        
298 14         82 return $string;
299             }
300              
301             onBOOT;
302              
303             if ($ON_EBCDIC) {
304             package Encode::UTF_EBCDIC;
305 35     35   9905 use parent 'Encode::Encoding';
  35         8706  
  35         169  
306             my $obj = bless { Name => "UTF_EBCDIC" } => "Encode::UTF_EBCDIC";
307             Encode::define_encoding($obj, 'Unicode');
308             sub decode {
309 0     0   0 my ( undef, $str, $chk ) = @_;
310 0         0 my $res = '';
311 0         0 for ( my $i = 0 ; $i < length($str) ; $i++ ) {
312 0         0 $res .=
313             chr(
314             utf8::unicode_to_native( ord( substr( $str, $i, 1 ) ) )
315             );
316             }
317 0 0       0 $_[1] = '' if $chk;
318 0         0 return $res;
319             }
320             sub encode {
321 0     0   0 my ( undef, $str, $chk ) = @_;
322 0         0 my $res = '';
323 0         0 for ( my $i = 0 ; $i < length($str) ; $i++ ) {
324 0         0 $res .=
325             chr(
326             utf8::native_to_unicode( ord( substr( $str, $i, 1 ) ) )
327             );
328             }
329 0 0       0 $_[1] = '' if $chk;
330 0         0 return $res;
331             }
332             } else {
333             package Encode::Internal;
334 35     35   8329 use parent 'Encode::Encoding';
  35         66  
  35         154  
335             my $obj = bless { Name => "Internal" } => "Encode::Internal";
336             Encode::define_encoding($obj, 'Unicode');
337             sub decode {
338 3     3   6 my ( undef, $str, $chk ) = @_;
339 3         7 utf8::upgrade($str);
340 3 50       6 $_[1] = '' if $chk;
341 3         5 return $str;
342             }
343             *encode = \&decode;
344             }
345              
346             {
347             # https://rt.cpan.org/Public/Bug/Display.html?id=103253
348             package Encode::XS;
349 35     35   4671 use parent 'Encode::Encoding';
  35         67  
  35         112  
350             }
351              
352             {
353             package Encode::utf8;
354 35     35   2154 use parent 'Encode::Encoding';
  35         73  
  35         109  
355             my %obj = (
356             'utf8' => { Name => 'utf8' },
357             'utf-8-strict' => { Name => 'utf-8-strict', strict_utf8 => 1 }
358             );
359             for ( keys %obj ) {
360             bless $obj{$_} => __PACKAGE__;
361             Encode::define_encoding( $obj{$_} => $_ );
362             }
363             sub cat_decode {
364             # ($obj, $dst, $src, $pos, $trm, $chk)
365             # currently ignores $chk
366 0     0     my ( undef, undef, undef, $pos, $trm ) = @_;
367 0           my ( $rdst, $rsrc, $rpos ) = \@_[ 1, 2, 3 ];
368 35     35   17442 use bytes;
  35         470  
  35         170  
369 0 0         if ( ( my $npos = index( $$rsrc, $trm, $pos ) ) >= 0 ) {
370 0           $$rdst .=
371             substr( $$rsrc, $pos, $npos - $pos + length($trm) );
372 0           $$rpos = $npos + length($trm);
373 0           return 1;
374             }
375 0           $$rdst .= substr( $$rsrc, $pos );
376 0           $$rpos = length($$rsrc);
377 0           return '';
378             }
379             }
380              
381             1;
382              
383             __END__