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上有一个计算的例子,原则上和上面是一样的,表述略有不同:
把 U+10437 (?) 转换成 UTF-16:
从 UTF-16 解码 U+10437 (?) :
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))
联系客服