ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

Unicode のサロゲートペアとは何か

こないだ同僚に Unicodeサロゲートペアについて説明する機会があって、それで Unicode の話をブログ記事に書きたくなったのでサロゲートペアについて書いておこうと思う。

この記事は Unicode Standard version 6.3.0 を見ながら書いた。

文字とコードポイント

抽象文字 (abstract character) を計算機上で扱うためには、符号化する必要がある。 Unicode では、文字の符号化のために使用できる整数の範囲を コード空間 (Codespace; 符号空間) と呼んでいる。 0 から 0x10FFFF がその範囲である。 そして、その空間に属する値を コードポイント (Code Point; 符号位置) と呼ぶ。

次の図は、抽象的な 「Å」 という文字と、対応する 符号化文字 (Encoded Character) を表現するコードポイントの関係を表すものである。 (Unicode Standard 6.2 より。) 下の図を見るとわかるように、1 つの抽象文字が複数の符号化文字に結び付けられることがある。 また、1 つの抽象文字が複数の符号化文字により構成されることもある。

f:id:nobuoka:20140604222944p:plain

Unicode コードポイントを参照する際は、「U+」 という接頭辞を付けて、16 進数表記の数字を続けて記述するのが Unicode Standard での表記法である。 また、符号化文字も単にコードポイントだけで参照することができる。

つまり、上の図における 00C5 という符号化文字を参照するために、「U+00C5」 という表記を使用できる。

なお、コードポイントは、必ずしも符号化文字に割り当てられているとは限らない。 (後で説明するが、サロゲートコードポイント (Surrogate Code Point) がその一例である。)

符号化文字と文字符号化形式

さて、上で述べたように Unicode 文字にはそれぞれコードポイントが与えられているわけであるが、そのコードポイントを計算機上でどのように表現するか、という意味でさらに符号化する必要がある。

Unicode Standard では、UTF-8UTF-16UTF-32 という 文字符号化形式 (Character Encoding Form) が提供されている。 それぞれ 8 ビット、16 ビット、32 ビットを 符号単位 (Code Unit) とする符号化方式である。

f:id:nobuoka:20140604234845p:plain

上の図は、いくつかのコードポイントが各文字符号化方式でどのように表現されるかを表した例である。 (Unicode Standard 6.2 より。)

任意のコードポイントは単一の 32 ビット符号単位で表現できるため、UTF-32 では常に 1 符号単位が 1 コードポイントを表す。 UTF-16 では、U+0000 から U+FFFF までのコードポイントは 1 符号単位で表現され、U+10000 以降のコードポイントは後述するサロゲートペアで表現される。 UTF-8 では、1 コードポイントを表現するために 1 個から 4 個の符号単位が使用される。

サロゲートペアについて

さて、いよいよ サロゲートペア (Surrogate Pair; 代用対) の説明を行う。 サロゲートペアとは、一言で言ってしまうと 16 ビット符号単位の組による単一の抽象文字の表現である。 UTF-16 でのみ用いられる。

UTF-16 は、16 ビットを符号単位とする文字符号化形式なので、任意のコードポイントを 1 符号単位で表現することができない。 16 ビットで表現可能な U+0000 から U+FFFF までのコードポイントについては、そのままコードポイントの数値を 16 ビットで表現するようになっている。 残りの U+10000 から U+10FFFF までのコードポイントは 16 ビットの符号単位の組で表現されるようになっていて、この組のことをサロゲートペアと呼ぶ。 例えば、先の図では U+10384 というコードポイントを表現するために、0xD800 と 0xDF84 の 2 つの符号単位の組が用いられていた。

上で 「U+0000 から U+FFFF までのコードポイントについては、コードポイントをそのまま 16 ビットで表現するようになっている」 と述べたが、それだとサロゲートペアのために使用できる符号単位がなくなってしまう。 そこで、Unicode では U+D800 から U+DFFF までのコードポイントをUnicode 文字に割り当てないようにし、0xD800 から 0xDFFF までの 16 ビット符号単位をサロゲートペアに使用できるようにしている。 これらのコードポイントはサロゲートコードポイントと呼ばれる。

つまり、より正確にいうと、UTF-16 では 「U+0000 から U+D7FF までと U+E000 から U+FFFF までのコードポイントについては 16 ビットの 1 符号単位であらわされ、U+10000 から U+10FFFF までのコードポイントは 2 つの符号単位の組で表現される」 ということになる。

文字符号化形式のためにコードポイントが使用されるのは奇妙な感じがするが、このような形になっているのは、もともと UTF-16 が固定長の文字符号化方式として設計されていたという歴史的な理由らしい。 (あんまり詳しくない。)

備考

U+0000 から U+FFFF までのコードポイント (文字符号化形式 UTF-16 において、単一の符号単位で表現できるコードポイント) は BMP コードポイント (BMP Code Point; BMP符号位置) と呼ばれる。 U+10000 から U+10FFFF までのコードポイントは 補助コードポイント (Supplementary Code Point; 補助符号位置) と呼ばれる。

ややこしいと思うこと

サロゲートペアはあくまで UTF-16 という文字符号化形式でのみ使用されるものであるが、UTF-16サロゲートペアが使用されるために U+D800 から U+DFFF のコードポイントがサロゲートコードポイントとして予約されていたりするあたりがややこしいと思う。 歴史的経緯...。

参考文献

ソフトウェア開発をするうえで最低限身につけておかなければならない文字エンコーディングに関する知識は次の書籍を読めば身につくと思う。 文字エンコーディング周りについて不安がある人は読むといい。

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)