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

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

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

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

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

效率始终是速度与规模之间的权衡。 如果速度优于大小,则最有效的方法是根据源字符串的长度进行猜测。

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

  • U + 0000-U + 007F – 将在utf8中编码为1字节,在utf16中编码为每字符2字节。 (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代码点都会产生相同的大小或更小的字节分配。

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

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

  • 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专家,但这看起来很容易上传。