Optimize str_casecmp length check using pointer end

This commit is contained in:
Erim Icel 2025-08-10 13:50:43 +01:00 committed by Nobuyoshi Nakada
parent df11c073f3
commit 5e324ac11c
3 changed files with 22 additions and 3 deletions

View file

@ -20,7 +20,9 @@ benchmark:
casecmp-10: lstr10.casecmp(ustr10) casecmp-10: lstr10.casecmp(ustr10)
casecmp-100: lstr100.casecmp(ustr100) casecmp-100: lstr100.casecmp(ustr100)
casecmp-1000: lstr1000.casecmp(ustr1000) casecmp-1000: lstr1000.casecmp(ustr1000)
casecmp-1000vs10: lstr1000.casecmp(ustr10)
casecmp-nonascii1: lnonascii1.casecmp(unonascii1) casecmp-nonascii1: lnonascii1.casecmp(unonascii1)
casecmp-nonascii10: lnonascii10.casecmp(unonascii10) casecmp-nonascii10: lnonascii10.casecmp(unonascii10)
casecmp-nonascii100: lnonascii100.casecmp(unonascii100) casecmp-nonascii100: lnonascii100.casecmp(unonascii100)
casecmp-nonascii1000: lnonascii1000.casecmp(unonascii1000) casecmp-nonascii1000: lnonascii1000.casecmp(unonascii1000)
casecmp-nonascii1000vs10: lnonascii1000.casecmp(unonascii10)

View file

@ -4381,9 +4381,9 @@ str_casecmp(VALUE str1, VALUE str2)
p2 += l2; p2 += l2;
} }
} }
if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) return INT2FIX(0); if (p1 == p1end && p2 == p2end) return INT2FIX(0);
if (RSTRING_LEN(str1) > RSTRING_LEN(str2)) return INT2FIX(1); if (p1 == p1end) return INT2FIX(-1);
return INT2FIX(-1); return INT2FIX(1);
} }
/* /*

View file

@ -2832,9 +2832,12 @@ CODE
def test_casecmp def test_casecmp
assert_equal(0, S("FoO").casecmp("fOO")) assert_equal(0, S("FoO").casecmp("fOO"))
assert_equal(1, S("FoO").casecmp("BaR")) assert_equal(1, S("FoO").casecmp("BaR"))
assert_equal(-1, S("foo").casecmp("FOOBAR"))
assert_equal(-1, S("baR").casecmp("FoO")) assert_equal(-1, S("baR").casecmp("FoO"))
assert_equal(1, S("\u3042B").casecmp("\u3042a")) assert_equal(1, S("\u3042B").casecmp("\u3042a"))
assert_equal(-1, S("foo").casecmp("foo\0")) assert_equal(-1, S("foo").casecmp("foo\0"))
assert_equal(1, S("FOOBAR").casecmp("foo"))
assert_equal(0, S("foo\0bar").casecmp("FOO\0BAR"))
assert_nil(S("foo").casecmp(:foo)) assert_nil(S("foo").casecmp(:foo))
assert_nil(S("foo").casecmp(Object.new)) assert_nil(S("foo").casecmp(Object.new))
@ -2842,6 +2845,16 @@ CODE
o = Object.new o = Object.new
def o.to_str; "fOO"; end def o.to_str; "fOO"; end
assert_equal(0, S("FoO").casecmp(o)) assert_equal(0, S("FoO").casecmp(o))
assert_equal(0, S("#" * 128 + "A" * 256 + "b").casecmp("#" * 128 + "a" * 256 + "B"))
assert_equal(0, S("a" * 256 + "B").casecmp("A" * 256 + "b"))
assert_equal(-1, S("@").casecmp("`"))
assert_equal(0, S("hello\u00E9X").casecmp("HELLO\u00E9x"))
s1 = S("\xff".force_encoding("UTF-8"))
s2 = S("\xff".force_encoding("ISO-2022-JP"))
assert_nil(s1.casecmp(s2))
end end
def test_casecmp? def test_casecmp?
@ -2857,6 +2870,10 @@ CODE
o = Object.new o = Object.new
def o.to_str; "fOO"; end def o.to_str; "fOO"; end
assert_equal(true, S("FoO").casecmp?(o)) assert_equal(true, S("FoO").casecmp?(o))
s1 = S("\xff".force_encoding("UTF-8"))
s2 = S("\xff".force_encoding("ISO-2022-JP"))
assert_nil(s1.casecmp?(s2))
end end
def test_upcase2 def test_upcase2