From: Nobuyoshi Nakada Date: 2007-12-28T18:21:31+09:00 Subject: [ruby-dev:32863] Re: Window でのデフォルトエンコーディング なかだです。 At Fri, 28 Dec 2007 15:09:28 +0900, NARUSE, Yui wrote in [ruby-dev:32855]: > > 多分 alias でいいと思います。でもそれも日本に限ります。 > > 現在 encoding として iso-8859-X をサポートしていますが、 > > これは windows 上で使われている windows-125x と違います。 > > 単に alias にしてしまうと大文字小文字を始め期待外れの > > 結果になる可能性が多いです。 > > 日本でも Shift_JIS と CP932 は別物なので alias じゃまずいですよ。 > 日本の混乱具合については英語ですと XML 日本語プロファイルがまとまってい > ます。これを参考に変換テーブルを作っても役には立たないあたりがまた混乱し > ているのですが・・・。 aliasではなくてreplicaにしてはどうかと思います。ただし、これはこ れで比較などの問題があるので、base encodingをたどって比較可能な encodingを探して、それのstrcmpメソッドに投げるというのを考えてみ ました。 Index: include/ruby/encoding.h =================================================================== --- include/ruby/encoding.h (revision 14758) +++ include/ruby/encoding.h (working copy) @@ -115,4 +115,6 @@ int rb_enc_casefold(char *to, const char int rb_enc_toupper(int c, rb_encoding *enc); int rb_enc_tolower(int c, rb_encoding *enc); +VALUE rb_enc_base_encoding(VALUE encoding); +rb_encoding *rb_enc_originally_compatible(rb_encoding *, rb_encoding *); ID rb_intern3(const char*, long, rb_encoding*); ID rb_interned_id_p(const char *, long, rb_encoding *); Index: include/ruby/intern.h =================================================================== --- include/ruby/intern.h (revision 14758) +++ include/ruby/intern.h (working copy) @@ -523,5 +523,5 @@ VALUE rb_str_concat(VALUE, VALUE); int rb_memhash(const void *ptr, long len); int rb_str_hash(VALUE); -int rb_str_comparable(VALUE, VALUE); +VALUE rb_str_comparable(VALUE, VALUE); int rb_str_cmp(VALUE, VALUE); VALUE rb_str_equal(VALUE str1, VALUE str2); Index: encoding.c =================================================================== --- encoding.c (revision 14758) +++ encoding.c (working copy) @@ -551,5 +551,7 @@ rb_enc_compatible(VALUE str1, VALUE str2 return enc; } - return 0; + + return rb_enc_originally_compatible(rb_enc_from_index(idx1), + rb_enc_from_index(idx2)); } @@ -729,10 +731,39 @@ enc_name(VALUE self) } -static VALUE -enc_base_encoding(VALUE self) +/* + * call-seq: + * enc.base_encoding => encoding + * + * Returns the base encoding of the encoding. + * + * Encoding::CP932.base_encoding => Encoding::Shift_JIS + */ +VALUE +rb_enc_base_encoding(VALUE self) { return rb_attr_get(self, id_base_encoding); } +static rb_encoding * +original_encoding(rb_encoding *enc) +{ + VALUE e = rb_enc_from_encoding(enc), t; + while (!ENC_DUMMY_P(e) && !NIL_P(t = rb_enc_base_encoding(e))) { + e = t; + } + return rb_to_encoding(e); +} + +rb_encoding * +rb_enc_originally_compatible(rb_encoding *enc1, rb_encoding *enc2) +{ + rb_encoding *oenc1 = original_encoding(enc1); + rb_encoding *oenc2 = original_encoding(enc2); + if (oenc1 == oenc2) { + return (enc1 == oenc1) ? enc2 : enc1; + } + return 0; +} + /* * call-seq: @@ -821,4 +852,21 @@ enc_compatible_p(VALUE klass, VALUE str1 } +/* + * call-seq: + * Encoding.strcmp(str1, str2) => -1, 0 or +1 + * + * Compares two strings in the encoding specific way. + */ +static VALUE +enc_strcmp(VALUE klass, VALUE str1, VALUE str2) +{ + int result; + + StringValue(str1); + StringValue(str2); + result = rb_str_cmp(str1, str2); + return INT2FIX(result); +} + /* :nodoc: */ static VALUE @@ -981,6 +1029,7 @@ Init_Encoding(void) rb_define_method(rb_cEncoding, "inspect", enc_inspect, 0); rb_define_method(rb_cEncoding, "name", enc_name, 0); - rb_define_method(rb_cEncoding, "base_encoding", enc_base_encoding, 0); + rb_define_method(rb_cEncoding, "base_encoding", rb_enc_base_encoding, 0); rb_define_method(rb_cEncoding, "dummy?", enc_dummy_p, 0); + rb_define_method(rb_cEncoding, "strcmp", enc_strcmp, 2); rb_define_singleton_method(rb_cEncoding, "list", enc_list, 0); rb_define_singleton_method(rb_cEncoding, "find", enc_find, 1); @@ -993,4 +1042,6 @@ Init_Encoding(void) rb_define_singleton_method(rb_cEncoding, "locale_charmap", rb_locale_charmap, 0); + rb_enc_replicate("CP932", rb_enc_from_index(ENCINDEX_SJIS)); + /* dummy for unsupported, statefull encoding */ rb_define_dummy_encoding("ISO-2022-JP"); Index: string.c =================================================================== --- string.c (revision 14758) +++ string.c (working copy) @@ -418,5 +418,5 @@ rb_str_shared_replace(VALUE str, VALUE s } -static ID id_to_s; +static ID id_to_s, id_strcmp; VALUE @@ -1262,5 +1262,5 @@ rb_str_hash_m(VALUE str) #define lesser(a,b) (((a)>(b))?(b):(a)) -int +VALUE rb_str_comparable(VALUE str1, VALUE str2) { @@ -1268,4 +1268,5 @@ rb_str_comparable(VALUE str1, VALUE str2 int idx2 = rb_enc_get_index(str2); int rc1, rc2; + rb_encoding *enc1 = 0, *enc2 = 0; if (idx1 == idx2) return Qtrue; @@ -1274,11 +1275,17 @@ rb_str_comparable(VALUE str1, VALUE str2 if (rc1 == ENC_CODERANGE_7BIT) { if (rc2 == ENC_CODERANGE_7BIT) return Qtrue; - if (rb_enc_asciicompat(rb_enc_from_index(idx1))) + enc1 = rb_enc_from_index(idx1); + if (rb_enc_asciicompat(enc1)) return Qtrue; } if (rc2 == ENC_CODERANGE_7BIT) { - if (rb_enc_asciicompat(rb_enc_from_index(idx2))) + enc2 = rb_enc_from_index(idx2); + if (rb_enc_asciicompat(enc2)) return Qtrue; } + if (!enc1) enc1 = rb_enc_from_index(idx1); + if (!enc2) enc2 = rb_enc_from_index(idx2); + enc1 = rb_enc_originally_compatible(enc1, enc2); + if (enc1) return rb_enc_from_encoding(enc1); return Qfalse; } @@ -1323,4 +1330,6 @@ VALUE rb_str_equal(VALUE str1, VALUE str2) { + VALUE enc; + if (str1 == str2) return Qtrue; if (TYPE(str2) != T_STRING) { @@ -1330,8 +1339,18 @@ rb_str_equal(VALUE str1, VALUE str2) return rb_equal(str2, str1); } - if (!rb_str_comparable(str1, str2)) return Qfalse; - if (RSTRING_LEN(str1) == RSTRING_LEN(str2) && - rb_str_cmp(str1, str2) == 0) { - return Qtrue; + switch (enc = rb_str_comparable(str1, str2)) { + case Qfalse: + return Qfalse; + case Qtrue: + if (RSTRING_LEN(str1) == RSTRING_LEN(str2) && + rb_str_cmp(str1, str2) == 0) { + return Qtrue; + } + break; + default: + if (rb_funcall(enc, id_strcmp, 2, str1, str2) == INT2FIX(0)) { + return Qtrue; + } + break; } return Qfalse; @@ -5804,4 +5823,5 @@ Init_String(void) id_to_s = rb_intern("to_s"); + id_strcmp = rb_intern("strcmp"); rb_fs = Qnil; -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦