[ Home | Software Index | Mail ]
ReadMeより
情けないことに開発者のほとんどは基本的な Unicode処理すら理解していません。Appleの技術者もこの例に洩れず、MacOS Xでも数々の初歩的な Unicode絡みの bugを見ることができます。
ほとんどの人が誤解している点をいくつか上げておきます。
まず、Unicodeは「1文字 = 2 byte」や「1文字 = 4 byte」でもなければ「1文字 = 1 code point」でもありません。複数の code pointの組み合わせで1文字を表すことは普通にありますし、encoding form(UTF-8, UTF-16...)によってこれをさらに byte列に変換して表現しますので、1文字を表すのに 10 byte以上を費やす場合もあります。
MacOSの Unicode処理は APIの parameterや HFS+ file systemで主に UTF-16を使っていますが、これを単純に 2 byte毎に分解して扱っては絶対にいけません。このミスを犯して Unicode文字列を破壊している例が非常に多いです。
UTF-16では code point U+010000 〜 U+10FFFFの範囲は surrogate pairを使って 4 byteで表現します。1文字が 2 byteに納まらないと馬鹿の一つ覚えの様にこれを糾弾する人がいますが、surrogate pairなんてのは 2 byte毎に分解して扱ってはいけないケースの最も簡単な物です。処理方法も極めて単純です。
Surrogate pair以外にも「combining character」や「decomposed form」は複数の code pointの組み合わせで1文字を表しますので、2 byteでは納まりません。これらは可変長で surrogate pairの様に単純に扱うことはできません。
Combining characterの例としては以下の様な物が上げられます。
は DTPで必要な Adobe CID 8321を表すための Apple privateな物ですが、直接対応する Unicode code pointが無いこともあり 5 code pointの組み合わせです。これを UTF-8に encodeすると1文字で 15 byte必要になります。
U+0031 + U+20DE
U+F862 + U+6709 + U+9650 + U+4F1A + U+793E
Decomposed formの例としては以下の様な物が上げられます。
U+0041 + U+0301
U+0061 + U+0323 + U+0302
U+304B + U+3099
これらを正しく解釈するためには code pointの属性テーブルを基に組み合わせを動的に判断して文字区切りを決定しないといけません。MacOSにはこのための APIがちゃんと備わっていますが、Unicode処理の基礎を知らないとバラバラに扱って文字を破壊する羽目になります。
根本に前述の様な誤解があるためか normalization(正規化)の目的も正しく理解されていません。
Unicodeでは同じ文字(同じとみなす文字)を違う code pointの組み合わせで表現することができます。これらが混在した状態ではデータの一貫性が保てなかったり、比較等も困難になります。これを避けて表現を統一するために行うのが normalizationです。
標準的な normalizationの方法としては、code pointを分解する方向と結合する方向があり、文字の差異を保持する方向と似た文字は同一視する方向もあります。この組み合わせに対応するのが、Normalization form D(分解 / 差異を保持)、Normalization form C(結合 / 差異を保持)、Normalization form KD(分解 / 同一視)、Normalization form KC(結合 / 同一視) です。これらは目的に応じて使い分けます。例えば、なるべくデータ量は小さくしてかつ曖昧検索キーとして使いたい場合は Normalization form KCを使うのが適切でしょう。
詳しくは、Unicode Normalization Forms を参照して下さい。
以下の資料は絶対です。特に Unicode文字列を扱うプログラムを作っている開発者は The Unicode Standard は必携です。もし手元に無いのでしたらゴミプログラムを作ってしまう前に入手して目を通して下さい。実際には Unicode処理を抜きにして現代的なアプリケーションを作ることは不可能ですから、対象は「全ての開発者」と言い換えても良いでしょう。
余談1) HFS+ file systemは canonical decomposed formの UTF-16でファイル名を保持していますので、accent記号付き roman文字や日本語で濁点が付いた「が」等は複数の code pointの組み合わせで表現します。これを等ととんでもないことを言う人を見かけますが、これは「私は Unicodeは解りません」宣言と取ってまず間違いありません。
- Unicodeのバージョンが違う。
- 他と違い normalizeされている。(多分 decompositionのことを言いたいのでしょう。「Unicode standard Normalization form D に準じて normalizeされている」 なら正しい表現です。)
- HFS+では日本語の濁点付きの文字は2文字になる。(「HFS+では日本語の濁点付きの文字は2つの code pointの組み合わせで表現する」なら正しい表現です。)
- 非標準で他のプラットフォームと互換性を取る上での障害
余談2) MacOS Xでは dragしたファイルを識別するのに内部で "file://..."という URL型式の表現を使っていますが、これは重大な設計ミスです。このため扱えないファイルが出て来るという致命的な bugを2つ抱えてしまっています。
ひとつは URLが長くなると URLから FSRef / POSIX pathへの変換がエラーになってしまうため、ファイルの置かれた場所によっては drag & dropで全く操作できなくなることです。Cocoaアプリケーションは未だに pathでファイル位置を扱うという石器時代の処理方法を取っていますが、POSIX pathには 1024 byteという限界があるためこれを超えるファイルを扱おうとすると無反応になるか敢え無くクラッシュします。長過ぎる URLが扱えない bugはこれを回避 / 隠蔽する策略かも知れません。
あとひとつはファイル名に UTF-16の surrogate pairを含んだファイルを drag & dropで操作できません。このこと一つを取っても Apple技術者の Unicode理解度に疑念が湧きます。
この Pageは MacOS X + Radio UserLand で作っています。