From: nobu.nakada@... Date: 2002-01-30T02:24:30+09:00 Subject: [ruby-dev:15803] Re: [PATCH] improve on \G なかだです。 At Wed, 30 Jan 2002 01:14:42 +0900, matz@ruby-lang.org (Yukihiro Matsumoto) wrote: > |[ruby-talk:30523]で、-Kを指定すると\Gを使ったマッチが遅いという > |話が出てます。調べてみると、regex.cのre_adjust_startpos()でマル > |チバイトの境界を文字列の最初から探しているせいのようです。逆方 > |向に探すことで-Kがないときとほぼ同じ速度になります。 > > んじゃ、これでコミットしてください。 すいません、なんか激しく間違ってたんで[ruby-dev:15798]に以下を 追加してコミットします。全然テスト条件が足りてませんでした。 > M17Nの方はどうしようかなあ。isleadを使えば実現できるか。 isleadだとマルチバイトの先頭かどうかですよね。それだけじゃUTF8 しかできません。必要なのは2バイト目以降にありうる値かどうかの判 定なので。 #!./ruby -Ke require 'rubyunit' class TestKanji < TestCase def setup @s = "あいうkえお" end def test_match assert_equal(0, /\Gあ/ =~ @s) assert_equal(0, /\Aあ/ =~ @s) assert_equal(2, /い/ =~ @s) assert_equal(4, /う/ =~ @s) assert_equal(7, /え/ =~ @s) end def test_index_1 assert_equal(4, @s.index(/\Gう/, 4)) assert_equal('う', $&) assert_equal(4, @s.index(/\Gう/, 3)) assert_equal('う', $&) assert_equal(4, @s.index(/う/, 3)) assert_nil(@s.index(/\Gう/, 5)) assert_nil(@s.index(/う/, 5)) end def test_index_2 assert_equal(7, @s.index(/\Gえ/, 7)) assert_equal('え', $&) assert_equal(6, @s.index(/\G.え/, 5)) assert_equal('kえ', $&) assert_equal(7, @s.index(/え/, 4)) assert_equal('え', $&) assert_nil(@s.index(/\Gえ/, 8)) assert_nil(@s.index(/え/, 8)) end def test_rindex_1 assert_equal(4, @s.rindex(/\Gう/, 4)) assert_equal('う', $&) assert_equal(4, @s.rindex(/\Gう/, 5)) assert_equal('う', $&) assert_equal(4, @s.rindex(/う/, 5)) assert_equal('う', $&) assert_equal(4, @s.rindex(/う/, 6)) assert_equal('う', $&) assert_nil(@s.rindex(/\Gう/, 3)) assert_nil(@s.rindex(/う/, 3)) end def test_rindex_2 assert_equal(7, @s.rindex(/\Gえ/, 7)) assert_equal('え', $&) assert_equal(7, @s.rindex(/\Gえ/, 8)) assert_equal('え', $&) assert_equal(6, @s.rindex(/\G.え/, 6)) assert_equal('kえ', $&) assert_equal(7, @s.rindex(/え/, 8)) assert_equal('え', $&) assert_equal(7, @s.rindex(/え/, 9)) assert_equal('え', $&) assert_nil(@s.rindex(/\Gえ/, 6)) assert_nil(@s.rindex(/え/, 6)) end end --- regex.c~ Tue Jan 29 19:54:17 2002 +++ regex.c Wed Jan 30 01:52:09 2002 @@ -479,5 +479,5 @@ re_set_syntax(syntax) ((current_mbctype != MBCTYPE_UTF8) ? ((c<0x100) ? (c) : (((c)>>8)&0xff)) : utf8_firstbyte(c)) -int mbc_backward_char _((const char *start, int pos)); +int mbc_startpos _((const char *start, int pos)); static unsigned int @@ -3079,9 +3079,12 @@ re_adjust_startpos(bufp, string, size, s /* Adjust startpos for mbc string */ if (current_mbctype && startpos>0 && !(bufp->options&RE_OPTIMIZE_BMATCH)) { - int i = mbc_backward_char(string, startpos); + int i = mbc_startpos(string, startpos); if (i < startpos && range > 0) { startpos = i + mbclen(string[i]); } + else { + startpos = i; + } } return startpos; @@ -4554,14 +4557,15 @@ re_mbcinit(mbctype) int -mbc_backward_char(string, pos) +mbc_startpos(string, pos) const char *string; int pos; { - const char *ptr = string + pos; - while (ptr > string) { - unsigned char c = *ptr; - if (!re_mbctab[c+256]) return ptr - string; - --ptr; + int i = pos, w; + + while (i > 0 && re_mbctab[(unsigned char)string[i]+256]) { + --i; } + if (i == pos || i + (w = mbclen(string[i])) > pos) return i; + i += w; switch (current_mbctype) { @@ -4569,8 +4573,6 @@ mbc_backward_char(string, pos) case MBCTYPE_SJIS: /* double byte char only */ - return pos / 2; + return i + ((pos - i) & ~1); case MBCTYPE_UTF8: - /* illegal sequence */ - /* fall through */ default: return pos; -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦