6

私は C で HTML パーサーを作成しており、パーサーの実装に関する W3C ガイドラインに正しく従おうとしています。重要なポイントの 1 つは、パーサーがバイトではなく Unicode コード ポイントのストリームで動作することです。これは理にかなっています。

基本的に、既知の文字エンコーディングのバッファが与えられた場合(明示的な入力エンコーディングが与えられるか、適切な推測を行うために HTML5 プレスキャン アルゴリズムを使用します)、C での最善の方法は何ですか — 理想的にはクロスプラットフォームですが、固執しますUNIX への変換は問題ありません — 同等の Unicode コード ポイントのシーケンスを反復するには?

適切なサイズのバッファをいくつか割り当てて、iconvその方法を使用していますか? ICUを見た方がいいですか?のようなマクロU16_NEXTは私のタスクに適しているように見えますが、ICU のドキュメントは信じられないほど長く、それらをどのように結合するかを正確に理解するのは少し困難です。

4

3 に答える 3

2

以下は、コードポイントをデコードし、文字列をどれだけインクリメントするか (「噛んだ」量) を返します。xs_utf16 は unsigned short であることに注意してください。詳細: http://sree.kotay.com/2006/12/unicode-is-pain-in.html

enum
{
    xs_UTF_Max          = 0x0010FFFFUL,
    xs_UTF_Replace      = 0x0000FFFDUL,
    xs_UTF16_HalfBase   = 0x00010000UL,
    xs_UTF16_HighStart  = 0x0000D800UL,
    xs_UTF16_HighEnd    = 0x0000DBFFUL,
    xs_UTF16_LowStart   = 0x0000DC00UL,
    xs_UTF16_LowEnd     = 0x0000DFFFUL,
    xs_UTF16_MaxUCS2    = 0x0000FFFFUL,
    xs_UTF16_HalfMask   = 0x000003FFUL,
    xs_UTF16_HalfShift  = 10
};


int32 xs_UTF16Decode (uint32 &code, const xs_utf16* str, int32 len, bool strict)
{
          if (str==0||len==0)          {code=0; return 0;}

          uint32 c1 = str[0];

          //note: many implementations test from HighStart to HighEnd,
          //                 this may be a partial code point, and is incorrect(?)
          //                 trivial checking should exclude the WHOLE surrogate range
          if (c1<xs_UTF16_HighStart || c1>xs_UTF16_LowEnd)          return 1;
                             //really an error if we're starting in the low range

          //surrogate pair
          if (len<=1 || str[1]==0)                                  {code=xs_UTF_Replace; return strict ? 0 : 1;} //error
          uint32 c2 = str[1];
          code = ((c1-xs_UTF16_HighStart)<<xs_UTF16_HalfShift) + (c2-xs_UTF16_LowStart) + xs_UTF16_HalfBase;

          if (strict==false)                                        return 2;

          //check for errors
          if (c1>=xs_UTF16_LowStart && c1<=xs_UTF16_LowEnd)         {code=xs_UTF_Replace; return 0;} //error
          if (c2<xs_UTF16_LowStart  || c2>xs_UTF16_LowEnd)          {code=xs_UTF_Replace; return 0;} //error
          if (code>xs_UTF_Max)                                      {code=xs_UTF_Replace; return 0;} //error

          //success
          return 2;
}
于 2013-02-15T01:38:43.420 に答える
2

ICUは良い選択です。私は C++ でそれを使用し、とても気に入りました。C でも同様の考え抜かれた API が得られると確信しています。

完全に同じというわけではありませんが、ストリーミング/インクリメンタル音訳を実行する方法を説明するこのチュートリアルが多少関連している可能性があります (この場合の問題は、「カーソル」がコード ポイント内にある場合があることです)。

于 2013-01-17T19:29:57.870 に答える
0

次の 2 つのことに関心があるかもしれません。

  1. Markus Kuhn Unicode チュートリアル
  2. lib9、Plan9 の utf ライブラリ、UTF の発明者が取り組んでいた Os。
于 2013-01-18T00:13:30.143 に答える