Unicode 圧縮を実装した
概要
Standard Compression Scheme for Unicode (UTS #6: Compression Scheme for Unicode) を Common Lisp で実装しました。
ここに至った経緯は以下のようになってます。
- 仕事で使えそうかなと思って調べた。でも使わなかった。
- 検索する限りだと既存の実装もなさそう *1なので、実装してみた。
- 実装は簡単かと思ってたら、結構時間がかかってしまった。
ここからは、実装して得られた知見などを適当にメモしていきます。
性能考察
圧縮率
公式にある例 について、ほとんど同等の圧縮率を達成しています。
- ドイツ語 :: 同じ圧縮結果。
- ロシア語 :: 同じ圧縮結果。
- 日本語 :: 圧縮結果は同じ長さになる。しかし、前半で例より1バイト長くなってしまっているが、後半で例より1バイト短く圧縮できているので、結果同じ長さになっている。
- All :: 例より6バイトも長い。これは、 U+10FFFF が non-character なので、日和って長く圧縮するようにしているため。
速度
最適化宣言などしておらず、そんなに速くないはずです。必要になることがあれば、やってみてもいいかもしれません。
実装考察
他の文字コード変換ライブラリとの食い合わせ
SCSU は、 圧縮をしていますが、その実態は Locking Shift する文字符号化方式とも捉えることも出来ると思われます。 成程ならば、既存の文字コード変換ライブラリ ( babel や flexi-streamsの external-format 周り ) の関数やマクロなどを借りれば、簡単に実装できるのかなあと思いました。
ただ、これらライブラリは、どうも Locking Shift する文字符号化形式 (ISO-2022 とか)を実装していないようで、それらが簡単に実装できるのかどうか分かりませんでした。そういうわけで、これらの機能を借りずに実装してしまいましたが、可能ならガワを頂きたいものです。
エラー処理
変換器が、変なバイト列を食わされてエラーとなることは往々にしてあるので、その対処をどうするかが問題になります。 以下のような機構があるようです。
- 停止し、変換できた所までの場所を返す (iconv 方式) 。 cl-scsu では、これを行う restart を提供した。
- 代替の文字で埋める。 flexi-stream では、 変数
*substitution-char*
や、 external-format-encoding-error でのuse-value
restart が相当する。
*1: このリンク先くらいしか見つからなかった: Unicode-handling library