File Coverage

blib/lib/Encode/Locale.pm
Criterion Covered Total %
statement 57 106 53.7
branch 15 66 22.7
condition 8 22 36.3
subroutine 12 18 66.6
pod 3 3 100.0
total 95 215 44.1


line stmt bran cond sub pod time code
1             package Encode::Locale;
2              
3 5     5   66771 use strict;
  5         7  
  5         256  
4             our $VERSION = "1.04";
5              
6 5     5   25 use base 'Exporter';
  5         6  
  5         604  
7             our @EXPORT_OK = qw(
8             decode_argv env
9             $ENCODING_LOCALE $ENCODING_LOCALE_FS
10             $ENCODING_CONSOLE_IN $ENCODING_CONSOLE_OUT
11             );
12              
13 5     5   2762 use Encode ();
  5         43540  
  5         138  
14 5     5   39 use Encode::Alias ();
  5         6  
  5         3655  
15              
16             our $ENCODING_LOCALE;
17             our $ENCODING_LOCALE_FS;
18             our $ENCODING_CONSOLE_IN;
19             our $ENCODING_CONSOLE_OUT;
20              
21             sub DEBUG () { 0 }
22              
23             sub _init {
24 6 50   6   37 if ($^O eq "MSWin32") {
25 0 0       0 unless ($ENCODING_LOCALE) {
26             # Try to obtain what the Windows ANSI code page is
27 0         0 eval {
28 0 0       0 unless (defined &GetConsoleCP) {
29 0         0 require Win32;
30             # no point falling back to Win32::GetConsoleCP from this
31             # as added same time, 0.45
32 0         0 eval { Win32::GetConsoleCP() };
  0         0  
33             # manually "import" it since Win32->import refuses
34 0 0   0   0 *GetConsoleCP = sub { &Win32::GetConsoleCP } unless $@;
  0         0  
35             }
36 0 0       0 unless (defined &GetConsoleCP) {
37 0         0 require Win32::API;
38 0         0 Win32::API->Import('kernel32', 'int GetConsoleCP()');
39             }
40 0 0       0 if (defined &GetConsoleCP) {
41 0         0 my $cp = GetConsoleCP();
42 0 0       0 $ENCODING_LOCALE = "cp$cp" if $cp;
43             }
44             };
45             }
46              
47 0 0       0 unless ($ENCODING_CONSOLE_IN) {
48             # only test one since set together
49 0 0       0 unless (defined &GetInputCP) {
50 0         0 eval {
51 0         0 require Win32;
52 0         0 eval { Win32::GetConsoleCP() };
  0         0  
53             # manually "import" it since Win32->import refuses
54 0 0   0   0 *GetInputCP = sub { &Win32::GetConsoleCP } unless $@;
  0         0  
55 0 0   0   0 *GetOutputCP = sub { &Win32::GetConsoleOutputCP } unless $@;
  0         0  
56             };
57 0 0       0 unless (defined &GetInputCP) {
58 0         0 eval {
59             # try Win32::Console module for codepage to use
60 0         0 require Win32::Console;
61 0         0 eval { Win32::Console::InputCP() };
  0         0  
62 0     0   0 *GetInputCP = sub { &Win32::Console::InputCP }
63 0 0       0 unless $@;
64 0     0   0 *GetOutputCP = sub { &Win32::Console::OutputCP }
65 0 0       0 unless $@;
66             };
67             }
68 0 0       0 unless (defined &GetInputCP) {
69             # final fallback
70             *GetInputCP = *GetOutputCP = sub {
71             # another fallback that could work is:
72             # reg query HKLM\System\CurrentControlSet\Control\Nls\CodePage /v ACP
73 0 0 0 0   0 ((qx(chcp) || '') =~ /^Active code page: (\d+)/)
74             ? $1 : ();
75 0         0 };
76             }
77             }
78 0         0 my $cp = GetInputCP();
79 0 0       0 $ENCODING_CONSOLE_IN = "cp$cp" if $cp;
80 0         0 $cp = GetOutputCP();
81 0 0       0 $ENCODING_CONSOLE_OUT = "cp$cp" if $cp;
82             }
83             }
84              
85 6 100       17 unless ($ENCODING_LOCALE) {
86 5         7 eval {
87 5         2372 require I18N::Langinfo;
88 5         3101 $ENCODING_LOCALE = I18N::Langinfo::langinfo(I18N::Langinfo::CODESET());
89              
90             # Workaround of Encode < v2.25. The "646" encoding alias was
91             # introduced in Encode-2.25, but we don't want to require that version
92             # quite yet. Should avoid the CPAN testers failure reported from
93             # openbsd-4.7/perl-5.10.0 combo.
94 5 50       23 $ENCODING_LOCALE = "ascii" if $ENCODING_LOCALE eq "646";
95              
96             # https://rt.cpan.org/Ticket/Display.html?id=66373
97 5 50 33     22 $ENCODING_LOCALE = "hp-roman8" if $^O eq "hpux" && $ENCODING_LOCALE eq "roman8";
98             };
99 5   33     16 $ENCODING_LOCALE ||= $ENCODING_CONSOLE_IN;
100             }
101              
102 6 50       17 if ($^O eq "darwin") {
103 0   0     0 $ENCODING_LOCALE_FS ||= "UTF-8";
104             }
105              
106             # final fallback
107 6 0 33     15 $ENCODING_LOCALE ||= $^O eq "MSWin32" ? "cp1252" : "UTF-8";
108 6   33     33 $ENCODING_LOCALE_FS ||= $ENCODING_LOCALE;
109 6   66     29 $ENCODING_CONSOLE_IN ||= $ENCODING_LOCALE;
110 6   66     34 $ENCODING_CONSOLE_OUT ||= $ENCODING_CONSOLE_IN;
111              
112 6 50       21 unless (Encode::find_encoding($ENCODING_LOCALE)) {
113 0         0 my $foundit;
114 0 0       0 if (lc($ENCODING_LOCALE) eq "gb18030") {
115 0         0 eval {
116 0         0 require Encode::HanExtra;
117             };
118 0 0       0 if ($@) {
119 0         0 die "Need Encode::HanExtra to be installed to support locale codeset ($ENCODING_LOCALE), stopped";
120             }
121 0 0       0 $foundit++ if Encode::find_encoding($ENCODING_LOCALE);
122             }
123 0 0       0 die "The locale codeset ($ENCODING_LOCALE) isn't one that perl can decode, stopped"
124             unless $foundit;
125              
126             }
127              
128             # use Data::Dump; ddx $ENCODING_LOCALE, $ENCODING_LOCALE_FS, $ENCODING_CONSOLE_IN, $ENCODING_CONSOLE_OUT;
129             }
130              
131             _init();
132             Encode::Alias::define_alias(sub {
133 5     5   28 no strict 'refs';
  5         9  
  5         145  
134 5     5   21 no warnings 'once';
  5         6  
  5         347  
135             return ${"ENCODING_" . uc(shift)};
136             }, "locale");
137              
138             sub _flush_aliases {
139 5     5   26 no strict 'refs';
  5         8  
  5         1437  
140 1     1   6 for my $a (keys %Encode::Alias::Alias) {
141 4 100       6 if (defined ${"ENCODING_" . uc($a)}) {
  4         21  
142 1         3 delete $Encode::Alias::Alias{$a};
143 1         2 warn "Flushed alias cache for $a" if DEBUG;
144             }
145             }
146             }
147              
148             sub reinit {
149 1     1 1 640 $ENCODING_LOCALE = shift;
150 1         3 $ENCODING_LOCALE_FS = shift;
151 1         4 $ENCODING_CONSOLE_IN = $ENCODING_LOCALE;
152 1         3 $ENCODING_CONSOLE_OUT = $ENCODING_LOCALE;
153 1         28 _init();
154 1         3610 _flush_aliases();
155             }
156              
157             sub decode_argv {
158 1 50   1 1 235 die if defined wantarray;
159 1         3 for (@ARGV) {
160 4         69 $_ = Encode::decode(locale => $_, @_);
161             }
162             }
163              
164             sub env {
165 9     9 1 4349 my $k = Encode::encode(locale => shift);
166 9         395 my $old = $ENV{$k};
167 9 100       29 if (@_) {
168 4         6 my $v = shift;
169 4 100       15 if (defined $v) {
170 3         10 $ENV{$k} = Encode::encode(locale => $v);
171             }
172             else {
173 1         7 delete $ENV{$k};
174             }
175             }
176 9 50       136 return Encode::decode(locale => $old) if defined wantarray;
177             }
178              
179             1;
180              
181             __END__