* string.c (rb_str_subpos): split from rb_str_substr.  returns
  adjusted position for substring.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36124 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2012-06-18 08:10:13 +00:00
Родитель e2ad92a075
Коммит 3137b0819d
2 изменённых файлов: 48 добавлений и 31 удалений

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

@ -1,3 +1,8 @@
Mon Jun 18 17:10:08 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* string.c (rb_str_subpos): split from rb_str_substr. returns
adjusted position for substring.
Mon Jun 18 10:42:57 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/readline/readline.c (readline_getc): deal with ESC just followed

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

@ -1635,32 +1635,30 @@ rb_str_subseq(VALUE str, long beg, long len)
return str2;
}
VALUE
rb_str_substr(VALUE str, long beg, long len)
static char *
rb_str_subpos(VALUE str, long beg, long *lenp)
{
long len = *lenp;
long slen = -1L;
long blen = RSTRING_LEN(str);
rb_encoding *enc = STR_ENC_GET(str);
VALUE str2;
char *p, *s = RSTRING_PTR(str), *e = s + RSTRING_LEN(str);
char *p, *s = RSTRING_PTR(str), *e = s + blen;
if (len < 0) return Qnil;
if (!RSTRING_LEN(str)) {
if (len < 0) return 0;
if (!blen) {
len = 0;
}
if (single_byte_optimizable(str)) {
if (beg > RSTRING_LEN(str)) return Qnil;
if (beg > blen) return 0;
if (beg < 0) {
beg += RSTRING_LEN(str);
if (beg < 0) return Qnil;
beg += blen;
if (beg < 0) return 0;
}
if (beg + len > RSTRING_LEN(str))
len = RSTRING_LEN(str) - beg;
if (len <= 0) {
len = 0;
p = 0;
}
else
p = s + beg;
goto sub;
if (beg + len > blen)
len = blen - beg;
if (len < 0) return 0;
p = s + beg;
goto end;
}
if (beg < 0) {
if (len > -beg) len = -beg;
@ -1668,29 +1666,32 @@ rb_str_substr(VALUE str, long beg, long len)
beg = -beg;
while (beg-- > len && (e = rb_enc_prev_char(s, e, e, enc)) != 0);
p = e;
if (!p) return Qnil;
if (!p) return 0;
while (len-- > 0 && (p = rb_enc_prev_char(s, p, e, enc)) != 0);
if (!p) return Qnil;
if (!p) return 0;
len = e - p;
goto sub;
goto end;
}
else {
beg += str_strlen(str, enc);
if (beg < 0) return Qnil;
slen = str_strlen(str, enc);
beg += slen;
if (beg < 0) return 0;
p = s + beg;
if (len == 0) goto end;
}
}
else if (beg > 0 && beg > RSTRING_LEN(str)) {
return Qnil;
return 0;
}
if (len == 0) {
if (beg > str_strlen(str, enc)) return Qnil;
p = 0;
if (beg > str_strlen(str, enc)) return 0;
p = s + beg;
}
#ifdef NONASCII_MASK
else if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID &&
enc == rb_utf8_encoding()) {
p = str_utf8_nth(s, e, &beg);
if (beg > 0) return Qnil;
if (beg > 0) return 0;
len = str_utf8_offset(p, e, len);
}
#endif
@ -1699,7 +1700,7 @@ rb_str_substr(VALUE str, long beg, long len)
p = s + beg * char_sz;
if (p > e) {
return Qnil;
return 0;
}
else if (len * char_sz > e - p)
len = e - p;
@ -1707,14 +1708,25 @@ rb_str_substr(VALUE str, long beg, long len)
len *= char_sz;
}
else if ((p = str_nth_len(s, e, &beg, enc)) == e) {
if (beg > 0) return Qnil;
if (beg > 0) return 0;
len = 0;
}
else {
len = str_offset(p, e, len, enc, 0);
}
sub:
if (len > RSTRING_EMBED_LEN_MAX && beg + len == RSTRING_LEN(str)) {
end:
*lenp = len;
return p;
}
VALUE
rb_str_substr(VALUE str, long beg, long len)
{
VALUE str2;
char *p = rb_str_subpos(str, beg, &len);
if (!p) return Qnil;
if (len > RSTRING_EMBED_LEN_MAX && p + len == RSTRING_END(str)) {
str2 = rb_str_new4(str);
str2 = str_new3(rb_obj_class(str2), str2);
RSTRING(str2)->as.heap.ptr += RSTRING(str2)->as.heap.len - len;