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

日々の流転


2001-11-07 [長年日記]

λ. wstring

mbとwcの変換部分がイケてない気がする。

  • NULを含む文字列を正しく扱えない
  • こっちは微妙なんで後でちゃんと調べようと思うけど、結論から書くと、変換時にはterminating NULを含めて変換した上で、変換結果のterminating NULをRubyから隠すべきだと思う。どっちでも同じように思えるかもしれないけど、statefulなエンコーディングを扱う際に差が出る。たとえば、mbがISO-2022-JPだとすると「ほげほげ」という文字列は「ESC $ B 0x24 0x5b 0x24 0x32 0x24 0x5b 0x24 0x32 ESC ( B」で表され、Cで扱う際の対応関係は次のようになる。
    mbESC$B0x240x5b0x240x320x240x5b0x240x32ESC(BNUL
    wcNUL
    この場合のmbからwcへの変換では、terminating NULを含めずに変換しても実質的に問題ないが、wcからmbへの変換ではterminating NULを変換しないと「ESC ( B」が落ちてしまう。
Tags: ruby
本日のツッコミ(全4件) [ツッコミを入れる]
ψ 小澤 (2001-11-12 01:26)

前者は特に問題があるわけでもなさそうなので、このままで行きたいと思います。<br><br>後者は修正しましたが、問題なのは引数が少ないほうのmbs_to_wcsとwcs_to_mbsですよね?

ψ さかい (2001-11-12 02:18)

自分で話をruby-extに振っておいて、忙しくて反応できなくてすいませんでした。<br><br>で、この変換の件ですが、僕がmbstowcsとwcstombsの仕様を誤解していました。これまたすいません。<br># 知ったかぶりはするもんじゃないなぁ。<br><br>これらの関数はterminating NULを含めて変換した上で、出力した文字数/バイト数をterminating NULの分を除いて返すのですね。<br>ということは、これまでのコードで基本的にオッケーだったような・・・<br><br>これだけじゃアレなので、罪滅ぼしにTipsを一つ。<br>mbstate_tを初期化するポータブルな方法は確か<br>memset(&state, '\0', sizeof(state));<br>だったと思います。

ψ 小澤 (2001-11-12 13:06)

get_wcs_sizeとget_mbs_sizeはterminating NULを除いたサイズを返すので、mbs_to_wcsとwcs_to_mbsでは、terminating NULを除いて変換していました。mbs_to_wstringでは、'\0'を変換してもしなくても、c_str()で必ず最後にL'\0'が付いた状態で逆変換されるので、問題ないと思います。<br><br>P.J. Plauger率いるDinkumwareのリファレンスには<br>mbstate_t mbst = {0};<br>と書いてありますが…。<br>http://www.dinkumware.com/htm_cpl/wchar.html#mbstate_t<br><br>mbstate_tが構造体の場合でも足りないメンバは0に初期化され、PODの場合でも0に初期化されるので、問題ないと思います。

ψ さかい (2001-11-14 20:34)

なるほど。<br>確かにこれでも問題ないですね。<br><br># Cも以外と奥が深いんだなぁ<br># Opaqueなデータ構造をそういう方法で初期化するのって<br># 個人的には気持悪いですが…