Punycodeのjavascript実装と変換テスト
概要
Punycode変換をjavascriptで実装した
- punycode.js https://github.com/wealandwoe/punicode.js
var encoded = Punycode.encode("ぴゅにこーど");//=> "28j1be9azfq9a"
var decoded = Punycode.decode(encoded);
decoded=="ぴゅにこーど" //=> true
encoded = Punycode.encode("Punycode変換・逆変換"); //=> "Punycode-wg5gy946aba2534aca0149m"
以下を参考にした
- Punycode - Wikipedia http://ja.wikipedia.org/wiki/Punycode
- rfc3492日本語訳 http://www.jdna.jp/survey/rfc/rfc3492j.html
- 日本語JPドメイン名のPunycode変換・逆変換 http://punycode.jp/
- Adam M. Costello - Internationalized Domain Names (IDN) http://www.nicemice.net/idn/
最後、Punycodeの発案者のサイトに最新のpunycode.cのサンプルがあり大いに参考にした。 RFC3492日本語訳のcのコードには抜けがあるので注意。
##実験
Punycodeをjavascriptに移植してみて以下がわかった
- 国際化URLの為の仕様だとおもっていたがURLには使用できない文字でもエンコード可能
- とはいえ、ASCII(0x80以下)はスルーするので文字以外には向かないかもしれない
- ASCIIにエスケープしているがバイトサイズで比較しても元と同じかより小さくなることも
- 処理は複雑で割り算を多用していることもあり時間がかかる
- 国際化URLとして使うには使用禁止文字、大文字小文字の同一化、prefix(xn--)追加など工夫が必要
Punycode内部で利用しているBootstringというアルゴリズムを応用すれば 36字(A-Z0-9)以上の文字種でエンコードが可能になる
Punycodeは、Bootstringと呼ばれる、より一般的なアルゴリズムの適用事例
(instance)である。このアルゴリズムは、より大きな文字集合に属する
コードポイントの並びを、小さな"基本(basic)"コードポイントの集合に
含まれるコードポイントの並びによって一意に表現可能にするものである。
Punycodeは、Bootstringの特定のパラメーター値をIDNA向けに適切に設定した
ものである。
試しにBase64([A-Za-z0-9+/])とBase85([0-9A-Za-z!#$%&()*+-;<=>?@^_`{|}~])で作成してみた
var str = "Punycodeのjavascript実装と変換テスト";
Punycode.encode(str,Punycode.Params); //=> "Punycodejavascript-ei4qnd68efitb5631q2rna9p4c6j0o"
Punycode.encode(str,Punycode.Base64Params); //=> "Punycodejavascript-8s6A4Bu3AxEvA7/uVqKE/dU8izB"
Punycode.encode(str,Punycode.Base85Params); //=> "Punycodejavascript.I2Xg1|lv3l0(%)D~a2g`Dd(j"
// ecl.js の JCT11280(JIS-UNICODE変換テーブル)でテスト
JCT11280.length; //=> 11280 (chars)
Utils.ByteArray.fromText(JCT11280).length; //=> 33718 (bytes)
Punycode.encode(JCT11280).length; //=> 31455 (bytes) 93.3%
Punycode.encode(JCT11280,Punycode.Base64Params).length; //=> 29584 (bytes) 87.7%
Punycode.encode(JCT11280,Punycode.Base85Params).length; //=> 28565 (bytes) 84.7%
パラメータのせいもあるかもしれないが、文字種が増えても思った以上には縮小されなかった。 36種類→85種類で236%の増加だが、縮小率は93.3%→84.7%で10%程しか差がない。
考察
Bootstringの仕組みは面白く、変換後のサイズも小さいが処理が遅いのが気になる。