From: Fujioka Date: 2009-07-30T12:31:48+09:00 Subject: [ruby-dev:38957] Re: String#valid_encoding?にオプションが欲しい xibbarこと藤岡です。 >> force_encodingにかんしては破壊的なイメージがあるんですよねえ。 >> 勝手な思いこみか、forceという単語の持つ印象か。 >> >> |あとはpresume_encoding!とかありますけれども……。 >> >> presume_encodingも用意するのであれば。 >> > ということは、 > presume_encoding(encoding) > presume_encoding!(encoding) > の2つを新設すると折り合いがつくということでしょうか? > 実装してみました。 irb(main):001:0> str="あ".force_encoding("EUC-JP") => "\xE3\x81\x82" irb(main):004:0> str.presume_encoding("EUC-JP") => nil irb(main):005:0> str.presume_encoding("UTF-8") => "あ" irb(main):007:0> str => "\xE3\x81\x82" irb(main):008:0> str.presume_encoding!("UTF-8") => "あ" irb(main):009:0> str => "あ" irb(main):010:0> str="あ".force_encoding("EUC-JP") => "\xE3\x81\x82" irb(main):011:0> str.presume_encoding!("SHIFT_JIS") => nil irb(main):012:0> str => "\xE3\x81\x82" irb(main):013:0> str.presume_encoding!("EUC-JP") => nil irb(main):014:0> str => "\xE3\x81\x82" 以下パッチ。 Index: string.c =================================================================== --- string.c (revision 24163) +++ string.c (working copy) @@ -7090,6 +7090,51 @@ /* * call-seq: + * str.presume_encoding(encoding) => new_str or nil + * + * If a string can be encoded correctly in the given encoding, + * returns a copy of str with changing the encoding to +encoding+ ; + * otherwise, returns nil. + */ + +static VALUE +rb_str_presume_encoding(VALUE str, VALUE encoding) +{ + rb_encoding *enc = rb_to_encoding(encoding); + int cr = coderange_scan(RSTRING_PTR(str), RSTRING_LEN(str), enc); + + if (cr != ENC_CODERANGE_BROKEN) { + return rb_enc_str_new(RSTRING_PTR(str),strlen(RSTRING_PTR(str)),enc); + } else { + return Qnil; + } +} + +/* + * call-seq: + * str.presume_encoding_bang(encoding) => str or nil + * + * If a string can be encoded correctly in the given encoding, + * changes the encoding to +encoding+ and returns self; + * otherwise, returns nil. + */ + +static VALUE +rb_str_presume_encoding_bang(VALUE str, VALUE encoding) +{ + rb_encoding *enc = rb_to_encoding(encoding); + int cr = coderange_scan(RSTRING_PTR(str), RSTRING_LEN(str), enc); + + if (cr != ENC_CODERANGE_BROKEN) { + ENCODING_CODERANGE_SET(str, rb_enc_to_index(enc), cr); + return str; + } else { + return Qnil; + } +} + +/* + * call-seq: * str.ascii_only? => true or false * * Returns true for a string which has only ASCII characters. @@ -7531,6 +7576,8 @@ rb_define_method(rb_cString, "encoding", rb_obj_encoding, 0); /* in encoding.c */ rb_define_method(rb_cString, "force_encoding", rb_str_force_encoding, 1); rb_define_method(rb_cString, "valid_encoding?", rb_str_valid_encoding_p, 0); + rb_define_method(rb_cString, "presume_encoding", rb_str_presume_encoding, 1); + rb_define_method(rb_cString, "presume_encoding!", rb_str_presume_encoding_bang, 1); rb_define_method(rb_cString, "ascii_only?", rb_str_is_ascii_only_p, 0); id_to_s = rb_intern("to_s");