6

UnicodeコードポイントとUTF-8の間で変換するための非常に巧妙なコードを見たことがあるので、誰かがこれを持っている(または考案するのを楽しむ)かどうか疑問に思いました。

  • UTF-8文字列が与えられた場合、同じ文字列のUTF-16エンコーディングに必要なバイト数。
  • UTF-8文字列がすでに検証されていると仮定します。BOMがなく、長すぎるシーケンスや無効なシーケンスがなく、nullで終了します。CESU-8ではありません。
  • サロゲートを含む完全なUTF-16をサポートする必要があります。

具体的には、UTF-8シーケンスをコードポイントに完全に変換せずに、サロゲートペアがいつ必要になるかを知るための近道があるのではないかと思います。

私が見た中で最高のUTF-8からコードポイントへのコードはベクトル化手法を使用しているので、ここでもそれが可能かどうか疑問に思います。

4

3 に答える 3

5

効率は常に速度とサイズのトレードオフです。サイズよりも速度を優先する場合、最も効率的な方法は、ソース文字列の長さに基づいて推測することです。

考慮する必要がある4つのケースがあり、最終的なバッファサイズとして最悪のケースを単純に取り上げます。

  • U + 0000-U + 007F-utf8では1バイト、utf16では1文字あたり2バイトにエンコードされます。(1:2 = x2)
  • U + 0080-U + 07FF-2バイトのutf8シーケンス、または1文字あたり2バイトのutf16文字にエンコードされます。(2:2 = x1)
  • U + 0800-U + FFFF-3バイトのutf8シーケンスとして格納されますが、単一のutf16文字に収まります。(3:2 = x.67)
  • U + 10000-U + 10FFFF-4バイトのutf8シーケンス、またはutf16の代理ペアとして格納されます。(4:4 = x1)

最悪の場合の拡張係数は、U + 0000-U + 007fをutf8からutf16に変換する場合です。バイト単位のバッファーは、ソース文字列の2倍の大きさである必要があります。他のすべてのUnicodeコードポイントは、utf16としてutf8としてエンコードされた場合、同じサイズ、またはより小さなバイト単位の割り当てになります。

于 2011-04-20T09:55:14.103 に答える
3

非常に単純です。ヘッドバイト数をカウントし、バイト数を2回カウントしますF0

コード内:

size_t count(unsigned char *s)
{
    size_t l;
    for (l=0; *s; s++) l+=(*s-0x80U>=0x40)+(*s>=0xf0);
    return l;
}

注:この関数は、UTF-16コード単位で長さを返します。必要なバイト数が必要な場合は、2を掛けます。ヌルターミネータを格納する場合は、そのためのスペースも考慮する必要があります(1つの追加コードユニット/ 2つの追加バイト)。

于 2011-04-20T11:25:59.460 に答える
2

これはアルゴリズムではありませんが、私が正しく理解していれば、ルールは次のようになります。

  • MSBが02バイト追加されるすべてのバイト(1 UTF-16コード単位)
    • そのバイトは、U + 0000〜U+007Fの範囲の単一のUnicodeコードポイントを表します
  • MSBを持つすべてのバイト110または11102バイトを追加(1 UTF-16コード単位)
    • これらのバイトは、それぞれ2バイトと3バイトのシーケンスで始まり、U + 0080〜U+FFFFの範囲のUnicodeコードポイントを表します。
  • 4つのMSBセット(つまり、で始まる1111)を持つすべてのバイトは、4バイト(2 UTF-16コード単位)を追加 します
    • これらのバイトは、Unicode範囲の「残り」をカバーする4バイトのシーケンスを開始します。これは、UTF-16ではローサロゲートとハイサロゲートで表すことができます。
  • 1バイトおき(つまり、で始まるバイト10)はスキップできます
    • これらのバイトはすでに他のバイトと一緒にカウントされています。

私はCの専門家ではありませんが、これは簡単にベクトル化できるように見えます。

于 2011-04-20T09:26:25.367 に答える