diff options
author | glass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-10-01 13:44:49 +0000 |
---|---|---|
committer | glass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-10-01 13:44:49 +0000 |
commit | 8320be1007be68232580e374669f54232657dc73 (patch) | |
tree | 47399c3fb76ba2ca3d2f729f3f6452fe63acbf0b /string.c | |
parent | 8875e0ca4affbe1c24ed7c13728124e58881061e (diff) | |
download | ruby-8320be1007be68232580e374669f54232657dc73.tar.gz |
string.c: avoid unnecessary call of str_strlen()
* string.c (rb_strseq_index): refactor and avoid
call of str_strlen() when offset == 0.
it will improve performance of String#index and #include?
* benchmark/bm_string_index.rb: benchmark for this change
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60086 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r-- | string.c | 57 |
1 files changed, 32 insertions, 25 deletions
@@ -3394,43 +3394,50 @@ str_casecmp_p(VALUE str1, VALUE str2) static long rb_strseq_index(VALUE str, VALUE sub, long offset, int in_byte) { - const char *s, *sptr, *e; - long pos, len, slen; + const char *str_ptr, *str_ptr_end, *sub_ptr, *search_start; + long pos, str_len, sub_len, search_len; int single_byte = single_byte_optimizable(str); rb_encoding *enc; enc = rb_enc_check(str, sub); if (is_broken_string(sub)) return -1; - len = (in_byte || single_byte) ? RSTRING_LEN(str) : str_strlen(str, enc); /* rb_enc_check */ - slen = in_byte ? RSTRING_LEN(sub) : str_strlen(sub, enc); /* rb_enc_check */ - if (offset < 0) { - offset += len; - if (offset < 0) return -1; - } - if (len - offset < slen) return -1; + str_ptr = RSTRING_PTR(str); + str_ptr_end = RSTRING_END(str); + str_len = RSTRING_LEN(str); + sub_ptr = RSTRING_PTR(sub); + sub_len = RSTRING_LEN(sub); - s = RSTRING_PTR(str); - e = RSTRING_END(str); - if (offset) { - if (!in_byte) offset = str_offset(s, e, offset, enc, single_byte); - s += offset; + if (str_len < sub_len) return -1; + + if (offset != 0) { + long str_len_char, sub_len_char; + str_len_char = (in_byte || single_byte) ? str_len : str_strlen(str, enc); + sub_len_char = in_byte ? sub_len : str_strlen(sub, enc); + if (offset < 0) { + offset += str_len_char; + if (offset < 0) return -1; + } + if (str_len_char - offset < sub_len_char) return -1; + if (!in_byte) offset = str_offset(str_ptr, str_ptr_end, offset, enc, single_byte); + str_ptr += offset; } - if (slen == 0) return offset; + if (sub_len == 0) return offset; + /* need proceed one character at a time */ - sptr = RSTRING_PTR(sub); - slen = RSTRING_LEN(sub); - len = RSTRING_LEN(str) - offset; + + search_start = str_ptr; + search_len = RSTRING_LEN(str) - offset; for (;;) { const char *t; - pos = rb_memsearch(sptr, slen, s, len, enc); + pos = rb_memsearch(sub_ptr, sub_len, search_start, search_len, enc); if (pos < 0) return pos; - t = rb_enc_right_char_head(s, s+pos, e, enc); - if (t == s + pos) break; - len -= t - s; - if (len <= 0) return -1; - offset += t - s; - s = t; + t = rb_enc_right_char_head(search_start, search_start+pos, str_ptr_end, enc); + if (t == search_start + pos) break; + search_len -= t - search_start; + if (search_len <= 0) return -1; + offset += t - search_start; + search_start = t; } return pos + offset; } |