File Coverage

blib/lib/Encode.pm
Criterion Covered Total %
statement 164 209 78.4
branch 62 94 65.9
condition 34 40 85.0
subroutine 30 36 83.3
pod 8 15 53.3
total 298 394 75.6


line stmt bran cond sub pod time code
1             #
2             # $Id: Encode.pm,v 2.92 2017/07/18 07:15:29 dankogai Exp dankogai $
3             #
4             package Encode;
5 41     41   281543 use strict;
  41         96  
  41         1124  
6 41     41   1127 use warnings;
  41         81  
  41         1500  
7 41     41   205 use constant DEBUG => !!$ENV{PERL_ENCODE_DEBUG};
  41         85  
  41         5076  
8             our $VERSION;
9             BEGIN {
10 41     41   525 $VERSION = sprintf "%d.%02d", q$Revision: 2.92 $ =~ /(\d+)/g;
11 41         217 require XSLoader;
12 41         19239 XSLoader::load( __PACKAGE__, $VERSION );
13             }
14              
15 41     41   326 use Exporter 5.57 'import';
  41         786  
  41         6575  
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 41     41   14420 use Encode::Alias ();
  41         129  
  41         1810  
53 41     41   17463 use Encode::MIME::Name;
  41         127  
  41         1467  
54              
55 41     41   23834 use Storable;
  41         113382  
  41         70320  
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 112 my %enc;
74 4   100     24 my $arg = $_[1] || '';
75 4 100       20 if ( $arg eq ":all" ) {
76 3         164 %enc = ( %Encoding, %ExtModule );
77             }
78             else {
79 1         17 %enc = %Encoding;
80 1 0       8 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 2142         3158 return sort { lc $a cmp lc $b }
88 4         59 grep { !/^(?:Internal|Unicode|Guess)$/o } keys %enc;
  383         723  
89             }
90              
91             sub perlio_ok {
92 16 50   16 0 9546 my $obj = ref( $_[0] ) ? $_[0] : find_encoding( $_[0] );
93 16 50       538 $obj->can("perlio_ok") and return $obj->perlio_ok();
94 0         0 return 0; # safety net
95             }
96              
97             sub define_encoding {
98 1366     1366 0 2451 my $obj = shift;
99 1366         2145 my $name = shift;
100 1366         3019 $Encoding{$name} = $obj;
101 1366         2402 my $lc = lc($name);
102 1366 100       3596 define_alias( $lc => $obj ) unless $lc eq $name;
103 1366         3179 while (@_) {
104 0         0 my $alias = shift;
105 0         0 define_alias( $alias, $obj );
106             }
107 1366         2315 my $class = ref($obj);
108 1366 100       2366 push @Encode::CARP_NOT, $class unless grep { $_ eq $class } @Encode::CARP_NOT;
  6094         12369  
109 1366 100       2330 push @Encode::Encoding::CARP_NOT, $class unless grep { $_ eq $class } @Encode::Encoding::CARP_NOT;
  7460         13438  
110 1366         5119 return $obj;
111             }
112              
113             sub getEncoding {
114 61771     61771 0 106730 my ( $class, $name, $skip_external ) = @_;
115              
116 61771 100       137155 defined($name) or return;
117              
118 61752         124767 $name =~ s/\s+//g; # https://rt.cpan.org/Ticket/Display.html?id=65796
119              
120 61752 100 66     145952 ref($name) && $name->can('renew') and return $name;
121 61749 100       214911 exists $Encoding{$name} and return $Encoding{$name};
122 3280         6889 my $lc = lc $name;
123 3280 100       7644 exists $Encoding{$lc} and return $Encoding{$lc};
124              
125 3229         7460 my $oc = $class->find_alias($name);
126 3229 100       10314 defined($oc) and return $oc;
127 478 100       1495 $lc ne $name and $oc = $class->find_alias($lc);
128 478 50       1123 defined($oc) and return $oc;
129              
130 478 50       1130 unless ($skip_external) {
131 478 100 66     2365 if ( my $mod = $ExtModule{$name} || $ExtModule{$lc} ) {
132 81         362 $mod =~ s,::,/,g;
133 81         194 $mod .= '.pm';
134 81         172 eval { require $mod; };
  81         38464  
135 81 50       668 exists $Encoding{$name} and return $Encoding{$name};
136             }
137             }
138 397         1054 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 3513     3513 0 13277 goto &Encode::Alias::find_alias;
145             }
146             sub define_alias {
147 358     358 0 1345 goto &Encode::Alias::define_alias;
148             }
149              
150             sub find_encoding($;$) {
151 61766     61766 1 515854 my ( $name, $skip_external ) = @_;
152 61766         137503 return __PACKAGE__->getEncoding( $name, $skip_external );
153             }
154              
155             sub find_mime_encoding($;$) {
156 50353     50353 1 117848 my ( $mime_name, $skip_external ) = @_;
157 50353         107556 my $name = Encode::MIME::Name::get_encode_name( $mime_name );
158 50353         102119 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 2285     2285 1 689724 my ( $name, $string, $check ) = @_;
175 2285 100       6231 return undef unless defined $string;
176 2152         6475 $string .= ''; # stringify;
177 2152   100     6293 $check ||= 0;
178 2152 50       4326 unless ( defined $name ) {
179 0         0 require Carp;
180 0         0 Carp::croak("Encoding name should not be undef");
181             }
182 2152         4242 my $enc = find_encoding($name);
183 2152 50       4842 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 2152         3008 my $octets;
190 2152 100       4925 if ( ref($enc) eq 'Encode::Unicode' ) {
191 72         126 my $warn = '';
192             {
193 72     0   114 local $SIG{__WARN__} = sub { $warn = shift };
  72         461  
  0         0  
194 72         48819 $octets = $enc->encode( $string, $check );
195             }
196 70 50       275 warnings::warnif('utf8', $warn) if length $warn;
197             }
198             else {
199 2080         118368 $octets = $enc->encode( $string, $check );
200             }
201 2020 100 100     14810 $_[1] = $string if $check and !ref $check and !( $check & LEAVE_SRC );
      100        
202 2020         7341 return $octets;
203             }
204             *str2bytes = \&encode;
205              
206             sub decode($$;$) {
207 1530     1530 1 441978 my ( $name, $octets, $check ) = @_;
208 1530 100       4871 return undef unless defined $octets;
209 1397         7961 $octets .= '';
210 1397   100     5178 $check ||= 0;
211 1397         3295 my $enc = find_encoding($name);
212 1397 50       3221 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         1971 my $string;
219 1397 100       3392 if ( ref($enc) eq 'Encode::Unicode' ) {
220 61         103 my $warn = '';
221             {
222 61     3   101 local $SIG{__WARN__} = sub { $warn = shift };
  61         360  
  3         19  
223 61         38087 $string = $enc->decode( $octets, $check );
224             }
225 59 100       624 warnings::warnif('utf8', $warn) if length $warn;
226             }
227             else {
228 1336         76923 $string = $enc->decode( $octets, $check );
229             }
230 1263 100 100     5119 $_[1] = $octets if $check and !ref $check and !( $check & LEAVE_SRC );
      100        
231 1263         6935 return $string;
232             }
233             *bytes2str = \&decode;
234              
235             sub from_to($$$;$) {
236 2151     2151 1 1495298 my ( $string, $from, $to, $check ) = @_;
237 2151 50       5764 return undef unless defined $string;
238 2151   100     10573 $check ||= 0;
239 2151         4676 my $f = find_encoding($from);
240 2151 50       5602 unless ( defined $f ) {
241 0         0 require Carp;
242 0         0 Carp::croak("Unknown encoding '$from'");
243             }
244 2151         3996 my $t = find_encoding($to);
245 2151 50       5289 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         3253 my $uni;
253 2151 100       5609 if ( ref($f) eq 'Encode::Unicode' ) {
254 3         5 my $warn = '';
255             {
256 3     3   4 local $SIG{__WARN__} = sub { $warn = shift };
  3         16  
  3         52  
257 3         38 $uni = $f->decode($string);
258             }
259 3 50       389 warnings::warnif('utf8', $warn) if length $warn;
260             }
261             else {
262 2148         9428 $uni = $f->decode($string);
263             }
264              
265 2151 50       5623 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         9245 $_[0] = $string = $t->encode( $uni, $check );
275             }
276              
277 2151 100 66     6144 return undef if ( $check && length($uni) );
278 2150 50       6662 return defined( $_[0] ) ? length($string) : undef;
279             }
280              
281             sub encode_utf8($) {
282 380     380 1 30397 my ($str) = @_;
283 380 100       828 return undef unless defined $str;
284 378         1024 utf8::encode($str);
285 378         1164 return $str;
286             }
287              
288             my $utf8enc;
289              
290             sub decode_utf8($;$) {
291 19     19 1 16777 my ( $octets, $check ) = @_;
292 19 100       106 return undef unless defined $octets;
293 16         46 $octets .= '';
294 16   100     89 $check ||= 0;
295 16   66     75 $utf8enc ||= find_encoding('utf8');
296 16         151 my $string = $utf8enc->decode( $octets, $check );
297 14 50 66     85 $_[0] = $octets if $check and !ref $check and !( $check & LEAVE_SRC );
      66        
298 14         99 return $string;
299             }
300              
301             onBOOT;
302              
303             if ($ON_EBCDIC) {
304             package Encode::UTF_EBCDIC;
305 41     41   18970 use parent 'Encode::Encoding';
  41         10386  
  41         226  
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 41     41   10610 use parent 'Encode::Encoding';
  41         141  
  41         219  
335             my $obj = bless { Name => "Internal" } => "Encode::Internal";
336             Encode::define_encoding($obj, 'Unicode');
337             sub decode {
338 3     3   12 my ( undef, $str, $chk ) = @_;
339 3         14 utf8::upgrade($str);
340 3 50       10 $_[1] = '' if $chk;
341 3         11 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 41     41   6076 use parent 'Encode::Encoding';
  41         108  
  41         159  
350             }
351              
352             {
353             package Encode::utf8;
354 41     41   2725 use parent 'Encode::Encoding';
  41         93  
  41         146  
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 32     32   75 my ( undef, undef, undef, $pos, $trm ) = @_;
367 32         68 my ( $rdst, $rsrc, $rpos ) = \@_[ 1, 2, 3 ];
368 41     41   27563 use bytes;
  41         568  
  41         216  
369 32 50       95 if ( ( my $npos = index( $$rsrc, $trm, $pos ) ) >= 0 ) {
370 32         68 $$rdst .=
371             substr( $$rsrc, $pos, $npos - $pos + length($trm) );
372 32         47 $$rpos = $npos + length($trm);
373 32         1515 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__