diff options
author | glass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-07-31 08:47:13 +0000 |
---|---|---|
committer | glass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-07-31 08:47:13 +0000 |
commit | 867876ab9bb156b9a6cd4f5cd84b042cee632492 (patch) | |
tree | 68d30ecd1a74f28eaca22ee549a56e29786b9005 | |
parent | 8b126d59b3b28a5c4b6de6e106a93d1aaa3d2174 (diff) | |
download | ruby-867876ab9bb156b9a6cd4f5cd84b042cee632492.tar.gz |
* string.c (rb_str_rindex): performance improvement by using
memrchr(3).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42269 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | configure.in | 1 | ||||
-rw-r--r-- | string.c | 77 |
3 files changed, 67 insertions, 16 deletions
@@ -1,3 +1,8 @@ +Wed Jul 31 17:45:39 2013 Masaki Matsushita <glass.saga@gmail.com> + + * string.c (rb_str_rindex): performance improvement by using + memrchr(3). + Wed Jul 31 16:43:30 2013 Masaki Matsushita <glass.saga@gmail.com> * string.c (rb_str_rindex): refactoring and avoid to call str_nth() if diff --git a/configure.in b/configure.in index fc5e68fce1..a701056491 100644 --- a/configure.in +++ b/configure.in @@ -1789,6 +1789,7 @@ AC_CHECK_FUNCS(log2) AC_CHECK_FUNCS(lstat) AC_CHECK_FUNCS(mblen) AC_CHECK_FUNCS(memalign) +AC_CHECK_FUNCS(memrchr) AC_CHECK_FUNCS(mktime) AC_CHECK_FUNCS(pipe2) AC_CHECK_FUNCS(poll) @@ -2667,11 +2667,68 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str) return LONG2NUM(pos); } +#if HAVE_MEMRCHR +static long +str_rindex(VALUE str, VALUE sub, const char *s, rb_encoding *enc) +{ + char *hit, *adjusted; + int c; + long slen, searchlen; + char *sbeg, *e, *t; + + sbeg = RSTRING_PTR(str); + e = RSTRING_END(str); + t = RSTRING_PTR(sub); + slen = RSTRING_LEN(sub); + c = *t & 0xff; + searchlen = s - sbeg + 1; + + do { + /* printf("\"%s\" \"%s\" %ld %ld %d\n", hit, t, slen, searchlen, memcmp(hit, t, slen)); */ + hit = memrchr(sbeg, c, searchlen); + if (!hit) break; + adjusted = rb_enc_left_char_head(sbeg, hit, e, enc); + if (hit != adjusted) { + searchlen = adjusted - sbeg; + continue; + } + if (memcmp(hit, t, slen) == 0) + return rb_str_sublen(str, hit - sbeg); + searchlen = adjusted - sbeg; + } while (searchlen > 0); + + return -1; +} +#else +static long +str_rindex(VALUE str, VALUE sub, const char *s, rb_encoding *enc) +{ + long slen; + char *sbeg, *e, *t; + + sbeg = RSTRING_PTR(str); + e = RSTRING_END(str); + t = RSTRING_PTR(sub); + slen = RSTRING_LEN(sub); + + while (s) { + if (memcmp(s, t, slen) == 0) { + return pos; + } + if (pos == 0) break; + pos--; + s = rb_enc_prev_char(sbeg, s, e, enc); + } + + return -1; +} +#endif + static long rb_str_rindex(VALUE str, VALUE sub, long pos) { long len, slen; - char *s, *sbeg, *e, *t; + char *sbeg, *s; rb_encoding *enc; int singlebyte; @@ -2687,28 +2744,16 @@ rb_str_rindex(VALUE str, VALUE sub, long pos) if (len == 0) return pos; sbeg = RSTRING_PTR(str); - e = RSTRING_END(str); - t = RSTRING_PTR(sub); - slen = RSTRING_LEN(sub); if (pos == 0) { - if (memcmp(sbeg, t, slen) == 0) + if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0) return 0; else return -1; } - s = str_nth(sbeg, e, pos, enc, singlebyte); - - while (s) { - if (memcmp(s, t, slen) == 0) { - return pos; - } - if (pos == 0) break; - pos--; - s = rb_enc_prev_char(sbeg, s, e, enc); - } - return -1; + s = str_nth(sbeg, RSTRING_END(str), pos, enc, singlebyte); + return str_rindex(str, sub, s, enc); } |