Unicodeと向き合う

Unicodeと向き合って3連休を費やしてしまいました。とりあえず書き記しておきます。

概要

  • Unicodeの世界には制御文字や結合文字があるため、1文字が40バイトくらいに膨れ上がることがある。まずはこの事実を受け入れること。
  • Unicodeを扱うには下記のような問題が生じるので、設計の際は気を付けること。
  • 具体的な対策方法を書くには時間が足りなかった。

書記素クラスタ

  • 「入力は10文字以内です」を正確に処理しているサイトは少ない。
  • 文字数を正確にカウントするには「書記素クラスタ(Grapheme Cluster)」を数える。
  • 数え方を誤っても、通常は増える(1文字が2文字扱いされる)ので案外平気。
  • 文字を検索する機能を実装する場合も、書記素クラスタを考慮しなければならない。

正規化

  • 「が」=「か」+「゛」のように、単一のコードポイントで表示できる文字を複数のコードポイントで表現してもよい。
  • 互換性を高めるために、NFC方式でUnicode正規化するとよい。
  • ただし、CJK互換漢字に分類されている旧字体(神)をNFCで正規化すると新字体(神)になる。
    • 異体字セレクタが導入される前の文字なので、仕様だと割り切るのがいいかもしれない。
  • NFKC方式でUnicode正規化すると、①や⒈のような文字を1に変換できる。こちらは検索エンジンのように、文字の形よりも意味を優先したい場合に使うとよい。
  • 分解するときはNFD, NFKDを使う。
  • NFDやNFKDはよく似た文字に分解するので、セキュリティに注意 (→Host/Split攻撃)

ToUpper/ToLower

  • Unicode対応のToUpper, ToLowerは想定外の結果を生むので注意が必要。
  • ß (ドイツ・エスツェット)の大文字は "SS"と2文字になる。
  • i (トルコ)の大文字は İ で、 Iの小文字は ı である。
  • Σ (ギリシャ・シグマ)の小文字は σだが、文末だとςである。
  • 小文字のみが収録されている特殊文字は、大文字にすると複数のラテン文字に展開される。
  • アカウントの乗っ取りのようなセキュリティリスクがある。

別の文字セットに変換する

  • unicodeの文字集合の方が大きいので、変換に失敗するか、多対一の変換になる。例えばバックスラッシュと円マークの両方が円マークに変換される。この変換は不可逆変換である。

Ref