6

我正在用 C 编写 HTML 解析器,并希望正确遵循W3C 关于解析器实现的指南。关键点之一是解析器对 Unicode 代码点流而不是字节进行操作,这是有道理的。

基本上,然后,给定一个已知字符编码的缓冲区(我将得到一个显式的输入编码,或者将使用 HTML5 预扫描算法做出一个好的猜测),C 中最好的方法是什么——理想情况下是跨平台的,但坚持对 UNIX 来说很好——迭代一个等价的 Unicode 代码点序列?

是否分配了一些合理大小的缓冲区并使用iconv该方法?我应该看ICU吗?宏之类的U16_NEXT似乎非常适合我的任务,但是 ICU 文档非常冗长,而且很难确切地了解如何将它们粘合在一起。

4

3 回答 3

2

ICU是个不错的选择。我将它与 C++ 一起使用并且非常喜欢它。我很确定您也会在 C 中获得类似的深思熟虑的 API。

本教程可能不完全相同但有些相关,它解释了如何执行流式传输/增量音译(这种情况下的困难是“光标”有时可能代码点内)。

于 2013-01-17T19:29:57.870 回答
2

下面将解码一个代码点并返回将字符串增加多少(“咀嚼”多少)。请注意,xs_utf16 是一个无符号短整数。更多信息: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 回答
0

您可能对两件事感兴趣:

  1. Markus Kuhn Unicode 教程
  2. lib9,Plan9 的 utf 库,UTF 的发明者正在研究的操作系统。
于 2013-01-18T00:13:30.143 回答