6

我已经看到了一些非常聪明的代码,用于在 Unicode 代码点和 UTF-8 之间进行转换,所以我想知道是否有人拥有(或喜欢设计)这个。

  • 给定一个 UTF-8 字符串,相同字符串的 UTF-16 编码需要多少字节。
  • 假设 UTF-8 字符串已经过验证。它没有 BOM,没有过长的序列,没有无效的序列,是空终止的。它不是CESU-8
  • 必须支持带有代理项的完整 UTF-16。

具体来说,我想知道是否有捷径可以知道何时需要代理对,而无需将 UTF-8 序列完全转换为代码点。

我见过的最好的 UTF-8 到代码点代码使用矢量化技术,所以我想知道这是否也可能在这里。

4

3 回答 3

5

效率始终是速度与大小的权衡。如果速度比大小更受青睐,那么最有效的方法就是根据源字符串的长度进行猜测。

有4种情况需要考虑,简单取最坏的情况作为最终的缓冲区大小:

  • U+0000-U+007F - 将在 utf8 中编码为 1 个字节,在 utf16 中每个字符编码为 2 个字节。(1:2 = x2)
  • U+0080-U+07FF - 编码为 2 字节 utf8 序列,或每个字符 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 时:缓冲区,按字节计算,只需要是源字符串的两倍大。当编码为 utf16 为 utf8 时,每个其他 unicode 代码点都会产生相同的大小或较小的字节分配。

于 2011-04-20T09:55:14.103 回答
3

非常简单:计算头字节数,重复计算字节数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。如果您要存储一个空终止符,您还需要为此考虑空间(一个额外的代码单元/两个额外的字节)。

于 2011-04-20T11:25:59.460 回答
2

这不是算法,但如果我理解正确,规则如下:

  • 具有 MSB 的每个字节0增加 2 个字节(1 个 UTF-16 代码单元)
    • 该字节表示 U+0000 - U+007F 范围内的单个 Unicode 代码点
  • 每个具有 MSB 的字节1101110添加 2 个字节(1 个 UTF-16 代码单元)
    • 这些字节分别以 2 和 3 字节序列开始,它们代表 U+0080 - U+FFFF 范围内的 Unicode 代码点
  • 具有 4 个 MSB 集的每个字节(即以 开头1111)添加 4 个字节(2 个 UTF-16 代码单元)
    • 这些字节开始 4 字节序列,覆盖 Unicode 范围的“其余部分”,可以用 UTF-16 中的低和高代理表示
  • 10可以跳过 每隔一个字节(即以 开头的字节)
    • 这些字节已经与其他字节一起计算。

我不是 C 专家,但这看起来很容易矢量化。

于 2011-04-20T09:26:25.367 回答