たとえば、としてエンコードされたUnicode文字列がありますUTF8
。Unicodeの1つの文字列は、数バイトの表現を持つことができます。Unicode文字列の正規の(正規化された)形式が存在するか、作成できるのでしょうか。たとえば、そのような文字列をmemcmp(3)
などと比較できます。たとえば、ICUや他のC/C++
ライブラリでそれを実行できますか?
3 に答える
Unicode の正規化を探しているかもしれません。基本的に 4 つの異なる正規形があり、それぞれが、すべての同等の文字列が後に共通の形を持つことを保証します。ただし、多くの場合、ロケールも考慮する必要があるため、これはバイト対バイトの比較を行う安価な方法かもしれません (UTF-8 や UTF-16 などの同じ Unicode 変換形式を保証する場合)。および同じ通常の形式) その限られたユースケースを除けば、あまりメリットはありません。
Unicodeコードポイントシーケンスの比較:
UTF-8は、それ自体が標準的な表現です。同じUnicodeコードポイントで構成される2つのUnicode文字列は、常にまったく同じUTF-8バイトシーケンスにエンコードされるため、と比較できますmemcmp
。これはUTF-8エンコーディングに必要なプロパティです。そうでないと、簡単にデコードできません。しかし、さらに先に進むことができます。これは、すべての公式Unicodeエンコーディングスキーム、UTF-8、UTF-16、およびUTF-32に当てはまります。これらは文字列を異なるバイトシーケンスにエンコードしますが、常に同じ文字列を同じシーケンスにエンコードします。エンディアンとプラットフォームの独立性を考慮する場合、16ビットまたは32ビット値の読み取りまたは書き込み時にバイト順序を処理する必要がないため、UTF-8が推奨されるエンコード方式です。
したがって、答えは、2つの文字列が同じエンコードスキーム(UTF-8など)とエンディアン(UTF-8の問題ではない)でエンコードされている場合、結果のバイトシーケンスは同じになるということです。
Unicode文字列の比較:
処理がより難しい他の問題があります。Unicodeでは、一部のグリフ(画面または紙に表示される文字)は、単一のコードポイントまたは2つの連続するコードポイントの組み合わせ(結合文字と呼ばれます)で表すことができます。これは通常、アクセント記号や発音区別符号などのあるグリフに当てはまります。コードポイント表現が異なるため、対応するバイトシーケンスは異なります。これらの結合文字を考慮した文字列の比較は、単純なバイト比較では実行できません。まず、正規化する必要があります。
他の回答は、Unicode文字列を通常の形式に変換するために使用できるいくつかのUnicode正規化手法、標準形、およびライブラリに言及しています。次に、それらをバイトごとに任意のエンコード方式と比較できるようになります。
文字列を Unicode 正規化形式の 1 つに正規化しようとしています。libicu はこれを行うことができますが、UTF-8 文字列ではできません。最初に eg を使用して UChar に変換しucnv_toUChars
、次に で正規化しunorm_normalize
、次に を使用して変換し直す必要がありucnv_fromUChars
ます。UTF-8 エンコーディング用の ucnv_* の特定のバージョンもあると思います。
memcmp が唯一の目標である場合は、もちろん、 の後に UChar 配列で直接行うことができますunorm_normalize
。