summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-02-05 02:45:29 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-02-05 02:45:29 +0000
commit62bd0f180fcdbf3c55ba6cc400ae631986ad720b (patch)
treee58311be6d38b76acd506fd17defa39954618bd9 /string.c
parent5c0d438fd3de8c805433fe7e7469bdd8b291e144 (diff)
* string.c (rb_str_new_frozen): refactoring code.
* Move code from str_new_frozen_with_klass() (and remove it) * `aux.shared' should not be 0 for STR_SHARED strings. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r--string.c72
1 files changed, 31 insertions, 41 deletions
diff --git a/string.c b/string.c
index 35b945090d..86ae2bf6db 100644
--- a/string.c
+++ b/string.c
@@ -798,58 +798,48 @@ rb_str_new_shared(VALUE str)
return str2;
}
-static VALUE
-str_new_frozen_with_klass(VALUE klass, VALUE str)
-{
- VALUE str2;
-
- str2 = str_alloc(klass);
- STR_SET_NOEMBED(str2);
- RSTRING(str2)->as.heap.len = RSTRING_LEN(str);
- RSTRING(str2)->as.heap.ptr = RSTRING_PTR(str);
- if (STR_SHARED_P(str)) {
- VALUE shared = RSTRING(str)->as.heap.aux.shared;
- assert(OBJ_FROZEN(shared));
- STR_SET_SHARED(str2, shared); /* TODO: WB is not needed because str2 is *new* object */
- }
- else {
- RSTRING(str2)->as.heap.aux.capa = RSTRING(str)->as.heap.aux.capa;
- STR_SET_SHARED(str, str2);
- }
- rb_enc_cr_str_exact_copy(str2, str);
- OBJ_INFECT(str2, str);
- return str2;
-}
-
VALUE
rb_str_new_frozen(VALUE orig)
{
VALUE klass, str;
if (OBJ_FROZEN(orig)) return orig;
+
klass = rb_obj_class(orig);
- if (STR_SHARED_P(orig) && (str = RSTRING(orig)->as.heap.aux.shared)) {
- long ofs;
- assert(OBJ_FROZEN(str));
- ofs = RSTRING_LEN(str) - RSTRING_LEN(orig);
- if ((ofs > 0) || (klass != RBASIC(str)->klass) ||
- ((RBASIC(str)->flags ^ RBASIC(orig)->flags) & FL_TAINT) ||
- ENCODING_GET(str) != ENCODING_GET(orig)) {
- str = str_new_shared(klass, str);
- RSTRING(str)->as.heap.ptr += ofs;
- RSTRING(str)->as.heap.len -= ofs;
- rb_enc_cr_str_exact_copy(str, orig);
- OBJ_INFECT(str, orig);
- }
- }
- else if (STR_EMBED_P(orig)) {
+
+ if (STR_EMBED_P(orig)) {
str = str_new(klass, RSTRING_PTR(orig), RSTRING_LEN(orig));
- rb_enc_cr_str_exact_copy(str, orig);
- OBJ_INFECT(str, orig);
}
else {
- str = str_new_frozen_with_klass(klass, orig);
+ if (FL_TEST(orig, STR_SHARED)) {
+ VALUE shared = RSTRING(orig)->as.heap.aux.shared;
+ long ofs = RSTRING_LEN(shared) - RSTRING_LEN(orig);
+ assert(OBJ_FROZEN(shared));
+
+ if ((ofs > 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;
+ }
+ else {
+ return shared;
+ }
+ }
+ else {
+ str = str_alloc(klass);
+ STR_SET_NOEMBED(str);
+ RSTRING(str)->as.heap.len = RSTRING_LEN(orig);
+ RSTRING(str)->as.heap.ptr = RSTRING_PTR(orig);
+ RSTRING(str)->as.heap.aux.capa = RSTRING(orig)->as.heap.aux.capa;
+ STR_SET_SHARED(orig, str);
+ }
}
+
+ rb_enc_cr_str_exact_copy(str, orig);
+ OBJ_INFECT(str, orig);
OBJ_FREEZE(str);
return str;
}