File Coverage

blib/lib/Encode/JP/Mobile/AirHJIS.pm
Criterion Covered Total %
statement 112 114 98.2
branch 38 46 82.6
condition 16 36 44.4
subroutine 20 20 100.0
pod 2 2 100.0
total 188 218 86.2


line stmt bran cond sub pod time code
1             package Encode::JP::Mobile::AirHJIS;
2 24     24   145 use strict;
  24         49  
  24         1011  
3 24     24   199 use warnings;
  24         407  
  24         1814  
4 24     24   148 use base qw(Encode::Encoding);
  24         52  
  24         1996  
5 24     24   134 use Encode::Alias;
  24         41  
  24         1479  
6 24     24   130 use Encode::CJKConstants qw(:all);
  24         47  
  24         4505  
7 24     24   157 use Encode qw(:fallbacks);
  24         73  
  24         3595  
8 24     24   139 use Encode::JP::Mobile;
  24         41  
  24         1182  
9 24     24   131 use POSIX 'ceil';
  24         39  
  24         172  
10 24     24   1497 use Carp;
  24         53  
  24         34588  
11              
12             define_alias('x-iso-2022-jp-airedge' => 'x-iso-2022-jp-airh');
13             __PACKAGE__->Define(qw(x-iso-2022-jp-airh));
14              
15             my $re_scan_sjis = qr{
16             $RE{SJIS_KANA}|$RE{SJIS_C}
17             }x;
18              
19             my $re_scan_jis = qr{
20             (?:($RE{JIS_0212})|$RE{JIS_0208}|($RE{ISO_ASC})|($RE{JIS_KANA}))([^\e]*)
21             }x;
22              
23             sub _encoding() { 'x-sjis-docomo-raw' }
24              
25             sub decode($$;$) {
26 22     22 1 15648 my ($self, $str, $chk) = @_;
27              
28 22         38 my $residue = '';
29 22 100       67 if ($chk) {
30 1 50       7 $str =~ s/([^\x00-\x7f].*)$//so and $residue = $1;
31             }
32 22         57 $residue .= _jis_sjis( \$str );
33 22 100       88 $_[1] = $residue if $chk;
34              
35 22         134 return Encode::decode( $self->_encoding, $str, FB_PERLQQ );
36             }
37              
38             sub encode($$;$) {
39 18     18 1 25912 my ( $obj, $utf8, $chk ) = @_;
40 18         84 my $octet = Encode::encode( $obj->_encoding, $utf8, $chk );
41 18         501 return _sjis_jis( $octet );
42             }
43              
44             sub ASC () { 1 }
45             sub JIS_0208 () { 2 }
46             sub KANA () { 3 }
47             sub _sjis_jis {
48 18     18   112 my $octet = shift;
49              
50 24     24   171 use bytes;
  24         58  
  24         161  
51              
52 18         94 my @chars = split //, $octet;
53 18         34 my $mode = ASC;
54 18         30 my $res = '';
55              
56 18         66 for (my $i=0; $i<@chars; $i++) {
57 68         101 my $x = ord $chars[$i];
58 68 100 100     233 if ($x < 0x80) {
    100          
59 16 100       33 if ($mode != ASC) {
60 2         5 $res .= $ESC{ASC};
61 2         4 $mode = ASC;
62             }
63 16         44 $res .= chr $x;
64             } elsif (0xA1 <= $x && $x <= 0xDF) {
65 12 100       24 if ($mode != KANA) {
66 2         5 $res .= $ESC{KANA};
67 2         4 $mode = KANA;
68             }
69 12         13 $mode = KANA;
70 12         33 $res .= chr($x - 0x80);
71             } else {
72 40 100       91 if ($mode != JIS_0208) {
73 16         39 $res .= $ESC{JIS_0208};
74 16         26 $mode = JIS_0208;
75             }
76 40         41 $i++;
77 40 50       92 last unless $i<@chars;
78 40         104 my ($c1, $c2) = _sjis2jis_one($x, ord $chars[$i]);
79 40 100       162 $res .= $c2 ? chr($c1).chr($c2) : $c1;
80             }
81             }
82              
83 18 100       51 if ($mode != ASC) {
84 16         37 $res .= $ESC{ASC};
85             }
86              
87 18         88 $res;
88             }
89             sub _sjis2jis_one {
90 40     40   125 my ($c1, $c2) = @_;
91              
92             # 0xF89F - 0xF949
93             # 0xF950 - 0xF952
94             # 0xF955 - 0xF957
95             # 0xF95B - 0xF95E
96             # 0xF972 - 0xF9FC
97 40         61 my $c = ($c1<<8) + $c2;
98 40 50 66     555 if (0xF89F <= $c && $c <= 0xF949 ||
      33        
      66        
      33        
      33        
      33        
      33        
      33        
      33        
99             0xF950 <= $c && $c <= 0xF952 ||
100             0xF955 <= $c && $c <= 0xF957 ||
101             0xF95B <= $c && $c <= 0xF95E ||
102             0xF972 <= $c && $c <= 0xF9FC) {
103 8         65 return pack('H*', sprintf('%X', $c));
104             }
105              
106 32 50       65 $c1 -= ($c1 <= 0x9f) ? 0x71 : 0xB1;
107 32         48 $c1 = $c1*2 + 1;
108              
109 32 100       61 if ($c2 > 0x7F) {
110 14         20 $c2 -= 0x01;
111             }
112              
113 32 100       52 if ($c2>=0x9E) {
114 14         14 $c2 = $c2-0x7D;
115 14         17 $c1++;
116             } else {
117 18         25 $c2 -= 0x1F;
118             }
119              
120 32         60 return ($c1, $c2);
121             }
122              
123             sub _jis_sjis {
124 22     22   80 local ${^ENCODING};
125              
126 22         35 my $r_str = shift;
127 22         157 $$r_str =~ s($re_scan_jis){
128 44         155 my ($esc_0212, $esc_asc, $esc_kana, $chunk) = ($1, $2, $3, $4);
129              
130 44 100       220 if ($esc_kana) {
    100          
131 2         221 $chunk =~ s{(.)}{
132 12         67 pack "H*", sprintf "%X", (0x80 + (hex unpack "H*", $1));
133             }geox;
134 2         12 $chunk;
135             } elsif ($esc_asc) {
136 22         70 $chunk;
137             } else {
138 20         134 $chunk =~ s{(?:($re_scan_sjis)|(..))}{
139 47 100       259 $1 ? $1 : pack "H*", sprintf "%X", _jis2sjis_one(hex(unpack "H*", $2))
140             }geox;
141 20         119 $chunk;
142             }
143             }geox;
144              
145 22         72 my ($residue) = ( $$r_str =~ s/(\e.*)$//so );
146              
147 22         74 return $residue;
148             }
149              
150 36     36   56 sub _jis2sjis_one { my $x = shift; return ( _xy($x) << 8 ) + _zu($x) } # input is binary
  36         55  
151              
152 72     72   73 sub _high { my $x = shift; $x >> 8 }
  72         196  
153 36     36   44 sub _low { my $x = shift; $x & 0xff }
  36         53  
154              
155             sub _xy {
156 36     36   42 my $jis = shift;
157              
158 36         64 my $pq = _high($jis);
159 36         138 my $t = ceil( $pq / 2 ) + 0x70;
160 36 50       79 my $ans = ($t <= 0x9F) ? $t : $t+0x40;
161              
162             # XXX !!!
163 36 50 33     255 if (0xED == $ans || $ans == 0xEE) {
    50 33        
164 0         0 return $ans + 0x06;
165             } elsif (0xEB == $ans || $ans == 0xEC) {
166 0         0 return $ans + 0x0b;
167             } else {
168 36         103 return $ans;
169             }
170             }
171              
172             sub _zu {
173 36     36   40 my $jis = shift;
174 36         61 my $pq = _high($jis);
175 36         59 my $rs = _low($jis);
176              
177 36 100       76 if ( $pq % 2 ) { # odd
178 18         24 my $t = $rs + 0x20;
179 18 50       110 return ( $t > 0x7f ) ? $t : $t - 1;
180             }
181             else { # even
182 18         130 return $rs + 0x7E;
183             }
184             }
185              
186             1;
187              
188             __END__