2012-04-05

iconvがクソすぎる

思うに、私が最初のOSに不自由なWindowsを選んだのは正解だったかもしれない。すくなくとも、Win32 APIはPOSIXよりはるかに使いやすい。

問題はiconvだ。一体どこの糞が何をキメながら設計したらこうなったんだ。狂っているにも程がある。

size_t iconv (iconv_t cd,
              const char ** inbuf, size_t * inbytesleft,
              char ** outbuf, size_t * outbytesleft) ;

ポインターのポインターであるには理由がある。iconvは、すべて書き換えるからだ。ポインターを書き換えるのでポインターへのポインターを要求する。当然だ。当然であって欲しくないが当然だ。

なんでそんなに馬鹿げた副作用を持ち込むんだ。それでは必ずlvalueを渡さなければならないし、大抵の場合、もとの値を保持しておきたいから、オブジェクトのコピーを作って渡さなければならない。

簡単なラップを書けば、それ以降この異常な副作用に悩まされることはない。しかし、なぜ設計がこうなっているんだ。もちろん、今の私はポインター演算ぐらい完全に理解しているが、だからといって直接使いたいとは思わない。

Win32 APIは少なくとも、そんな馬鹿げた副作用を持ち込むことはなかったし、読むオブジェクトと書くオブジェクトは明確に分けている。たとえば、Win32 APIの流儀に従うと、inbytesleftやoutbytesleftは、それぞれconst size_tとsize_t *の2つの引数に分割し、読み込みと書き込みを分離する。

私がCを学んでいたとき、Cの標準ライブラリがあまりにも使いづらかったので、すぐにWin32 APIに移行した。また、C言語自体が気に食わなかったので、すぐにC++に移行した。思うに、これは正解だった。おかげで私は、POSIXの汚い設計に苦しめられることはなかった。

ちなみに、今のUbuntuのiconvパッチを当てたunzipにはバグがある。シフトJISやCP932でエンコードされた半角カナが多い文字列をUTF-8に変換することができない。なぜならば、バッファの確保が単に元の文字列のオクテット数の二倍になっているだけだからだ。半角カナは、UTF-8でエンコードすると3オクテット必要である。

どうも、unzipは変換元文字列の6倍のバッファを確保しているらしい。Twitter / @mattn_jp: んーunzipで領域2倍しか取ってないっての話、ちゃ ...

しかし、現在のUbuntu 11.10や12.04のレポジトリのソースコードのパッチを読むと、

Ubuntu -- Details of package unzip in precise

やはり2倍の確保になっている。

1 comment:

Anonymous said...

unzip の Invalid or incomplete multibyte or wide character からここにたどり着きました。何とか、正常に修正されますように。