読者です 読者をやめる 読者になる 読者になる

y2q_actionman’s ゴミクズチラ裏

内向きのメモ書きを置いてます

Unicode 圧縮を実装した

概要

Standard Compression Scheme for Unicode (UTS #6: Compression Scheme for Unicode) を Common Lisp で実装しました。

github.com

ここに至った経緯は以下のようになってます。

  1. 仕事で使えそうかなと思って調べた。でも使わなかった。
  2. 検索する限りだと既存の実装もなさそう *1なので、実装してみた。
  3. 実装は簡単かと思ってたら、結構時間がかかってしまった。

ここからは、実装して得られた知見などを適当にメモしていきます。

性能考察

圧縮率

公式にある例 について、ほとんど同等の圧縮率を達成しています。

  1. ドイツ語 :: 同じ圧縮結果。
  2. ロシア語 :: 同じ圧縮結果。
  3. 日本語 :: 圧縮結果は同じ長さになる。しかし、前半で例より1バイト長くなってしまっているが、後半で例より1バイト短く圧縮できているので、結果同じ長さになっている。
  4. All :: 例より6バイトも長い。これは、 U+10FFFF が non-character なので、日和って長く圧縮するようにしているため。

速度

最適化宣言などしておらず、そんなに速くないはずです。必要になることがあれば、やってみてもいいかもしれません。

実装考察

他の文字コード変換ライブラリとの食い合わせ

SCSU は、 圧縮をしていますが、その実態は Locking Shift する文字符号化方式とも捉えることも出来ると思われます。 成程ならば、既存の文字コード変換ライブラリ ( babelflexi-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