これでもまだ税率が高かったので。

404 Blog Not Found:javascript - Yet Another Base64 transcoder
Base64の利点は、なんといっても「固定税率」、それも比較的「税率が低い」ことにあります。Paddingなしなら、3バイトが4バイトにencodeされるので、33%ということになります。これに対してencodeURIComponentの税率は、UTF-8基準で最高で3倍、UTF-16基準で最高で4.5倍にも達します。

ついに負の税率、すなわち税還付を実現しました!

まずはデモを。

Inflated + Base64-Decoded (Original):
chars / bytes
Deflated + Base64-Encoded (Compressed):
bytes

その仕組みですが、圧縮時にはいったんUTF-8のバイト列にしたもの(CESU-8)をRFC1951の Raw Deflate にかけた上で Base64 encode し、伸張時には逆に Base 64 decode したものを Raw Inflate し、それを(UTF-16である) JavaScript String にしているというわけです。

Raw Deflate のエンジン部分は、「高度な JavaScript 技集」の inflate.js および deflate.js から拝借させていただきました。私が直したところは、グローバル変数(関数だけだがそれも含む)をローカルに閉じ込めたこと、そしてIEでも「使える」速度で動くよう、String の+演算を減らしたことぐらいでしょうか。10年も前にあれほど高度な JavaScript が書かれたことが驚きです。Masanao Izumo 様、ありがとうございました。

と同時に、「404 Blog Not Found:javascript - Yet Another Base64 transcoder」で発表し、drryさんがばっさり手直ししてくれた base64.js を再びばっさり手直ししました。最初のバージョンでは 文字列をちまちまいじっていましたが、drryさんがそれを一端配列に直してから操作し、そして文字列に戻すよう書き換えたのですが、これだと(特に string + string が遅いIEで)高速になりはするのですが、メモリーの使い方が富豪すぎて、大きなデータだとブラクラになっちゃったのです。

結局どうやったかというと、正規表現を使いました。これなら文字列から文字列への変換なので、文字を一つ一つ配列に入れてから処理するよりメモリーも食いませんし、より高速でもあります。実際jQueryとPrototype.js、そして本blogのHTMLなどを食わせてみましたが、IE7でもぼちぼち動きますし、Chromeに至ってはとてもJSで書かれたとは思えないほどさくさく動きました。これなら充分実用になるのではないでしょうか。

なお、サーバー側で Raw Deflate/Inflate する方法なのですが、Perlであれば IO::Compress::Zlib をインストールしておけば、 IO::Compress::RawDeflateIO::Uncompress::RawInflate がもれなく付いてくるので、それを使えばよいでしょう。以下、コマンドラインで指定したファイルを Raw Deflate した上で Base64 encode する perl script の例です。

#!/usr/local/bin/perl
use strict;
use warnings;
use IO::Compress::RawDeflate ':all';
use MIME::Base64;


sub slurp{
    my $filename = shift;
    open my $fh, '<', $filename or die "$filename:$!";
    local $/;
    my $content = <$fh>;
    close $fh or warn "$filename:$!";
    return $content;
}

my $orig = slurp shift || die "$0 file";
my $deflated;
rawdeflate(\$orig => \$deflated) or die "deflate failed: $RawDeflateError";
print encode_base64($deflated);

Enjoy!

Dan the Inflated JavaScripter

追記:IPhoneでも動いた!