2008年10月07日

UTF-8のデコード

 先日 UTF-8 のデコード処理を組み込む用事がありました。
 デコードの方法というか、定義自体は知っていたので、特に問題なく組み込めました。

 で、正しく認識しておこうと思い、資料を幾つか見てみるとイマイチ分かりにくい。
 それが個人的にちょっと気になったので、息抜きがてら少しまとめてみようと思います。


 UTF-8 の場合、ASCII 範囲の場合は 1 バイトで、それ以外は 2~6 バイトにエンコードされています。
 とはいえ、5~6 バイトは現時点では不正なコードと扱っても問題ないとされていますので、バッファオーバーフローさえしない作りにしておけば、とりあえずは問題ないでしょう。

 で、1バイトの場合はそのまま下位 7 ビットに当て嵌めれば問題ないのですが、少し面倒なのが 2~4 バイトの時。
 でもビットストリームを図解すると結構簡単です。

 ★1バイトの場合
  0aaa-aaaa

 ★2バイトの場合
  110a-aaaa 10bb-bbbb

 ★3バイトの場合
  1110-aaaa 10bb-bbbb 10cc-cccc

 ★4バイトの場合
  1111-0aaa 10bb-bbbb 10cc-cccc 10dd-dddd

 ★5バイトの場合
  1111-10aa 10bb-bbbb 10cc-cccc 10dd-dddd 10ee-eeee

 ★6バイトの場合
  1111-110a 10bb-bbbb 10cc-cccc 10dd-dddd 10ee-eeee 10ff-ffff

 0 と 1 はそのままの値が入って、バイト長の判定に使います。
 abcdef は、例えば a であれば、その文字の 1 バイト目でデータとして扱う部分。
 b であれば 2 バイト目の、c であれば 3 バイト目の……といった具合です。


 上のだとちょっと分かりにくいのですが、実際にデコードされたデータを並べると、以下のような感じ。

 ★1バイトの場合
  0000-0000 0000-0000 0aaa-aaaa (0x00007f ~ 0x000000)

 ★2バイトの場合
  0000-0000 0000-0aaa aabb-bbbb (0x0007ff ~ 0x000080)

 ★3バイトの場合
  0000-0000 aaaa-bbbb bbcc-cccc (0x00ffff ~ 0x000800)

 ★4バイトの場合
  000a-aabb bbbb-cccc ccdd-dddd (0x1fffff ~ 0x010000)

 1 バイト目だけが特殊で、2 バイト目以降は下位 6 ビットを引っ張ってきているだけです。

 ちなみに、4 バイトの場合だと、既に Unicode の範囲外のところまで表現できています。
 逆を返すとここまでで現時点で Unicode で定義されている内容を全て表現出来るということです。
 その為、5 バイト以上のものについては、不正なコードとして扱えるわけです。


同じカテゴリー(プログラム)の記事
 Navigate2を使ってPOSTで送信してみる (2008-02-15 10:05)