【问题标题】:How are surrogate pairs calculated?如何计算代理对?
【发布时间】:2012-01-15 08:28:11
【问题描述】:

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

【问题讨论】:

  • 什么意思? Unicode 代码点不是 17 位,并且 UTF-8 不使用代理对。
  • Unicode 代码点大约需要 21 位。它虽然使用了每个 65536 个代码点的 17 个平面,但总共有 1114112 个代码点。大约是 20.087 位。

标签: unicode utf-8


【解决方案1】:

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

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

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

Unicode 联盟的常见问题解答UTF-8, UTF-16, UTF-32 & BOM 中通过示例代码对此进行了详细说明。该常见问题解答指的是 Unicode 标准中包含更多详细信息的部分。

【讨论】:

【解决方案2】:

如果是您所追求的代码,以下是单个代码点分别以 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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-22
    • 1970-01-01
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    • 2014-12-09
    • 2018-07-29
    • 1970-01-01
    相关资源
    最近更新 更多