File Coverage

blib/lib/encoding.pm
Criterion Covered Total %
statement 90 143 62.9
branch 25 68 36.7
condition 6 19 31.5
subroutine 15 16 93.7
pod 0 1 0.0
total 136 247 55.0


line stmt bran cond sub pod time code
1             # $Id: encoding.pm,v 2.20 2017/06/10 17:23:50 dankogai Exp $
2             package encoding;
3             our $VERSION = sprintf "%d.%02d", q$Revision: 2.20 $ =~ /(\d+)/g;
4              
5 7     7   82534 use Encode;
  7         39  
  7         827  
6 7     7   68 use strict;
  7         21  
  7         211  
7 7     7   49 use warnings;
  7         19  
  7         230  
8 7     7   53 use Config;
  7         19  
  7         720  
9              
10             use constant {
11             DEBUG => !!$ENV{PERL_ENCODE_DEBUG},
12 7   33     24 HAS_PERLIO => eval { require PerlIO::encoding; PerlIO::encoding->VERSION(0.02) },
  7         4229  
  7         6537  
13             PERL_5_21_7 => $^V && $^V ge v5.21.7, # lexically scoped
14 7     7   56 };
  7         20  
15              
16             sub _exception {
17 8     8   27 my $name = shift;
18 8 50       63 $] > 5.008 and return 0; # 5.8.1 or higher then no
19 0         0 my %utfs = map { $_ => 1 }
  0         0  
20             qw(utf8 UCS-2BE UCS-2LE UTF-16 UTF-16BE UTF-16LE
21             UTF-32 UTF-32BE UTF-32LE);
22 0 0       0 $utfs{$name} or return 0; # UTFs or no
23 0         0 require Config;
24 0         0 Config->import();
25 0         0 our %Config;
26 0 0       0 return $Config{perl_patchlevel} ? 0 : 1 # maintperl then no
27             }
28              
29 0   0 0 0 0 sub in_locale { $^H & ( $locale::hint_bits || 0 ) }
30              
31             sub _get_locale_encoding {
32 1     1   11 my $locale_encoding;
33              
34 1 50       8 if ($^O eq 'MSWin32') {
35 0         0 my @tries = (
36             # First try to get the OutputCP. This will work only if we
37             # are attached to a console
38             'Win32.pm' => 'Win32::GetConsoleOutputCP',
39             'Win32/Console.pm' => 'Win32::Console::OutputCP',
40             # If above failed, this means that we are a GUI app
41             # Let's assume that the ANSI codepage is what matters
42             'Win32.pm' => 'Win32::GetACP',
43             );
44 0         0 while (@tries) {
45 0         0 my $cp = eval {
46 0         0 require $tries[0];
47 7     7   67 no strict 'refs';
  7         20  
  7         4746  
48 0         0 &{$tries[1]}()
  0         0  
49             };
50 0 0       0 if ($cp) {
51 0 0       0 if ($cp == 65001) { # Code page for UTF-8
52 0         0 $locale_encoding = 'UTF-8';
53             } else {
54 0         0 $locale_encoding = 'cp' . $cp;
55             }
56 0         0 return $locale_encoding;
57             }
58 0         0 splice(@tries, 0, 2)
59             }
60             }
61              
62             # I18N::Langinfo isn't available everywhere
63 1         3 $locale_encoding = eval {
64 1         633 require I18N::Langinfo;
65 1         757 find_encoding(
66             I18N::Langinfo::langinfo( I18N::Langinfo::CODESET() )
67             )->name
68             };
69 1 50       9 return $locale_encoding if defined $locale_encoding;
70              
71 0         0 eval {
72 0         0 require POSIX;
73             # Get the current locale
74             # Remember that MSVCRT impl is quite different from Unixes
75 0         0 my $locale = POSIX::setlocale(POSIX::LC_CTYPE());
76 0 0       0 if ( $locale =~ /^([^.]+)\.([^.@]+)(?:@.*)?$/ ) {
77 0         0 my $country_language;
78 0         0 ( $country_language, $locale_encoding ) = ( $1, $2 );
79              
80             # Could do more heuristics based on the country and language
81             # since we have Locale::Country and Locale::Language available.
82             # TODO: get a database of Language -> Encoding mappings
83             # (the Estonian database at http://www.eki.ee/letter/
84             # would be excellent!) --jhi
85 0 0       0 if (lc($locale_encoding) eq 'euc') {
86 0 0       0 if ( $country_language =~ /^ja_JP|japan(?:ese)?$/i ) {
    0          
    0          
    0          
87 0         0 $locale_encoding = 'euc-jp';
88             }
89             elsif ( $country_language =~ /^ko_KR|korean?$/i ) {
90 0         0 $locale_encoding = 'euc-kr';
91             }
92             elsif ( $country_language =~ /^zh_CN|chin(?:a|ese)$/i ) {
93 0         0 $locale_encoding = 'euc-cn';
94             }
95             elsif ( $country_language =~ /^zh_TW|taiwan(?:ese)?$/i ) {
96 0         0 $locale_encoding = 'euc-tw';
97             }
98             else {
99 0         0 require Carp;
100 0         0 Carp::croak(
101             "encoding: Locale encoding '$locale_encoding' too ambiguous"
102             );
103             }
104             }
105             }
106             };
107              
108 0         0 return $locale_encoding;
109             }
110              
111             sub import {
112              
113 9     9   220 if ( ord("A") == 193 ) {
114             require Carp;
115             Carp::croak("encoding: pragma does not support EBCDIC platforms");
116             }
117              
118             my $deprecate =
119             ($] >= 5.017 and !$Config{usecperl})
120 9 50 33     713 ? "Use of the encoding pragma is deprecated" : 0;
121              
122 9         44 my $class = shift;
123 9         27 my $name = shift;
124 9 50       40 if (!$name){
125 0         0 require Carp;
126 0         0 Carp::croak("encoding: no encoding specified.");
127             }
128 9 50       41 if ( $name eq ':_get_locale_encoding' ) { # used by lib/open.pm
129 0         0 my $caller = caller();
130             {
131 7     7   69 no strict 'refs';
  7         25  
  7         812  
  0         0  
132 0         0 *{"${caller}::_get_locale_encoding"} = \&_get_locale_encoding;
  0         0  
133             }
134 0         0 return;
135             }
136 9 50       41 $name = _get_locale_encoding() if $name eq ':locale';
137 7 50 33 7   3770 BEGIN { strict->unimport('hashpairs') if $] >= 5.027 and $^V =~ /c$/; }
138 9         35 my %arg = @_;
139 9 50       35 $name = $ENV{PERL_ENCODING} unless defined $name;
140 9         45 my $enc = find_encoding($name);
141 9 50       44 unless ( defined $enc ) {
142 0         0 require Carp;
143 0         0 Carp::croak("encoding: Unknown encoding '$name'");
144             }
145 9         104 $name = $enc->name; # canonize
146 9 100       47 unless ( $arg{Filter} ) {
147 8 50 33     50 if ($] >= 5.025003 and !$Config{usecperl}) {
148 0         0 require Carp;
149 0         0 Carp::croak("The encoding pragma is no longer supported. Check cperl");
150             }
151 8 50       863 warnings::warnif("deprecated",$deprecate) if $deprecate;
152              
153 8         31 DEBUG and warn "_exception($name) = ", _exception($name);
154 8 50       39 if (! _exception($name)) {
155 8         23 if (!PERL_5_21_7) {
156             ${^ENCODING} = $enc;
157             }
158             else {
159             # Starting with 5.21.7, this pragma uses a shadow variable
160             # designed explicitly for it, ${^E_NCODING}, to enforce
161             # lexical scope; instead of ${^ENCODING}.
162 8         48 $^H{'encoding'} = 1;
163 8         41 ${^E_NCODING} = $enc;
164             }
165             }
166 8         23 if (! HAS_PERLIO ) {
167             return 1;
168             }
169             }
170             else {
171 1 50       52 warnings::warnif("deprecated",$deprecate) if $deprecate;
172              
173 1 50       5 defined( ${^ENCODING} ) and undef ${^ENCODING};
174 1         3 undef ${^E_NCODING} if PERL_5_21_7;
175              
176             # implicitly 'use utf8'
177 1         6 require utf8; # to fetch $utf8::hint_bits;
178 1         3 $^H |= $utf8::hint_bits;
179 1 50 50     2 eval {
180 1         675 require Filter::Util::Call;
181 1         898 Filter::Util::Call->import;
182             filter_add(
183             sub {
184 11     11   60 my $status = filter_read();
185 11 50       26 if ( $status > 0 ) {
186 11         40 $_ = $enc->decode( $_, 1 );
187 11         17 DEBUG and warn $_;
188             }
189 11         125 $status;
190             }
191 1         9 );
192 1         20 1;
193             } and DEBUG and warn "Filter installed";
194             }
195 9 50 33     90 defined ${^UNICODE} and ${^UNICODE} != 0 and return 1;
196 9         31 for my $h (qw(STDIN STDOUT)) {
197 18 50       71 if ( $arg{$h} ) {
198 0 0       0 unless ( defined find_encoding( $arg{$h} ) ) {
199 0         0 require Carp;
200 0         0 Carp::croak(
201             "encoding: Unknown encoding for $h, '$arg{$h}'");
202             }
203 0         0 eval { binmode( $h, ":raw :encoding($arg{$h})" ) };
  0         0  
204             }
205             else {
206 18 50       68 unless ( exists $arg{$h} ) {
207 18         46 eval {
208 7     7   68 no warnings 'uninitialized';
  7         24  
  7         1275  
209 18         271 binmode( $h, ":raw :encoding($name)" );
210             };
211             }
212             }
213 18 50       90 if ($@) {
214 0         0 require Carp;
215 0         0 Carp::croak($@);
216             }
217             }
218 9         2021 return 1; # I doubt if we need it, though
219             }
220              
221             sub unimport {
222 7     7   64 no warnings;
  7         21  
  7         1071  
223 3     3   148 undef ${^ENCODING};
224 3         8 undef ${^E_NCODING} if PERL_5_21_7;
225 3         5 if (HAS_PERLIO) {
226 3         13 binmode( STDIN, ":raw" );
227 3         9 binmode( STDOUT, ":raw" );
228             }
229             else {
230             binmode(STDIN);
231             binmode(STDOUT);
232             }
233 3 100       85 if ( $INC{"Filter/Util/Call.pm"} ) {
234 1         2 eval { filter_del() };
  1         1046  
235             }
236             }
237              
238             1;
239             __END__