From: "NARUSE, Yui" Date: 2009-02-16T04:15:26+09:00 Subject: [ruby-dev:38022] ENCODING_FIXED と ENCODING_NONE の廃止 成瀬です。 概要は先日まつもとさんに話しましたが、Regexp における特殊な ENCODING_FIXED と ENCODING_NONE の扱いは一部不要に感じます。 Ruby 1.9.1 には 1.8 同様、 正規表現リテラルに //s や //n といったオプションを指定できます。 ところが、この効果は、//s や //e、//u の場合は、 正規表現のエンコーディングを指定するだけでなく、 マッチ対象の文字列を指定したエンコーディングに「固定」します。 具体的には /aa/u =~ "aa".force_encoding("euc-jp") がマッチしなくなります。 しかし、この仕様は混乱を招くだけで不要ではないでしょうか。 非 ASCII 文字のチェック用として、正規表現内部の KCODE_FIXED は 残す必要があると思いますが、//s 等から指定できる仕様の削除を提案します。 また、//n は、 1. エンコーディングに ASCII-8BIT を指定 2. 正規表現リテラルに非 ASCII 文字を含むとエラー 3. /./n =~ "あ" 等で警告を表示 を行いますが、3. は不要ではないでしょうか。 Index: re.c =================================================================== --- re.c (revision 22332) +++ re.c (working copy) @@ -238,7 +238,6 @@ rb_memsearch(const void *x0, long m, const void *y } #define REG_LITERAL FL_USER5 -#define REG_ENCODING_NONE FL_USER6 #define KCODE_FIXED FL_USER4 @@ -302,7 +301,6 @@ rb_char_to_option_kcode(int c, int *option, int *k *kcode = -1; return (*option = char_to_option(c)); } - *option = ARG_ENCODING_FIXED; return 1; } @@ -1201,12 +1199,6 @@ rb_reg_prepare_enc(VALUE re, VALUE str, int warn) } enc = RREGEXP(re)->ptr->enc; } - if (warn && (RBASIC(re)->flags & REG_ENCODING_NONE) && - enc != rb_ascii8bit_encoding() && - rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) { - rb_warn("regexp match /.../n against to %s string", - rb_enc_name(enc)); - } return enc; } @@ -2329,8 +2321,7 @@ rb_reg_initialize(VALUE obj, const char *s, int le return -1; if (fixed_enc) { - if ((fixed_enc != enc && (options & ARG_ENCODING_FIXED)) || - (fixed_enc != a_enc && (options & ARG_ENCODING_NONE))) { + if (fixed_enc != enc && (options & ARG_ENCODING_FIXED)) { errcpy(err, "incompatible character encoding"); return -1; } @@ -2347,9 +2338,6 @@ rb_reg_initialize(VALUE obj, const char *s, int le if ((options & ARG_ENCODING_FIXED) || fixed_enc) { re->basic.flags |= KCODE_FIXED; } - if (options & ARG_ENCODING_NONE) { - re->basic.flags |= REG_ENCODING_NONE; - } re->ptr = make_regexp(RSTRING_PTR(unescaped), RSTRING_LEN(unescaped), enc, options & ARG_REG_OPTION_MASK, err); @@ -2946,7 +2934,6 @@ rb_reg_options(VALUE re) rb_reg_check(re); options = RREGEXP(re)->ptr->options & ARG_REG_OPTION_MASK; if (RBASIC(re)->flags & KCODE_FIXED) options |= ARG_ENCODING_FIXED; - if (RBASIC(re)->flags & REG_ENCODING_NONE) options |= ARG_ENCODING_NONE; return options; } Index: test/ruby/test_m17n.rb =================================================================== --- test/ruby/test_m17n.rb (revision 22332) +++ test/ruby/test_m17n.rb (working copy) @@ -349,24 +349,14 @@ class TestM17N < Test::Unit::TestCase def test_regexp_ascii_none r = /a/n - assert_warning(%r{regexp match /.../n against to}) { - assert_regexp_generic_ascii(r) - } - assert_equal(0, r =~ a("a")) assert_equal(0, r =~ e("a")) assert_equal(0, r =~ s("a")) assert_equal(0, r =~ u("a")) assert_equal(nil, r =~ a("\xc2\xa1")) - assert_warning(%r{regexp match /.../n against to EUC-JP string}) { - assert_equal(nil, r =~ e("\xc2\xa1")) - } - assert_warning(%r{regexp match /.../n against to Windows-31J string}) { - assert_equal(nil, r =~ s("\xc2\xa1")) - } - assert_warning(%r{regexp match /.../n against to UTF-8 string}) { - assert_equal(nil, r =~ u("\xc2\xa1")) - } + assert_equal(nil, r =~ e("\xc2\xa1")) + assert_equal(nil, r =~ s("\xc2\xa1")) + assert_equal(nil, r =~ u("\xc2\xa1")) assert_nothing_raised { eval(e("/\\x80/n")) } end @@ -392,7 +382,7 @@ class TestM17N < Test::Unit::TestCase end def test_regexp_euc - assert_regexp_fixed_eucjp(/a/e) + assert_regexp_generic_ascii(/a/e) assert_regexp_fixed_eucjp(/\xc2\xa1/e) assert_regexp_fixed_eucjp(eval(e(%{/\xc2\xa1/}))) assert_regexp_fixed_eucjp(eval(e(%q{/\xc2\xa1/}))) @@ -402,10 +392,10 @@ class TestM17N < Test::Unit::TestCase assert_equal(0, r =~ e("a")) assert_equal(0, r =~ s("a")) assert_equal(0, r =~ u("a")) - assert_raise(Encoding::CompatibilityError) { r =~ a("\xc2\xa1") } + assert_nothing_raised{ r =~ a("\xc2\xa1") } assert_equal(nil, r =~ e("\xc2\xa1")) - assert_raise(Encoding::CompatibilityError) { r =~ s("\xc2\xa1") } - assert_raise(Encoding::CompatibilityError) { r =~ u("\xc2\xa1") } + assert_nothing_raised{ r =~ s("\xc2\xa1") } + assert_nothing_raised{ r =~ u("\xc2\xa1") } } [/\xc2\xa1/e, eval(e(%{/\xc2\xa1/})), eval(e(%q{/\xc2\xa1/}))].each {|r| @@ -421,7 +411,7 @@ class TestM17N < Test::Unit::TestCase end def test_regexp_sjis - assert_regexp_fixed_sjis(/a/s) + assert_regexp_generic_ascii(/a/s) assert_regexp_fixed_sjis(/\xc2\xa1/s) assert_regexp_fixed_sjis(eval(s(%{/\xc2\xa1/}))) assert_regexp_fixed_sjis(eval(s(%q{/\xc2\xa1/}))) @@ -598,12 +588,10 @@ class TestM17N < Test::Unit::TestCase def test_union_1_regexp assert_regexp_generic_ascii(Regexp.union(//)) - assert_warning(%r{regexp match /.../n against to}) { - assert_regexp_generic_ascii(Regexp.union(//n)) - } - assert_regexp_fixed_eucjp(Regexp.union(//e)) - assert_regexp_fixed_sjis(Regexp.union(//s)) - assert_regexp_fixed_utf8(Regexp.union(//u)) + assert_regexp_generic_ascii(Regexp.union(//n)) + assert_regexp_generic_ascii(Regexp.union(//e)) + assert_regexp_generic_ascii(Regexp.union(//s)) + assert_regexp_generic_ascii(Regexp.union(//u)) end def test_union_2 @@ -641,16 +629,14 @@ class TestM17N < Test::Unit::TestCase end def test_dynamic_ascii_regexp - assert_warning(%r{regexp match /.../n against to}) { - assert_regexp_generic_ascii(/#{}/n) - } + assert_regexp_generic_ascii(/#{}/n) assert_regexp_fixed_ascii8bit(/#{}\xc2\xa1/n) assert_regexp_fixed_ascii8bit(/\xc2\xa1#{}/n) assert_nothing_raised { s1, s2 = a('\xc2'), a('\xa1'); /#{s1}#{s2}/ } end def test_dynamic_eucjp_regexp - assert_regexp_fixed_eucjp(/#{}/e) + assert_regexp_generic_ascii(/#{}/e) assert_regexp_fixed_eucjp(/#{}\xc2\xa1/e) assert_regexp_fixed_eucjp(/\xc2\xa1#{}/e) assert_raise(SyntaxError) { eval('/\xc2#{}/e') } @@ -660,7 +646,7 @@ class TestM17N < Test::Unit::TestCase end def test_dynamic_sjis_regexp - assert_regexp_fixed_sjis(/#{}/s) + assert_regexp_generic_ascii(/#{}/s) assert_regexp_fixed_sjis(/#{}\xc2\xa1/s) assert_regexp_fixed_sjis(/\xc2\xa1#{}/s) assert_raise(SyntaxError) { eval('/\x81#{}/s') } @@ -670,7 +656,7 @@ class TestM17N < Test::Unit::TestCase end def test_dynamic_utf8_regexp - assert_regexp_fixed_utf8(/#{}/u) + assert_regexp_generic_ascii(/#{}/u) assert_regexp_fixed_utf8(/#{}\xc2\xa1/u) assert_regexp_fixed_utf8(/\xc2\xa1#{}/u) assert_raise(SyntaxError) { eval('/\xc2#{}/u') } -- NARUSE, Yui