diff options
-rw-r--r-- | string.c | 54 | ||||
-rw-r--r-- | test/ruby/test_string.rb | 7 | ||||
-rw-r--r-- | test/ruby/test_symbol.rb | 8 |
3 files changed, 69 insertions, 0 deletions
@@ -3194,6 +3194,40 @@ rb_str_casecmp(VALUE str1, VALUE str2) return INT2FIX(-1); } +/* + * call-seq: + * str.casecmp?(other_str) -> true, false, or nil + * + * Returns true if str and other_other_str are equal after Unicode case folding, + * false if they are not equal, and nil if other_str is not a string. + * + * "abcdef".casecmp("abcde") #=> false + * "aBcDeF".casecmp("abcdef") #=> true + * "abcdef".casecmp("abcdefg") #=> false + * "abcdef".casecmp("ABCDEF") #=> true + */ + + +static VALUE rb_str_downcase(int argc, VALUE *argv, VALUE str); /* forward declaration */ +static VALUE +rb_str_casecmp_p(VALUE str1, VALUE str2) +{ + rb_encoding *enc; + VALUE folded_str1, folded_str2; + VALUE fold_opt = sym_fold; + + StringValue(str2); + enc = rb_enc_compatible(str1, str2); + if (!enc) { + return Qnil; + } + + folded_str1 = rb_str_downcase(1, &fold_opt, str1); + folded_str2 = rb_str_downcase(1, &fold_opt, str2); + + return rb_str_eql(folded_str1, folded_str2); +} + #define rb_str_index(str, sub, offset) rb_strseq_index(str, sub, offset, 0) static long @@ -9617,6 +9651,24 @@ sym_casecmp(VALUE sym, VALUE other) /* * call-seq: + * + * sym.casecmp?(other) -> true, false, or nil + * + * Returns true if sym and other are equal after Unicode case folding, + * false if they are not equal, and nil if other is not a symbol. + */ + +static VALUE +sym_casecmp_p(VALUE sym, VALUE other) +{ + if (!SYMBOL_P(other)) { + return Qnil; + } + return rb_str_casecmp_p(rb_sym2str(sym), rb_sym2str(other)); +} + +/* + * call-seq: * sym =~ obj -> integer or nil * * Returns <code>sym.to_s =~ obj</code>. @@ -9814,6 +9866,7 @@ Init_String(void) rb_define_method(rb_cString, "eql?", rb_str_eql, 1); rb_define_method(rb_cString, "hash", rb_str_hash_m, 0); rb_define_method(rb_cString, "casecmp", rb_str_casecmp, 1); + rb_define_method(rb_cString, "casecmp?", rb_str_casecmp_p, 1); rb_define_method(rb_cString, "+", rb_str_plus, 1); rb_define_method(rb_cString, "*", rb_str_times, 1); rb_define_method(rb_cString, "%", rb_str_format_m, 1); @@ -9963,6 +10016,7 @@ Init_String(void) rb_define_method(rb_cSymbol, "<=>", sym_cmp, 1); rb_define_method(rb_cSymbol, "casecmp", sym_casecmp, 1); + rb_define_method(rb_cSymbol, "casecmp?", sym_casecmp_p, 1); rb_define_method(rb_cSymbol, "=~", sym_match, 1); rb_define_method(rb_cSymbol, "[]", sym_aref, -1); diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index b1d795e183..90f48e4f08 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -2210,6 +2210,13 @@ CODE assert_equal(1, "\u3042B".casecmp("\u3042a")) end + def test_casecmp? + assert_equal(true, 'FoO'.casecmp?('fOO')) + assert_equal(false, 'FoO'.casecmp?('BaR')) + assert_equal(false, 'baR'.casecmp?('FoO')) + assert_equal(true, 'äöü'.casecmp?('ÄÖÜ')) + end + def test_upcase2 assert_equal("\u3042AB", "\u3042aB".upcase) end diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb index d8c91c1eea..24d319211f 100644 --- a/test/ruby/test_symbol.rb +++ b/test/ruby/test_symbol.rb @@ -276,6 +276,14 @@ class TestSymbol < Test::Unit::TestCase assert_nil(:foo.casecmp("foo")) end + def test_casecmp? + assert_equal(true, :FoO.casecmp?(:fOO)) + assert_equal(false, :FoO.casecmp?(:BaR)) + assert_equal(false, :baR.casecmp?(:FoO)) + assert_nil(:foo.casecmp?("foo")) + assert_equal(true, :äöü.casecmp?(:ÄÖÜ)) + end + def test_length assert_equal(3, :FoO.length) assert_equal(3, :FoO.size) |