如何计算代理对?

时间:2012-01-15 08:28:11

标签: unicode utf-8

如果unicode使用17位代码点,那么如何从代码点计算代理对?

2 个答案:

答案 0 :(得分:7)

Unicode代码点是标量值,范围从0x000000到0x10FFFF。因此它们是21位整数,而不是17位。

代理对是UTF-16形式的机制。这表示21位标量值为一个或两个16位代码单元。

  • 从0x000000到0x00FFFF的标量值表示为单个16位代码单元,从0x0000到0xFFFF。
  • 从0x00D800到0x00DFFF的标量值不是Unicode中的字符,因此它们永远不会出现在Unicode字符串中。
  • 从0x010000到0x10FFFF的标量值表示为两个16位代码单元。第一代码单元对标量值的高11位进行编码,作为范围从0xD800-0xDBFF的代码单元。在四位中编码来自0x01-0x10的值有点棘手。第二代码单元对标量值的低10位进行编码,作为范围从0xDC00-0xDFFF的代码单元。

使用示例代码在Unicode联盟的常见问题解答UTF-8, UTF-16, UTF-32 & BOM中详细解释了这一点。该FAQ引用了Unicode标准中更详细的部分。

答案 1 :(得分:4)

如果是您所使用的代码,以下是单个代码点分别以UTF-16和UTF-8编码的方式。

UTF-16代码单的单个代码点:

if (cp < 0x10000u)
{
   *out++ = static_cast<uint16_t>(cp);
}
else
{
   *out++ = static_cast<uint16_t>(0xd800u + (((cp - 0x10000u) >> 10) & 0x3ffu));
   *out++ = static_cast<uint16_t>(0xdc00u + ((cp - 0x10000u) & 0x3ffu));
}

UTF-8代码单的单个代码点:

if (cp < 0x80u)
{
   *out++ = static_cast<uint8_t>(cp);
}
else if (cp < 0x800u)
{
   *out++ = static_cast<uint8_t>((cp >> 6) & 0x1fu | 0xc0u);
   *out++ = static_cast<uint8_t>((cp & 0x3fu) | 0x80u);
}
else if (cp < 0x10000u)
{
   *out++ = static_cast<uint8_t>((cp >> 12) & 0x0fu | 0xe0u);
   *out++ = static_cast<uint8_t>(((cp >> 6) & 0x3fu) | 0x80u);
   *out++ = static_cast<uint8_t>((cp & 0x3fu) | 0x80u);
}
else
{
   *out++ = static_cast<uint8_t>((cp >> 18) & 0x07u | 0xf0u);
   *out++ = static_cast<uint8_t>(((cp >> 12) & 0x3fu) | 0x80u);
   *out++ = static_cast<uint8_t>(((cp >> 6) & 0x3fu) | 0x80u);
   *out++ = static_cast<uint8_t>((cp & 0x3fu) | 0x80u);
}