D800〜E000の領域をサロゲートと呼び,連続する2つの2バイトコードをあわせて1文字を表現することにしている(1文字2バイトのルールがくずれている). この2つの2バイトコードのことを“サロゲート ペア”と呼び,前半2バイトを上位サロゲート(High Surrogates),後半2バイトを下位サロゲート(Low Surrogates)と呼ぶ. サロゲート領域は下の図のように2分割されていて, 低位側半分が上位サロゲート,高位側の残り半分が下位サロゲート用に割り当てられている. いずれも1024個ずつのコードが割りあたっているので,表現できる文字数は最大1024×1024=1M(約100万)文字となる.
上位サロゲートのための領域には128個ぶんだけ,ユーザ定義文字用の領域である上位私用サロゲート(High Private Surrogates)が用意されている. ユニコードにはもともとE000〜F800の範囲に6144文字分の“私用領域”(Private Use Area)が設けられているけども, それでは足りないという人がいるみたいで,サロゲート領域でも私用領域を128×1024=約13万文字分追加している.
範囲 | コード数 | 領域の名前 | 説明 |
---|---|---|---|
D800-DB7F | 1024-128 | 上位サロゲート | サロゲートペアの前半の2バイト |
DB80-DBFF | 128 | 上位私用サロゲート | サロゲートペアの前半の2バイトが,この領域の値になっている場合は私用文字(外字)とみなされる. |
DC00-E000 | 1024 | 下位サロゲート | サロゲートペアの後半の2バイト |
サロゲートペアをつかってあらわそうとする文字が,
(0)第ppppp
面の第rrrrrrrr
区,第cccccccc
点にある文字だとする.
サロゲートペアであらわす領域は面01〜10Hで,面00ではないことがわかってるので,
(1)ppppp-1
→qqqq
として1ビット節約する.
次に,(2)この4+8+8=20ビットのビット列を10ビットずつにわける.
(3)10ビットずつに分離したビット列の上位6ビットに それぞれ上位サロゲートと下位サロゲートの開始位置の値を足す.
具体的には,上位サロゲートにはD800,下位サロゲートにはDC00を加える.
下の流れを見るとわかるけど,(2)までにつくった10ビット×2個のビット列は,
D800およびDC00の0でないビット部分と重ならないため,加えるといってもビットORをとるだけでOK.
逆に言えばサロゲートペア表現からUnicodeスカラ値にもどすときにも上位6ビットをマスクするANDでOK.
(0) Original Scalar Value Plane Row Cell <----> <-------> <-------> p pppp | rrrr rrrr | cccc cccc 5 + 8 + 8 bits (1) Reduce one bit by qqqq = ppppp - 1 qqqq | rrrr rrrr | cccc cccc 4 + 8 + 8 bits (2) Divide bits into two 10-bit sequences qq qqrr rrrr | rr cccc cccc 10 + 10 bits (3) Shift them to the surrogate area ( D 8 0 0 D C 0 0 Hexadecimal Form) 1101 1000 0000 0000 1101 1100 0000 0000 Binary Form + qq qqrr rrrr rr cccc cccc ------------------------------------------- 1101 10qq qqrr rrrr 1101 11rr cccc cccc
サロゲートペアを使わない場合,2バイト(16ビット)のコードであらわせる文字数は最大65535文字. サロゲートペアを使ってBMP(面00)+面01〜面10Hを表せるようにしたエンコーディング スキームがUTF-16.