4

「大文字と小文字を区別しない」正規化された形式の Unicode テキストを生成する必要がある C プロジェクトに取り組んでいます。最初に正規化フォーム NFD に変換し、次に Unicode 大文字と小文字の折り畳みアルゴリズムを適用し、最後に結果を Unicode 正規化フォーム NFC に変換することによって達成される正規化フォームを定義することにしました。

私は Unicode 表現とユーティリティ関数を ICU の C API に依存しており、ICU の関数unorm_normalize()u_strFoldCase()関数を使用して私のスキームを実装するのはかなり簡単でした。しかし、私のテストの 1 つが失敗しており、その理由がわかりません。ICU は、私の予想とは異なる NFC フォームを生成しているようです。

入力シーケンスは、次の BMP コード ポイントで構成されます。

U+0020, U+1EA5, U+0328, U+1EC4, U+031C

デバッガーを介して、ケース フォールディング後の中間結果について ICU と同意することを確認しました。

U+0020 U+0061 U+0328 U+0302 U+0301 U+0065 U+031C U+0302 U+0303

特に、NFD を形成するための初期の変換では、関係する文字の相対 CCC 番号に基づいて、文字 U+031C が U+1EC4 の分解の途中に移動したことに特に注意してください。それは私がテストしようとしているものの一部です。

ここで良い点: ICU によると、折りたたまれた文字シーケンスの NFC 正規化は

U+0020 U+0105 U+0302 U+0301 U+1ec5 U+031C

一方、私はそうあるべきだと思います

U+0020 U+0105 U+0302 U+0301 U+0065 U+031C U+0302 U+0303

末尾の 3 つの結合文字は既に標準的な順序になっており、U+0065 と U+031C の標準的な合成は存在しないためです。

だから、2つの質問:

  1. 正しい NFC フォームはどれですか?
  2. ICUが正しいなら、なぜですか?
4

1 に答える 1

7

ICUは正しいです。その理由を理解するには、Unicode Standard の第 3 章で定義されている Canonical Composition Algorithm をご覧ください。

D117 Canonical Composition Algorithm:コード化された文字シーケンス (Canonical Decomposition または Compatibility Decomposition の) の 2 番目の文字から開始して、最終文字まで順番に進み、次の手順を実行します。

R1 コード化された文字列を文字 C から逆方向 (左) にシークして、文字列で C の前にある最後の Starter L を見つけます。

R2 そのような L があり、C が L からブロックされておらず、シーケンス <L, C> と標準的に等価なプライマリ コンポジット P が存在する場合、シーケンス内の L を P に置き換え、シーケンスから C を削除します.

また、特に以下の定義を理解する必要があります。

D115ブロック済み: A と C を、コード化された文字シーケンス <A, ... C> 内の 2 文字とします。C が A からブロックされるのは、ccc(A)=0 であり、コード化された文字列の A と C の間に文字 B が存在する場合 (つまり、<A、... B、... C>)、およびいずれかの ccc が存在する場合のみです。 (B)=0 または ccc(B) >= ccc(C)。

入力シーケンスの次の部分文字列を考えてみましょう。

U+0065 U+031C U+0302 U+0303

キャラクターU+031Cから始めて、次の最後のスターターに戻りますU+0065

U+0065 U+031C U+0302 U+0303
L      C

C は明らかに L からブロックされていませんが、同等のプライマリ コンポジットがない<L, C>ため、次の文字に進みます。

U+0065 U+031C U+0302 U+0303
L             C

現在、C はまだ L からブロックされていません (これはおそらく誤解されていることですccc(U+031C) = 220 < 230 = ccc(U+0302)) 。したがって、L を置き換えて C を削除します。U+00EAU+0065 U+0302

U+00EA U+031C U+0303
L             C

繰り返しますが、C は L からブロックされておらず、プライマリ コンポジットU+1EC5は と同等でU+00EA U+0303あるため、合成の最終結果は次のようになります。

U+1EC5 U+031C

これは、ICU からの出力と一致します。

于 2014-06-21T15:51:31.773 に答える