This section provides a quick introduction of paired surrogates which are pairs of 16-bit integers to represent Unicode code points in the U+10000...0x10FFFF range.
The goal UTF-16 encoding is to:
Map Unicode code points in the range of U+0000...0xFFFF with 2 bytes (16 bits).
Map Unicode code points in the range of U+10000...0x10FFFF with 4 bytes (32 bits).
The mapping for the U+0000...0xFFFF range is straightforward.
But the mapping for the U+10000...0x10FFFF range is tricky,
because we want the resulting 4-byte stream can be recognized as 1 character in the U+10000...0x10FFFF range
instead of 2 characters in the U+0000...0xFFFF range. This is achieved by using paired surrogates.
What Are Paired Surrogates?
Paired surrogates are pairs of 2 16-bit unsigned integers in the surrogate area between 0xD800
and 0xDFFF. Since there are no Unicode characters assigned with code points in the surrogate area,
Paired surrogates can be easily recognized as 1 character in the U+10000...0x10FFFF range.
The UTF-16 specification defines that the first surrogate must be in the high surrogate
area between 0xD800 and 0xDBFF and the second surrogate in the low surrogate
area between 0xDC00 and 0xDFFF.
Based on my understanding of the specification, here is the algorithm to convert a Unicode code point in the
range of U+10000...0x10FFFF to a surrogate pair:
Let U be the unsigned integer value of the give code point.
Let U' = U - 0x10000. U' is less than or equal to 0xFFFFF and now can be
expressed as an unassigned 20-bit integer.
Divide 20 bits of U' into 2 blocks with 10 bits in each block as
0byyyyyyyyyyxxxxxxxxxx.
Let S1 = 0xD800 + 0byyyyyyyyyy, or S1 = 0b110110yyyyyyyyyy. S1 is the first surrogate of the surrogate pair.
Let S2 = 0xDC00 + 0bxxxxxxxxxx, or S2 = 0b110111xxxxxxxxxx. S2 is the second surrogate of the surrogate pair.
Exercise: Write an algorithm to convert a surrogate pair back to a Unicode code point.