diff --git a/string.c b/string.c index c140148..3253e9c 100644 --- a/string.c +++ b/string.c @@ -3206,15 +3206,20 @@ static VALUE str_casecmp_p(VALUE str1, VALUE str2); * "abcdef".casecmp("ABCDEF") #=> 0 * * +nil+ is returned if the two strings have incompatible encodings. + * or if +other_str+ is not a string and does not respond to +to_str+. * * "\u{e4 f6 fc}".encode("ISO-8859-1").casecmp("\u{c4 d6 dc}") #=> nil + * "abcdef".casecmp(1) #=> nil */ static VALUE rb_str_casecmp(VALUE str1, VALUE str2) { - StringValue(str2); - return str_casecmp(str1, str2); + VALUE s = rb_check_string_type(str2); + if (NIL_P(s)) { + return Qnil; + } + return str_casecmp(str1, s); } static VALUE @@ -3224,6 +3229,10 @@ str_casecmp(VALUE str1, VALUE str2) rb_encoding *enc; char *p1, *p1end, *p2, *p2end; + if (!rb_obj_is_kind_of(str2, rb_cString)) { + return Qnil; + } + enc = rb_enc_compatible(str1, str2); if (!enc) { return Qnil; @@ -3288,15 +3297,21 @@ str_casecmp(VALUE str1, VALUE str2) * "\u{e4 f6 fc}".casecmp?("\u{c4 d6 dc}") #=> true * * +nil+ is returned if the two strings have incompatible encodings. + * or if +other_str+ is not a string and does not respond to +to_str+. * * "\u{e4 f6 fc}".encode("ISO-8859-1").casecmp?("\u{c4 d6 dc}") #=> nil + * "abcdef".casecmp?(1) #=> nil */ static VALUE + rb_str_casecmp_p(VALUE str1, VALUE str2) { - StringValue(str2); - return str_casecmp_p(str1, str2); + VALUE s = rb_check_string_type(str2); + if (NIL_P(s)) { + return Qnil; + } + return str_casecmp_p(str1, s); } static VALUE diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 7dbf27e..3b72d25 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -2318,6 +2318,12 @@ def test_compare_different_encoding_string def test_casecmp assert_equal(1, "\u3042B".casecmp("\u3042a")) + assert_nil("Foo".casecmp(:Foo)) + assert_nil("1".casecmp(1)) + + o = Object.new + def o.to_str; "abcde"; end + assert_equal(1, "abcdef".casecmp(o)) end def test_casecmp? @@ -2325,6 +2331,12 @@ def test_casecmp? assert_equal(false, 'FoO'.casecmp?('BaR')) assert_equal(false, 'baR'.casecmp?('FoO')) assert_equal(true, 'äöü'.casecmp?('ÄÖÜ')) + assert_nil("Foo".casecmp?(:Foo)) + assert_nil("1".casecmp?(1)) + + o = Object.new + def o.to_str; "foo"; end + assert_equal(true, "Foo".casecmp?(o)) end def test_upcase2