String Encodingぅ

Ada2012ではUTFの変換ライブラリが用意されます。

http://www.ada-auth.org/standards/12rm/html/RM-A-4-11.html

StringからUTF_8_Stringに変換(同じ型ですが)するEncode関数が用意されていることで、文字コードの違いが明確になっています。Stringには現在のロケール、Wide_Stringには現在のロケールの文字をpacked形式で、UTF_8_StringにはUTF-8、UTF_16_Wide_StringにはUTF-16、といった使い分けがなされることになるのでしょう。それとは別にUTF_Stringとして、Stringにバイナリ列を詰め込んだものを処理できるようにもなっています。

GNAT GPLの実装を見たらなんかStringにはUTF-32の0からFFまでが入るような感じで激しく不安に駆られるのですが、文字コードについてAdaCoreに期待してはいけないというのは私の中で了解事項ですので気にしないことにします。

しかし、それを差し引いても、よく見てみるとこのライブラリはいろいろ足りないような……。

まずUTF-32のBOMがありません、というかUnicodeを扱う上で一番扱いやすい形式のはずのUTF-32がすっぽり抜け落ちています。このライブラリを実装するにも、UTF-8と16の間の変換で一時的にでもUTF-32にするはずなのに。まあ、変換は一文字単位で行われるはずでしょうけれど……。

……そう、一番大きな点として、一文字単位で処理をするための関数がこのライブラリには一切ありません。実装上必要なはずなのにユーザーに解放されていません。全データをひとつのStringに入れて、全部スタック*1の上で処理しろとおっしゃいますか。
例えばストリームから読み出したデータを順次変換するような処理を考えた場合、最低でもmblen相当は必要になると思うんですよ。まあUTF-8/16の一文字分を切りだしてくる処理なんてすげー簡単ですが、ライブラリにあるに越したことはないと思うんですよ。それ以外にも、文字列の一部だけを処理するための関数があると便利と思うんですよ。Ada.Text_IO.Get_Lineみたいなプロトタイプで。

-- 一文字だけ変換
procedure Encode (
   Source : in String;
   Next : out Positive; -- Source中の次の文字のインデックス
   Result : out String;
   Last : out Natural); -- 変換後の文字がResultに格納された終端

これですとスタックも使いませんしね。
こういった明らかに必要な関数が足りてないのに、滅多に使わないであろうBOM周りだけ(UTF-32抜きで)執拗にサポートされてるものですから、溜息が……。
こうして、Adaにまたひとつ使えない標準ライブラリが増えたのでした。いや、単純な用途には使えますけどね……。

……いやいや、Ada2012まであと2年ある!きっと、きっと……!!

追記

http://www.adaic.com/standards/05rm/html/RM-3-5-2.html

CharacterがBMPの最初の256文字(Latin-1相当)というのは決まってるのか……orz
しかしまあStringにLatin-1しか入れられないとすると多くのパッケージでファイル名にLatin-1しか使えないことになってしまいますし、事実GNATのライブラリがIO周りでは素通し(or統一感のない迷惑な変換)で全然Latin-1として動作してないというのもありますし、a-chlat9.adsを見るに、本当にCharacterをBMPの最初の256文字にしようとしているなら「Summary of Changes from Latin-1 => Latin-9」なんて変更があるわけ無いし(Latin-9で164に割り当てられているEuro-SignUnicodeですとU+20ACですので)、混乱状態なのは確かです。
StringはUTF-8固定、Wide_StringはUTF-16固定、Wide_Wide_StringはUTF-32固定が一番嬉しいんですけどねえ……。

*1:AdaのStringはスタックに確保されます。GNATの場合関数の返値のみセカンダリスタック(実体はmallocされたメモリ)なので実は気にしなくていいのかもしれません。