Unicode:Surrogate Pairs UTF-16中用于扩展字符

解释

Surrogate Pairs 主要是针对增补字符,此时一个16位的编码(2个Byte的UTF-16)已经无法表示,所以就扩展成需要两个16位的编码单元。也就是说,在范围U+10000到U+10FFFF间的编码则使用一对16位编码单元表示,称作代理对(surrogate pair)。

在BMP内的字符,仍然按照UTF-16的编码规则,使用两个字符来表示。 (注:BMP内的字符编码,不包含从U+D800到U+DFFF的预留码位。这些预留码位就恰好用于扩展字符编码)

增补字符的编码值已经超过了BMP的编码范围,需要使用一对UTF-16字符来表示一个字符。把Unicode编码记作U。编码规则如下:

  • 如果U<0x10000,U的UTF-16编码就是U对应的16位无符号整数。

  • 如果U≥0x10000,

    • 先计算U’=U-0x10000,

    • 然后将U’写成二进制形式:yyyy yyyy yyxx xxxx xxxx,(注意这里共计20位)

    • U的UTF-16编码(二进制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。

这两个字符就称为surrogate pair(代理对)。第一个代理字符为16位编码,范围为U+D800到U+DBFF,第二个代理字符也是一个16位编码,范围为U+DC00 to U+DFFF。

 

Wikipedia Examples

在wikipedia上有一个计算的例子,原则上和上面是一样的,表述略有不同:

把 U+10437 (?) 转换成 UTF-16:

  • 0x10437- 0x100000 = 0x0437.
  • high surrogate: 0x0437右移10位 (相当于除以0x400,也相当于扩展成20位之后,取左边的高10位), 然后加上 0xD800,得到:0x0001 + 0xD800 = 0xD801.
  • low surrogate, 取低10位(相当于对0x400取余), 然后加上0xDC00, 得到:0x0037 + 0xDC00 = 0xDC37.

从 UTF-16 解码 U+10437 (?) :

  • 取high surrogate, 0xD801 - 0xD800(等价于:0xD801&0x3FF), 结果再乘以 0x400, 得到:(0xD801-0xD800)×0x400=0x0001×0x400=0x0400
  • 取low surrogate,0xDC37-0xDC00(等价于:0xDC37&0x3FF), 得到:(0xDC37-0xDC00) = 0x0037.
  • 把上述两个结果相加,0x0400+ 0x0037 =0x0437, 最后加上0x10000得到0x10437,这个就是最终的UTF-32 code point, 0x10437.

The following table summarizes this conversion, as well as others. The colors indicate how bits from the code point are distributed among the UTF-16 bytes. Additional bits added by the UTF-16 encoding process are shown in black.

CharacterBinary code pointBinary UTF-16UTF-16 hex
code units
UTF-16BE
hex bytes
UTF-16LE
hex bytes
$U+00240000 0000 0010 01000000 0000 0010 0100002400 2424 00
U+20AC0010 0000 1010 11000010 0000 1010 110020AC20 ACAC 20
?U+104370001 0000 0100 0011 01111101 1000 0000 0001 1101 1100 0011 0111D801 DC37D8 01 DC 3701 D8 37 DC
?U+24B620010 0100 1011 0110 00101101 1000 0101 0010 1101 1111 0110 0010D852 DF62D8 52 DF 6252 D8 62 DF

 

应用举例:

python的源码(UnicodeObject.h)中有这么几个定义,

1。用来判断是否有UTF-16代理surrogate,

#define Py_UNICODE_IS_SURROGATE(ch)     (0xD800 <= (ch) && (ch) <= 0xDFFF)
#define Py_UNICODE_IS_HIGH_SURROGATE(ch)     (0xD800 <= (ch) && (ch) <= 0xDBFF)
#define Py_UNICODE_IS_LOW_SURROGATE(ch)      (0xDC00 <= (ch) && (ch) <= 0xDFFF)

2。从UTF16解码的过程如下,

#define Py_UNICODE_JOIN_SURROGATES(high, low)  \
    (((((Py_UCS4)(high) & 0x03FF) << 10) |      \
      ((Py_UCS4)(low) & 0x03FF)) + 0x10000)

注:Py_UCS4定义:typedef uint32_t Py_UCS4;

3。取得high surrogate和low surrogate的宏代码如下

/* high surrogate = top 10 bits added to D800 */
#define Py_UNICODE_HIGH_SURROGATE(ch) (0xD800 - (0x10000 >> 10) + ((ch) >> 10))
/* low surrogate = bottom 10 bits added to DC00 */
#define Py_UNICODE_LOW_SURROGATE(ch) (0xDC00 + ((ch) & 0x3FF))

 

【1】 https://en.wikipedia.org/wiki/UTF-16

posted @ 2019-01-12 13:19  SpaceVision  阅读(101)  评论(0编辑  收藏  举报