1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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
This commit is contained in:
nobu 2014-04-18 12:48:26 +00:00
parent 95013cd5c0
commit 609a6ebac5
3 changed files with 28 additions and 11 deletions

View file

@ -1,3 +1,11 @@
Fri Apr 18 21:48:24 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* 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.
Fri Apr 18 15:40:05 2014 NARUSE, Yui <naruse@ruby-lang.org>
* string.c: use uintptr_t instead of VALUE because they are not ruby

5
NEWS
View file

@ -107,3 +107,8 @@ with all sufficient information, see the ChangeLog file.
Ruby's heaps.
* rb_str_cat_cstr() added. This is same as `rb_str_cat2()`.
* `rb_str_substr()` and `rb_str_subseq()` now share middle of a string,
but not only the end of a string. Therefore, result strings may not
be NULL-terminated, `StringValueCStr()` is needed calling to obtain a
NULL-terminated C string.

View file

@ -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 {