diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-04-18 12:48:26 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-04-18 12:48:26 +0000 |
commit | 609a6ebac54746adc36422dce417cdb02d126886 (patch) | |
tree | ad9b669dc20d643ca35a18e76f9c4e96ec0f845f /string.c | |
parent | 95013cd5c0196f7a7fb0261594dcb74e3588af42 (diff) | |
download | ruby-609a6ebac54746adc36422dce417cdb02d126886.tar.gz |
string.c: share middle of a string
* string.c (rb_str_new_frozen): consider the shared string at
middle.
* string.c (rb_str_subseq, rb_str_substr, str_byte_substr): share
middle of a string.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45628 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r-- | string.c | 26 |
1 files changed, 15 insertions, 11 deletions
@@ -823,16 +823,17 @@ rb_str_new_frozen(VALUE orig) else { if (FL_TEST(orig, STR_SHARED)) { VALUE shared = RSTRING(orig)->as.heap.aux.shared; - long ofs = RSTRING_LEN(shared) - RSTRING_LEN(orig); + long ofs = RSTRING_PTR(orig) - RSTRING_PTR(shared); + long rest = RSTRING_LEN(shared) - ofs - RSTRING_LEN(orig); assert(OBJ_FROZEN(shared)); - if ((ofs > 0) || + if ((ofs > 0) || (rest > 0) || (klass != RBASIC(shared)->klass) || ((RBASIC(shared)->flags ^ RBASIC(orig)->flags) & FL_TAINT) || ENCODING_GET(shared) != ENCODING_GET(orig)) { str = str_new_shared(klass, shared); RSTRING(str)->as.heap.ptr += ofs; - RSTRING(str)->as.heap.len -= ofs; + RSTRING(str)->as.heap.len -= ofs + rest; } else { return shared; @@ -1789,10 +1790,12 @@ rb_str_subseq(VALUE str, long beg, long len) { VALUE str2; - if (RSTRING_LEN(str) == beg + len && - RSTRING_EMBED_LEN_MAX < len) { - str2 = rb_str_new_shared(rb_str_new_frozen(str)); - rb_str_drop_bytes(str2, beg); + if (RSTRING_EMBED_LEN_MAX < len) { + long olen; + str2 = rb_str_new_shared(rb_str_new_frozen(str)); + RSTRING(str2)->as.heap.ptr += beg; + olen = RSTRING(str2)->as.heap.len; + if (olen > len) RSTRING(str2)->as.heap.len = len; } else { str2 = rb_str_new_with_class(str, RSTRING_PTR(str)+beg, len); @@ -1897,10 +1900,11 @@ rb_str_substr(VALUE str, long beg, long len) char *p = rb_str_subpos(str, beg, &len); if (!p) return Qnil; - if (len > RSTRING_EMBED_LEN_MAX && p + len == RSTRING_END(str)) { + if (len > RSTRING_EMBED_LEN_MAX) { + long ofs = p - RSTRING_PTR(str); str2 = rb_str_new_frozen(str); str2 = str_new_shared(rb_obj_class(str2), str2); - RSTRING(str2)->as.heap.ptr += RSTRING(str2)->as.heap.len - len; + RSTRING(str2)->as.heap.ptr += ofs; RSTRING(str2)->as.heap.len = len; } else { @@ -4409,10 +4413,10 @@ str_byte_substr(VALUE str, long beg, long len) else p = s + beg; - if (len > RSTRING_EMBED_LEN_MAX && beg + len == n) { + if (len > RSTRING_EMBED_LEN_MAX) { str2 = rb_str_new_frozen(str); str2 = str_new_shared(rb_obj_class(str2), str2); - RSTRING(str2)->as.heap.ptr += RSTRING(str2)->as.heap.len - len; + RSTRING(str2)->as.heap.ptr += beg; RSTRING(str2)->as.heap.len = len; } else { |