C:确定UTF-8字符串中UTF-16字符串需要多少字节的最有效方法

时间:2011-04-20 09:16:07

标签: c algorithm utf-8 utf-16 unicode-string

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

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

具体来说,我想知道是否有快捷方式可以在不完全将UTF-8序列转换为代码点的情况下知道何时需要代理对。

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

3 个答案:

答案 0 :(得分:5)

效率始终是速度与尺寸的权衡。如果速度优于大小,那么最有效的方法就是根据源字符串的长度进行猜测。

有4种情况需要考虑,只需将最坏情况作为最终缓冲区大小:

  • U + 0000-U + 007F - 将在utf8中编码为1byte,在utf16中编码为每字符2bytes。 (1:2 = x2)
  • U + 0080-U + 07FF - 编码为2byte utf8序列,或每字符2字节utf16个字符。 (2:2 = x1)
  • U + 0800-U + FFFF - 存储为3byte utf8序列,但仍然适合单个utf16字符。 (3:2 = x.67)
  • U + 10000-U + 10FFFF - 存储为4byte utf8序列或utf16中的代理对。 (4:4 = x1)

更糟糕的扩展因子是将U + 0000-U + 007f从utf8转换为utf16时:缓冲区按字节顺序只需要是源字符串的两倍。当将utf16编码为utf8时,每个其他unicode代码点都会产生相同的大小或更小的字节分配。

答案 1 :(得分: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.如果你要存储一个空终止符,你还需要考虑空间(一个额外的代码单元/两个额外的字节)。

答案 2 :(得分: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专家,但这看起来很容易上传。