From: "NARUSE, Yui" Date: 2008-01-22T04:59:27+09:00 Subject: [ruby-dev:33268] Re: default encoding for Marshal.load 成瀬です。 Tietew wrote: >> アプリケーションがloadしたデータ中の文字列をたどってforce_encoding >> するくらいが妥当ですかねえ。 > > ある程度複雑なオブジェクトの中に文字列が保存されている場合、それをくまな > く辿って force_encoding するのは骨が折れるし間違いも起こりやすいのではな > いでしょうか。 > > そうでなくても、「文字列と nil が混じっている配列」のような単純な構造で > も、似て非なるコードを書き散らさなくてはならなくなりそうです。 Marlshal.recursive_force_encoding とかいう「データ中の文字列をたどって force_encoding する」メソッドがあったら楽だろうと思ったんですが、すごい 面倒そうだったので [ruby-dev:33205] の「dumpの入力データのエンコーディン グにする」を書いてみました。 Index: marshal.c =================================================================== --- marshal.c (revision 15163) +++ marshal.c (working copy) @@ -882,6 +882,7 @@ struct load_arg { int taint; st_table *compat_tbl; VALUE compat_tbl_wrapper; + rb_encoding *enc; }; static VALUE r_entry(VALUE v, struct load_arg *arg); @@ -968,7 +969,7 @@ r_bytes0(long len, struct load_arg *arg) if (len == 0) return rb_str_new(0, 0); if (TYPE(arg->src) == T_STRING) { if (RSTRING_LEN(arg->src) - arg->offset >= len) { - str = rb_str_new(RSTRING_PTR(arg->src)+arg->offset, len); + str = rb_enc_str_new(RSTRING_PTR(arg->src)+arg->offset, len, arg->enc); arg->offset += len; } else { @@ -1569,6 +1570,7 @@ marshal_load(int argc, VALUE *argv) arg.offset = 0; arg.compat_tbl = st_init_numtable(); arg.compat_tbl_wrapper = Data_Wrap_Struct(rb_cData, rb_mark_tbl, 0, arg.compat_tbl); + arg.enc = rb_enc_get(arg.src); major = r_byte(&arg); minor = r_byte(&arg); この arg.enc に encoding をつっこむ方法が何かあれば明示的に指定できるの ですが、まぁ、これで事実上問題ないのではないでしょうか。 -- NARUSE, Yui DBDB A476 FDBD 9450 02CD 0EFC BCE3 C388 472E C1EA