File Coverage

blib/lib/encoding.pm
Criterion Covered Total %
statement 36 136 26.4
branch 3 64 4.6
condition 2 17 11.7
subroutine 11 16 68.7
pod 0 1 0.0
total 52 234 22.2


line stmt bran cond sub pod time code
1             # $Id: encoding.pm,v 2.21 2017/10/06 22:21:53 dankogai Exp dankogai $
2             package encoding;
3             our $VERSION = sprintf "%d.%02d", q$Revision: 2.21 $ =~ /(\d+)/g;
4              
5 2     2   49615 use Encode;
  2         5  
  2         119  
6 2     2   10 use strict;
  2         4  
  2         30  
7 2     2   8 use warnings;
  2         3  
  2         48  
8 2     2   12 use Config;
  2         4  
  2         142  
9              
10             use constant {
11             DEBUG => !!$ENV{PERL_ENCODE_DEBUG},
12 2   33     4 HAS_PERLIO => eval { require PerlIO::encoding; PerlIO::encoding->VERSION(0.02) },
  2         450  
  2         1059  
13             PERL_5_21_7 => $^V && $^V ge v5.21.7, # lexically scoped
14 2     2   12 };
  2         2  
15              
16             sub _exception {
17 0     0   0 my $name = shift;
18 0 0       0 $] > 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 2     2   72 my $locale_encoding;
33              
34 2 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 2     2   36 no strict 'refs';
  2         3  
  2         836  
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 2         3 $locale_encoding = eval {
64 2         474 require I18N::Langinfo;
65 2         862 find_encoding(
66             I18N::Langinfo::langinfo( I18N::Langinfo::CODESET() )
67             )->name
68             };
69 2 50       9 return $locale_encoding if defined $locale_encoding;
70              
71 0           eval {
72 0           require POSIX;
73             # Get the current locale
74             # Remember that MSVCRT impl is quite different from Unixes
75 0           my $locale = POSIX::setlocale(POSIX::LC_CTYPE());
76 0 0         if ( $locale =~ /^([^.]+)\.([^.@]+)(?:@.*)?$/ ) {
77 0           my $country_language;
78 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         if (lc($locale_encoding) eq 'euc') {
86 0 0         if ( $country_language =~ /^ja_JP|japan(?:ese)?$/i ) {
    0          
    0          
    0          
87 0           $locale_encoding = 'euc-jp';
88             }
89             elsif ( $country_language =~ /^ko_KR|korean?$/i ) {
90 0           $locale_encoding = 'euc-kr';
91             }
92             elsif ( $country_language =~ /^zh_CN|chin(?:a|ese)$/i ) {
93 0           $locale_encoding = 'euc-cn';
94             }
95             elsif ( $country_language =~ /^zh_TW|taiwan(?:ese)?$/i ) {
96 0           $locale_encoding = 'euc-tw';
97             }
98             else {
99 0           require Carp;
100 0           Carp::croak(
101             "encoding: Locale encoding '$locale_encoding' too ambiguous"
102             );
103             }
104             }
105             }
106             };
107              
108 0           return $locale_encoding;
109             }
110              
111             sub import {
112              
113 0     0     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 0 0 0       ? "Use of the encoding pragma is deprecated" : 0;
121              
122 0           my $class = shift;
123 0           my $name = shift;
124 0 0         if (!$name){
125 0           require Carp;
126 0           Carp::croak("encoding: no encoding specified.");
127             }
128 0 0         if ( $name eq ':_get_locale_encoding' ) { # used by lib/open.pm
129 0           my $caller = caller();
130             {
131 2     2   16 no strict 'refs';
  2         4  
  2         157  
  0            
132 0           *{"${caller}::_get_locale_encoding"} = \&_get_locale_encoding;
  0            
133             }
134 0           return;
135             }
136 0 0         $name = _get_locale_encoding() if $name eq ':locale';
137 2 50 33 2   627 BEGIN { strict->unimport('hashpairs') if $] >= 5.027 and $^V =~ /c$/; }
138 0           my %arg = @_;
139 0 0         $name = $ENV{PERL_ENCODING} unless defined $name;
140 0           my $enc = find_encoding($name);
141 0 0         unless ( defined $enc ) {
142 0           require Carp;
143 0           Carp::croak("encoding: Unknown encoding '$name'");
144             }
145 0           $name = $enc->name; # canonize
146 0 0         unless ( $arg{Filter} ) {
147 0 0 0       if ($] >= 5.025003 and !$Config{usecperl}) {
148 0           require Carp;
149 0           Carp::croak("The encoding pragma is no longer supported. Check cperl");
150             }
151 0 0         warnings::warnif("deprecated",$deprecate) if $deprecate;
152              
153 0           DEBUG and warn "_exception($name) = ", _exception($name);
154 0 0         if (! _exception($name)) {
155 0           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 0           $^H{'encoding'} = 1;
163 0           ${^E_NCODING} = $enc;
164             }
165             }
166 0           if (! HAS_PERLIO ) {
167             return 1;
168             }
169             }
170             else {
171 0 0         warnings::warnif("deprecated",$deprecate) if $deprecate;
172              
173 0 0         defined( ${^ENCODING} ) and undef ${^ENCODING};
174 0           undef ${^E_NCODING} if PERL_5_21_7;
175              
176             # implicitly 'use utf8'
177 0           require utf8; # to fetch $utf8::hint_bits;
178 0           $^H |= $utf8::hint_bits;
179              
180 0           require Filter::Util::Call;
181 0           Filter::Util::Call->import;
182             filter_add(
183             sub {
184 0     0     my $status = filter_read();
185 0 0         if ( $status > 0 ) {
186 0           $_ = $enc->decode( $_, 1 );
187 0           DEBUG and warn $_;
188             }
189 0           $status;
190             }
191 0           );
192             }
193 0 0 0       defined ${^UNICODE} and ${^UNICODE} != 0 and return 1;
194 0           for my $h (qw(STDIN STDOUT)) {
195 0 0         if ( $arg{$h} ) {
196 0 0         unless ( defined find_encoding( $arg{$h} ) ) {
197 0           require Carp;
198 0           Carp::croak(
199             "encoding: Unknown encoding for $h, '$arg{$h}'");
200             }
201 0           binmode( $h, ":raw :encoding($arg{$h})" );
202             }
203             else {
204 0 0         unless ( exists $arg{$h} ) {
205 2     2   11 no warnings 'uninitialized';
  2         3  
  2         205  
206 0           binmode( $h, ":raw :encoding($name)" );
207             }
208             }
209             }
210 0           return 1; # I doubt if we need it, though
211             }
212              
213             sub unimport {
214 2     2   11 no warnings;
  2         2  
  2         176  
215 0     0     undef ${^ENCODING};
216 0           undef ${^E_NCODING} if PERL_5_21_7;
217 0           if (HAS_PERLIO) {
218 0           binmode( STDIN, ":raw" );
219 0           binmode( STDOUT, ":raw" );
220             }
221             else {
222             binmode(STDIN);
223             binmode(STDOUT);
224             }
225 0 0         if ( $INC{"Filter/Util/Call.pm"} ) {
226 0           eval { filter_del() };
  0            
227             }
228             }
229              
230             1;
231             __END__