root/lang/perl/Encode-JP-Mobile/trunk/lib/Encode/JP/Mobile/KDDIJIS.pm @ 6465

Revision 6465, 5.8 kB (checked in by tokuhirom, 5 years ago)

lang/perl/Encode-JP-Mobile: added '_' prefix for private methods

RevLine 
[1392]1package Encode::JP::Mobile::KDDIJIS;
2use strict;
3use warnings;
4use base qw(Encode::Encoding);
5use Encode::Alias;
6use Encode::CJKConstants qw(:all);
7use Encode qw(:fallbacks);
8use Encode::JP::Mobile;
9use POSIX 'ceil';
10use Carp;
11
12define_alias('x-iso-2022-jp-ezweb' => 'x-iso-2022-jp-kddi');
13__PACKAGE__->Define(qw(x-iso-2022-jp-kddi));
14
15my $re_scan_jis = qr{
16   (?:($RE{JIS_0212})|$RE{JIS_0208}|($RE{ISO_ASC})|($RE{JIS_KANA}))([^\e]*)
17}x;
18
[5219]19sub _encoding() { 'x-sjis-kddi-cp932-raw' }
[4775]20
[1392]21sub decode($$;$) {
22    my ($self, $str, $chk) = @_;
23
24    my $residue = '';
25    if ($chk) {
26        $str =~ s/([^\x00-\x7f].*)$//so and $residue = $1;
27    }
[6465]28    $residue .= _jis_sjis( \$str );
[1392]29    $_[1] = $residue if $chk;
30
[4775]31    return Encode::decode( $self->_encoding, $str, FB_PERLQQ );
[1392]32}
33
34sub encode($$;$) {
[1434]35    my ( $obj, $utf8, $chk ) = @_;
[4775]36    my $octet = Encode::encode( $obj->_encoding, $utf8, $chk );
[6465]37    return _sjis_jis( $octet );
[1392]38}
39
[1434]40sub ASC () { 1 }
41sub JIS_0208 () { 2 }
42sub KANA () { 3 }
[6465]43sub _sjis_jis {
[1434]44    my $octet = shift;
45
46    use bytes;
47
48    my @chars = split //, $octet;
49    my $mode = ASC;
50    my $res = '';
51
52    for (my $i=0; $i<@chars; $i++) {
53        my $x = ord $chars[$i];
54        if ($x < 0x80) {
55            if ($mode != ASC) {
56                $res .= $ESC{ASC};
57                $mode = ASC;
58            }
59            $res .= chr $x;
60        } elsif (0xA1 <= $x && $x <= 0xDF) {
61            if ($mode != KANA) {
62                $res .= $ESC{KANA};
63                $mode = KANA;
64            }
65            $mode = KANA;
66            $res .= chr($x - 0x80);
67        } else {
68            if ($mode != JIS_0208) {
69                $res .= $ESC{JIS_0208};
70                $mode = JIS_0208;
71            }
72            $i++;
73            last unless $i<@chars;
74            my ($c1, $c2) = sjis2jis_one($x, ord $chars[$i]);
75            $res .= chr($c1).chr($c2);
76        }
77    }
78
79    if ($mode != ASC) {
80        $res .= $ESC{ASC};
81    }
82
83    $res;
84}
85sub sjis2jis_one {
86    my ($c1, $c2) = @_;
87
88    # 0x0600 : 0xF340 - 0xF48D
89    # 0x0B00 : 0xF640 - 0xF7FC
90
91    my $c = ($c1<<8) + $c2;
92    if (0xF340 <= $c && $c <= 0xF48D) {
93        $c1 -= 0x06;
94    } elsif (0xF640 <= $c && $c <= 0xF7FC) {
95        $c1 -= 0x0B;
96    }
97
98    $c1 -= ($c1 <= 0x9f) ? 0x71 : 0xB1;
99    $c1 = $c1*2 + 1;
100
101    if ($c2 > 0x7F) {
102        $c2 -= 0x01;
103    }
104
105    if ($c2>=0x9E) {
106        $c2  = $c2-0x7D;
107        $c1++;
108    } else {
109        $c2 -= 0x1F;
110    }
111
112    return ($c1, $c2);
113}
114
[6465]115sub _jis_sjis {
[1392]116    local ${^ENCODING};
117
118    my $r_str = shift;
119    $$r_str =~ s($re_scan_jis){
120        my ($esc_0212, $esc_asc, $esc_kana, $chunk) = ($1, $2, $3, $4);
121
122        if ($esc_kana) {
123            $chunk =~ s{(.)}{
124                pack "H*", sprintf "%X", (0x80 + (hex unpack "H*", $1));
125            }geox;
126            $chunk;
127        } elsif ($esc_asc) {
128            $chunk;
129        } else {
130            $chunk =~ s((..)){
[6465]131                pack "H*", sprintf"%X", _jis2sjis_one(hex(unpack "H*", $1));
[1392]132            }geox;
133            $chunk;
134        }
135
136    }geox;
137
138    my ($residue) = ( $$r_str =~ s/(\e.*)$//so );
139
140    return $residue;
141}
142
[6465]143sub _jis2sjis_one { my $x = shift; return ( _xy($x) << 8 ) + _zu($x) } # input is binary
[1392]144
[6465]145sub _high { my $x = shift; $x >> 8 }
146sub _low  { my $x = shift; $x & 0xff }
[1392]147
[6465]148sub _xy {
[1392]149    my $jis = shift;
150
[6465]151    my $pq = _high($jis);
[1392]152    my $t  = ceil( $pq / 2 ) + 0x70;
153    my $ans = ($t <= 0x9F) ? $t : $t+0x40;
154
155    # XXX !!!
156    if (0xED == $ans || $ans == 0xEE) {
157        return $ans + 0x06;
158    } elsif (0xEB == $ans || $ans == 0xEC) {
159        return $ans + 0x0b;
160    } else {
161        return $ans;
162    }
163}
164
[6465]165sub _zu {
[1392]166    my $jis = shift;
[6465]167    my $pq  = _high($jis);
168    my $rs  = _low($jis);
[1392]169
170    if ( $pq % 2 ) {    # odd
171        my $t = $rs + 0x20;
172        return ( $t > 0x7f ) ? $t : $t - 1;
173    }
174    else {              # even
175        return $rs + 0x7E;
176    }
177}
178
[4775]179package # hide from PAUSE
180    Encode::JP::Mobile::KDDIJIS::Auto;
181use base 'Encode::JP::Mobile::KDDIJIS';
182use Encode::Alias;
[1392]183
[4775]184define_alias('x-iso-2022-jp-ezweb-auto' => 'x-iso-2022-jp-kddi-auto');
185__PACKAGE__->Define(qw(x-iso-2022-jp-kddi-auto));
186
[5216]187sub _encoding() { 'x-sjis-kddi-auto-raw' }
[4775]188
[1392]1891;
190
191__END__
192
[4705]193=encoding utf-8
[1392]194
195=head1 NAME
196
197Encode::JP::Mobile::KDDIJIS - KDDI のメール受信で絵文字つかう
198
199=head1 DESCRIPTION
200
201KDDI のメールで送信される iso-2022-jp にのってやってくるメール用絵文字JISコードを decode するためのアレ。
202
203この実装の根拠は、絵文字用 JIS コードと他の文字コードの間にはとくに法則性はない
204
205絵文字用JISコードを素直に一般に知られている SJIS に変換する方式にしたがってずらしたものが絵文字用SJISコード。
206絵文字用SJISコードは
207
208 * 0xED40 から 0xEE8D の区間では、0x0600 足す
209 * 0xEB59から0xECE4の区間では 0x0b00 足す
210
211というルールにより通常の sjis 時の区画にもっていくことができる。この手法が非常に簡単に実装可能であることから、
212実機もこのような方法で実装されているのではないかと想像している(私見)
213
214この後で、x-sjis-kddi で decode すれば OK.
215
[1434]216encode の場合はこの逆をやればよい。unicode 文字列を sjis のバイト列に encode してやり、
217下記のエリアにある文字列をシフトしてやる。
218
219 * 0x0600 : 0xF340 - 0xF48D
220 * 0x0B00 : 0xF640 - 0xF7FC
221
222こうしてシフトしつつ、iso-2022-jp に変換してやればよい。
223
[4775]224=head1 ENCODINGS
225
226x-iso-2022-jp-kddi, x-iso-2022-jp-ezweb で表 utf-8 に decode。x-iso-2022-jp-ezweb-auto,
227x-iso-2022-jp-kddi-auto で裏 utf-8 に decode できます。
228
[1392]229=head1 TODO
230
231JIS X 0212 に対応してない。けどそもそも ezweb で使えるのかね。そこがまず疑問ではあるよ。
232
233=head1 AUTHOR
234
235Tokuhiro Matsuno <tokuhirom at mobile factory dot jp>
236
237=head1 SEE ALSO
238
239L<http://www.cc.kurume-it.ac.jp/home/general/sibhome/moji/moji11.html>
240
Note: See TracBrowser for help on using the browser.