UTF-9
2005年にUTF-9という規格ができていました。知らなかった。
http://www.ietf.org/rfc/rfc4042.txt
http://nikki.hio.jp/files/2005/rfc4042.txt
UTF-8ではCJK文字が8*3ビットになってしまうのですが、UTF-9ですと2*9ビットに収まってしまうスグレモノ。
ただしこれを扱うには9ビット単位の操作が必要。12ビットマシンならともかく、1バイト8ビットのCPUの上で、16ビットを単位とするのは効率が悪すぎます。
ここは間違いなく、(最近D言語がbit型を放棄したので)恐らく世界で唯一*1、ビット単位で自在に変数を確保できる言語であるAdaの出番でしょう、というわけで、RFC中のサンプルの変換コードを移植してみました。
package UTF9 is type UTF9_Character is new Wide_Wide_Character range Wide_Wide_Character'Val (0) .. Wide_Wide_Character'Val (8#777#); for UTF9_Character'Size use 9; type UTF9_String is array (Positive range <>) of UTF9_Character; for UTF9_String'Component_Size use 9; function UTF9_to_UCS4 (Single_Character : UTF9_String) return Wide_Wide_Character; function UCS4_to_UTF9 (Single_Character : Wide_Wide_Character) return UTF9_String; end UTF9;
with Interfaces; use Interfaces; package body UTF9 is function UTF9_to_UCS4 (Single_Character : UTF9_String) return Wide_Wide_Character is I : Natural := Single_Character'First; nonet : Unsigned_32 := UTF9_Character'Pos (Single_Character (I)); ucs4 : Unsigned_32 := nonet and 8#377#; begin while (nonet and 8#400#) /= 0 loop I := I + 1; nonet := UTF9_Character'Pos (Single_Character (I)); ucs4 := Shift_Left (ucs4, 8) or (nonet and 8#377#); end loop; return Wide_Wide_Character'Val (ucs4); end UTF9_to_UCS4; function UCS4_to_UTF9 (Single_Character : Wide_Wide_Character) return UTF9_String is ucs4 : Unsigned_32 := Wide_Wide_Character'Pos (Single_Character); Result : UTF9_String (1 .. 4); I : Natural := 1; begin if ucs4 > 8#400# then if ucs4 > 8#200000# then if ucs4 > 8#100000000# then Result (I) := UTF9_Character'Val (8#400# or (Shift_Right (ucs4, 24) and 8#377#)); I := I + 1; end if; Result (I) := UTF9_Character'Val (8#400# or (Shift_Right (ucs4, 16) and 8#377#)); I := I + 1; end if; Result (I) := UTF9_Character'Val (8#400# or (Shift_Right (ucs4, 8) and 8#377#)); I := I + 1; end if; Result (I) := UTF9_Character'Val (ucs4 and 8#377#); return Result (1 .. I); end UCS4_to_UTF9; end UTF9;
テスト。
with Ada.Text_IO; use Ada.Text_IO; with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; with UTF9; use UTF9; procedure Test is -- GOTHIC LETTER AHSA subtype UTF9_3 is UTF9_String (1 .. 3); S : UTF9_3 := UCS4_to_UTF9 (Wide_Wide_Character'Val (16#10330#)); begin for I in S'Range loop Put (UTF9_Character'Pos (S (I)), Base => 8); end loop; New_Line; Put (UTF9_3'Size); New_Line; end Test;
...>test 8#401# 8#403# 8#60# -- RFCに例示された結果と一致 27 -- 3文字で27ビット占有
うむ、完璧。まさか8進数なんてものを使うようになる日が来るとは思いませんでした。
このように、Adaでは9ビット単位の配列をも扱えます。もしUTF-9が一般の文字コードとして使われるようになったら、1バイトが8ビットの環境では、ありとあらゆる文字列処理において、他の言語との効率及び扱いやすさにおける格差は明白となるでしょう。さぁ、いずれ来るUTF-9普及に向けて、皆さんAdaを使おうではありませんか。
ちなみに規格の日付は見てはいけないらしいです。
*1:適当言ってます。同じことができる無名の言語がいくらでもありそうな。