Encode.pm 最近の雑感
2.19 から ISO-2022-JP の encode() が custom fallback に対応(CHECK をきちんと CHECK するようになった)とのことでめでたい。miyagawa ++
で,どこ変わったの?とみてみたら,
@@ -49,7 +49,7 @@ # empty the input string in the stack so perlio is ok $_[1] = '' if $chk; my ( $h2z, $jis0212 ) = @$obj{qw(h2z jis0212)}; - my $octet = Encode::encode( 'euc-jp', $utf8, FB_PERLQQ ); + my $octet = Encode::encode( 'euc-jp', $utf8, $chk ); $h2z and &Encode::JP::H2Z::h2z( \$octet ); euc_jis( \$octet, $jis0212 ); return $octet;
あ,やっぱそこっすか。実は Encode::EUCJPMS の CP50220 / CP50221 も流用してるんで,こちらは未だに必ず PERLQQ になってしまう罠。RT にあげたほうがいいかな。
んで,Encode の encode() って渡した文字列が侵食されうるんですよね。Encode::LEAVE_SRC を渡すと侵食しないんですが(ちなみに FB_PERLQQ と FB_HTMLCREF と FB_XMLCREF には LEAVE_SRC フラグが含まれてます),custom fallback function だとそのような意図を伝えることができないのが残念。
実際,
use Encode; my $s1 = $s2 = 'A①'; my $d1 = encode('EUC-JP', $s1, FB_DEFAULT); # $s1 は侵食されない $d1 = encode('EUC-JP', $s1, sub { '!' }); # $s1 は侵食されない my $d2 = encode('ISO-2022-JP', $s2, FB_DEFAULT); # $s2 は侵食されない $d2 = encode('ISO-2022-JP', $s2, sub { '!' }); # $s2 は侵食される!(空になる)
のように,エンコーディングによって挙動が違うんですよね。仕様といえば仕様のようですが。