トップ «前の日記(2001-11-09) 最新 次の日記(2001-11-11)» 月表示 編集

日々の流転


2001-11-10 [長年日記]

λ. 部品単位のコードから文字単位のコードへのiconv

ruby_m17nからはじまってこんな事を書いて、自分でも「ホントか?」とか思ったのでちょっと考えてみた。

λ. 結論から書くと、「結合できない部品が現れるまで最後の文字を確定できない」事の帰結として、変換を終了する際のiconv_closeを呼ぶ前に、iconvをinbufをNULLにして呼び出して、状態を初期状態に戻す必要がある(はず)。

λ. 簡単な場合で考えよう。出力エンコーディングの「文字」は、入力エンコーディングではベースの部品に0個以上の結合部品を連結して表されるとする。そして、ベースの部品はアルファベットで、結合用の部品は記号で表す事にする。

で、iconvが「A ^ : B」という列を受け取ったとする。Bまで読んだ時点で結合できない部品に出会ったので、「A ^ :」で出力エンコーディングの「1文字」が決定できて「:」まで変換出来る。が、その後どうなるかが問題。バッファの中には存在しないけど、実際の「B」の後には結合部品が続いて入力されるかもしれないので、この時点で「B」を変換してしまうことは出来ないのね。では、どうするか… Bは単独でも正しい文字なのでEINVALを返すのは変だし、そもそもEINVALで突っ返したりすると、「B」の直後で変換が終了する場合に、どうやっても「B」を出力エンコーディングの1文字に変換できない。だから「B」を受理してiconv_tの「状態」を遷移すべき。(幸いにしてiconv_tは明示的に初期化/破棄されるので、ポインタを含む任意の情報を持たせることが出来る) そして、iconvがinbufをNULLにして呼ばれて、状態を初期状態に戻す際に、やっと「B」を1文字と確定できて出力できる。

λ. このinbufをNULLにしてのiconvの呼び出しって、glibcのinfoにもnecessaryと書かれているし、もともと必須なものだと思うけど、これってつい忘れがち…、っていうより実際忘れているソースの方が多く出回っていそうな気がする。I18Nハンドブックの例もこれをしてないし。

あ、I18Nハンドブックってのは「国際化プログラミング - I18N ハンドブック」(ISBN4-320-02904-6 通称「いっちまっえーん」)の事ね。

本日のツッコミ(全3件) [ツッコミを入れる]
ψ なかだ (2001-11-12 12:35)

inbufをNULLにしての呼び出しがバグってるiconvなんかもあったりしますが。

ψ さかい (2001-11-13 00:29)

そういえばmgeditというエディタのソースでは、inbufをNULLにしての呼び出しの部分に「Write the reset sequence. We don't realloc 'to' here in order not to hit a bug(?) in glibc-2.1.」と書かれてましたが、これかな…

ψ なかだ (2001-11-13 14:12)

同じくglibc-2.1で、outlenとかoutbufにでたらめな値を返すので長さ<br>が分からないというバグだったので、たぶんdon't realloc 'to'という<br>のはそれのような気がします。でもreallocしないだけでいいのかな…。<br><br>ruby/iconvではNULLを指定する前に一度空文字列を変換するという方法<br>で回避してますが、今確かめたら2.2.2では直ってるようです。