RubyCocoa 今週のコミット 2014-06-13 文字列のエンコーディング
Ruby 1.8と1.9以降のちがいについては、るびま25号の"Rubyist Magazine - Ruby M17N の設計と実装"に詳しい。すげー雑に書くと、
という感じ。CocoaのNSStringは後者と同様にエンコーディングを持ってる。
なので、RubyとObjective-Cで文字列オブジェクトを変換するときには、それぞれのエンコーディングに読み替えて処理するようにしてやればよい。中間データとしては例によって(char *)になる。
RubyのエンコーディングはEncodingクラスおよびそのインスタンスで表現され(内部的にはrb_encoding*とindexも使える)、NSStringではNSStringEncoding(CoreFoundationではCFStringEncoding)を使う。
それぞれ文字列の生成や、バイト列を取るときにエンコーディングを指定できるので、プログラム的には問題なさそう。
実装に当たって決めなきゃいけないことは、
- RubyとNSString(CFString)のエンコーディングの対応関係のリストアップ。
- RubyではCocoaならNSDataで扱うような文字でないデータもStringで扱うがそれをどうするか。
- 相互に変換できないエンコーディングがあったらどうするか。
あたり。
1つめは基本がんばるしかない。やってみないとわからないけど、IANA Character Setsの名前でマッチングさせて変換表を自動的に作れたりするとだいぶ楽になるかもしれない。
2つめはRubyではダミーエンコーディング、NSStringではCoreFoundationになるけどkCFStringEncodingInvalidIdとよくわからないデータで構成される文字列(?)を表現するエンコーディングがある(正しくはRubyのはそうではない)。Rubyにはバイナリとかバイト列用のダミーエンコーディングはあらかじめ定義はされていないので、rb_define_dummy_encoding()を使って自分で使うダミーエンコーディングを定義してやる必要がある。
3つめは次のどちらかかなあ。
今回の仮実装では前者とした。
で、これらをとりあえず実装してみたのがr2551になる。
恐ろしいことにこれでもけっこうちゃんと動いたりするわけだけど、もうちょっとマシにするためのタスクはこのくらい。
- 変換をswitch/ifでなく、対応関係を登録したst_tableを使うようにする。Rubyはindexを、CocoaはCFStringEncodingを登録するようにするつもり。
- ruby側からの変換表へのアクセス機能を提供。実行時に変換表を登録、削除、lookupできるように。
- ダミーエンコーディングの定義をRubyCocoa初期化のときに行うように。
- ダミーエンコーディングのStringをつくる関数を定義して、それを使うようにする。
だいぶゴールが近づいてきた感じがする。