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.
Character | Binary code point | Binary UTF-16 | UTF-16 hex code units | UTF-16BE hex bytes | UTF-16LE hex bytes | |
---|---|---|---|---|---|---|
$ | U+0024 | 0000 0000 0010 0100 | 0000 0000 0010 0100 | 0024 | 00 24 | 24 00 |
€ | U+20AC | 0010 0000 1010 1100 | 0010 0000 1010 1100 | 20AC | 20 AC | AC 20 |
? | U+10437 | 0001 0000 0100 0011 0111 | 1101 1000 0000 0001 1101 1100 0011 0111 | D801 DC37 | D8 01 DC 37 | 01 D8 37 DC |
? | U+24B62 | 0010 0100 1011 0110 0010 | 1101 1000 0101 0010 1101 1111 0110 0010 | D852 DF62 | D8 52 DF 62 | 52 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))