summaryrefslogtreecommitdiffstats
path: root/string.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-12-17 18:20:46 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-12-17 18:20:46 +0000
commit4f2d51cdb87dcc413934e000fa27c52e05ecf392 (patch)
tree97e2974f426a0cb1dbc82c3ca75d6e4f6095e2f5 /string.c
parent67ef69a9dfff3a47f7e3c150a6c00bd85f6a2649 (diff)
downloadruby-4f2d51cdb87dcc413934e000fa27c52e05ecf392.tar.gz
ruby-4f2d51cdb87dcc413934e000fa27c52e05ecf392.tar.xz
ruby-4f2d51cdb87dcc413934e000fa27c52e05ecf392.zip
* string.c (rb_str_new4): handle tail shared string.
(ruby-bugs-ja:PR#370) git-svn-id: http://svn.ruby-lang.org/repos/ruby/trunk@3164 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r--string.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/string.c b/string.c
index 5ca6aae4d..01316b9c2 100644
--- a/string.c
+++ b/string.c
@@ -137,6 +137,21 @@ rb_str_new3(str)
return str_new3(rb_obj_class(str), str);
}
+static VALUE
+str_new4(klass, str)
+ VALUE klass, str;
+{
+ VALUE str2 = rb_obj_alloc(klass);
+
+ RSTRING(str2)->len = RSTRING(str)->len;
+ RSTRING(str2)->ptr = RSTRING(str)->ptr;
+ RSTRING(str)->aux.shared = str2;
+ FL_SET(str, ELTS_SHARED);
+ OBJ_INFECT(str2, str);
+
+ return str2;
+}
+
VALUE
rb_str_new4(orig)
VALUE orig;
@@ -145,20 +160,20 @@ rb_str_new4(orig)
klass = rb_obj_class(orig);
if (FL_TEST(orig, ELTS_SHARED)) {
- str = str_new3(klass, RSTRING(orig)->aux.shared);
+ long ofs;
+ str = RSTRING(orig)->aux.shared;
+ ofs = RSTRING(str)->len - RSTRING(orig)->len;
+ str = str_new3(klass, str);
+ RSTRING(str)->ptr += ofs;
+ RSTRING(str)->len -= ofs;
}
else if (FL_TEST(orig, STR_ASSOC)) {
str = str_new(klass, RSTRING(orig)->ptr, RSTRING(orig)->len);
+ OBJ_INFECT(str, orig);
}
else {
- str = rb_obj_alloc(klass);
-
- RSTRING(str)->len = RSTRING(orig)->len;
- RSTRING(str)->ptr = RSTRING(orig)->ptr;
- RSTRING(orig)->aux.shared = str;
- FL_SET(orig, ELTS_SHARED);
+ str = str_new4(klass, orig);
}
- OBJ_INFECT(str, orig);
OBJ_FREEZE(str);
return str;
}
@@ -477,7 +492,7 @@ rb_str_substr(str, beg, len)
if (len > sizeof(struct RString)/2 &&
beg + len == RSTRING(str)->len &&
!FL_TEST(str, STR_ASSOC)) {
- if (!FL_TEST(str, ELTS_SHARED)) str = rb_str_new4(str);
+ if (!FL_TEST(str, ELTS_SHARED)) str = str_new4(CLASS_OF(str), str);
str2 = rb_str_new3(str);
RSTRING(str2)->ptr += beg;
RSTRING(str2)->len = len;