* string.c (rb_str_substr): perfomance improvement. [ruby-dev:31806]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13791 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2007-10-29 08:58:17 +00:00
Родитель b088414390
Коммит 2ae60f1634
2 изменённых файлов: 40 добавлений и 13 удалений

Просмотреть файл

@ -1,3 +1,7 @@
Mon Oct 29 17:58:16 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* string.c (rb_str_substr): perfomance improvement. [ruby-dev:31806]
Mon Oct 29 17:20:13 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* encoding.c (rb_enc_replicate): new function to replicate encoding.

Просмотреть файл

@ -787,27 +787,50 @@ rb_str_substr(VALUE str, long beg, long len)
{
rb_encoding *enc = rb_enc_get(str);
VALUE str2;
int slen = str_strlen(str, enc);
char *p, *s = RSTRING_PTR(str), *e = s + RSTRING_LEN(str);
if (len < 0) return Qnil;
if (beg > slen) return Qnil;
if (beg < 0) {
beg += slen;
if (beg < 0) return Qnil;
}
if (beg + len > slen) {
len = slen - beg;
}
if (len < 0) {
if (!RSTRING_LEN(str)) {
len = 0;
}
if (beg < 0) {
if (len > -beg) len = -beg;
if (-beg * rb_enc_mbmaxlen(enc) < RSTRING_LEN(str) / 8) {
beg = -beg;
while (len++ < beg && (e = rb_enc_prev_char(s, e, enc)) != 0);
p = e;
if (!p) return Qnil;
while (beg-- > 0 && (p = rb_enc_prev_char(s, p, enc)) != 0);
if (!p) return Qnil;
len = e - p;
goto sub;
}
else {
beg += str_strlen(str, enc);
if (beg < 0) return Qnil;
}
}
else if (beg > 0 && beg > str_strlen(str, enc)) {
return Qnil;
}
if (len == 0) {
str2 = rb_str_new5(str,0,0);
p = 0;
}
else if ((p = str_nth(s, e, beg, enc)) == e) {
len = 0;
}
else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
long rest = (e - p) / rb_enc_mbmaxlen(enc);
if (len > rest)
len = rest;
else
len *= rb_enc_mbmaxlen(enc);
}
else {
char *p = str_nth(RSTRING_PTR(str), RSTRING_END(str), beg, enc);
str2 = rb_str_new5(str, p, str_offset(p, RSTRING_END(str), len, enc));
len = str_offset(p, e, len, enc);
}
sub:
str2 = rb_str_new5(str, p, len);
rb_enc_copy(str2, str);
OBJ_INFECT(str2, str);