ruby-changes:33547
From: nobu <ko1@a...>
Date: Fri, 18 Apr 2014 21:48:30 +0900 (JST)
Subject: [ruby-changes:33547] nobu:r45628 (trunk): string.c: share middle of a string
nobu 2014-04-18 21:48:26 +0900 (Fri, 18 Apr 2014) New Revision: 45628 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=45628 Log: 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. Modified files: trunk/ChangeLog trunk/NEWS trunk/string.c Index: ChangeLog =================================================================== --- ChangeLog (revision 45627) +++ ChangeLog (revision 45628) @@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Fri Apr 18 21:48:24 2014 Nobuyoshi Nakada <nobu@r...> + + * 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@r...> * string.c: use uintptr_t instead of VALUE because they are not ruby Index: string.c =================================================================== --- string.c (revision 45627) +++ string.c (revision 45628) @@ -823,16 +823,17 @@ rb_str_new_frozen(VALUE orig) https://github.com/ruby/ruby/blob/trunk/string.c#L823 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 https://github.com/ruby/ruby/blob/trunk/string.c#L1790 { 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 https://github.com/ruby/ruby/blob/trunk/string.c#L1900 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, lon https://github.com/ruby/ruby/blob/trunk/string.c#L4413 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 { Index: NEWS =================================================================== --- NEWS (revision 45627) +++ NEWS (revision 45628) @@ -107,3 +107,8 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L107 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. -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/