From 31c55301e4c3c84803186d28d2764363b457532f Mon Sep 17 00:00:00 2001 From: matz Date: Mon, 13 Mar 2000 07:18:45 +0000 Subject: 2000-03-13 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@638 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- string.c | 92 +++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 27 deletions(-) (limited to 'string.c') diff --git a/string.c b/string.c index d7445301f6..f68ffb7dc0 100644 --- a/string.c +++ b/string.c @@ -106,9 +106,7 @@ rb_str_new4(orig) str->ptr = RSTRING(orig)->ptr; RSTRING(orig)->orig = (VALUE)str; str->orig = 0; - if (OBJ_TAINTED(orig)) { - OBJ_TAINT(str); - } + OBJ_INFECT(str, orig); OBJ_FREEZE(str); return (VALUE)str; @@ -162,32 +160,53 @@ rb_obj_as_string(obj) } static VALUE -rb_str_clone(str) +str_dup(str) VALUE str; { - VALUE clone; + VALUE s; - if (RSTRING(str)->orig && !FL_TEST(str, STR_NO_ORIG)) - clone = rb_str_new3(RSTRING(str)->orig); - else - clone = rb_str_new(RSTRING(str)->ptr, RSTRING(str)->len); - if (RSTRING(str)->orig && FL_TEST(str, STR_NO_ORIG)) - RSTRING(str)->orig = RSTRING(str)->orig; - CLONESETUP(clone, str); - return clone; + if (TYPE(str) != T_STRING) str = rb_str_to_str(str); + s = rb_str_new(RSTRING(str)->ptr, RSTRING(str)->len); + if (OBJ_TAINTED(str)) OBJ_TAINT(s); + + return s; } VALUE rb_str_dup(str) VALUE str; { - VALUE s; - if (TYPE(str) != T_STRING) str = rb_str_to_str(str); - s = rb_str_new(RSTRING(str)->ptr, RSTRING(str)->len); - if (OBJ_TAINTED(str)) OBJ_TAINT(s); + if (OBJ_FROZEN(str)) return rb_str_new3(str); + if (FL_TEST(str, STR_NO_ORIG)) return str_dup(str); + if (RSTRING(str)->orig) return rb_str_new3(RSTRING(str)->orig); + else { + VALUE shadow; - return s; + NEWOBJ(dup, struct RString); + OBJSETUP(dup, rb_cString, T_STRING); + + shadow = rb_str_new4(str); + + dup->len = RSTRING(shadow)->len; + dup->ptr = RSTRING(shadow)->ptr; + dup->orig = shadow; + OBJ_INFECT(dup, str); + + return (VALUE)dup; + } +} + + +static VALUE +rb_str_clone(str) + VALUE str; +{ + VALUE clone = rb_str_dup(str); + if (FL_TEST(str, STR_NO_ORIG)) + RSTRING(str)->orig = RSTRING(str)->orig; + CLONESETUP(clone, str); + return clone; } static VALUE @@ -1059,6 +1078,7 @@ rb_str_sub_bang(argc, argv, str) pat = get_pat(argv[0]); if (rb_reg_search(pat, str, 0, 0) >= 0) { + rb_str_modify(str); match = rb_backref_get(); regs = RMATCH(match)->regs; @@ -1071,7 +1091,6 @@ rb_str_sub_bang(argc, argv, str) repl = rb_reg_regsub(repl, str, regs); } plen = END(0) - BEG(0); - rb_str_modify(str); if (RSTRING(repl)->len > plen) { REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len + RSTRING(repl)->len - plen + 1); @@ -1085,6 +1104,7 @@ rb_str_sub_bang(argc, argv, str) RSTRING(repl)->ptr, RSTRING(repl)->len); RSTRING(str)->len += RSTRING(repl)->len - plen; RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; + OBJ_INFECT(str, repl); return str; } return Qnil; @@ -1102,10 +1122,11 @@ rb_str_sub(argc, argv, str) } static VALUE -rb_str_gsub_bang(argc, argv, str) +str_gsub(argc, argv, str, bang) int argc; VALUE *argv; VALUE str; + int bang; { VALUE pat, val, repl, match; struct re_registers *regs; @@ -1129,7 +1150,10 @@ rb_str_gsub_bang(argc, argv, str) pat = get_pat(argv[0]); offset=0; n=0; beg = rb_reg_search(pat, str, 0, 0); - if (beg < 0) return Qnil; /* no match, no substitution */ + if (beg < 0) { + if (bang) return Qnil; /* no match, no substitution */ + return rb_str_dup(str); + } blen = RSTRING(str)->len + 30; /* len + margin */ buf = ALLOC_N(char, blen); @@ -1190,25 +1214,39 @@ rb_str_gsub_bang(argc, argv, str) bp += RSTRING(str)->len - offset; } rb_backref_set(match); - rb_str_modify(str); - free(RSTRING(str)->ptr); + if (bang) { + rb_str_modify(str); + free(RSTRING(str)->ptr); + } + else { + NEWOBJ(dup, struct RString); + OBJSETUP(dup, rb_cString, T_STRING); + str = (VALUE)dup; + } RSTRING(str)->ptr = buf; RSTRING(str)->len = len = bp - buf; RSTRING(str)->ptr[len] = '\0'; - if (tainted) OBJ_TAINT(str); + if (tainted) OBJ_TAINT(str); return str; } +static VALUE +rb_str_gsub_bang(argc, argv, str) + int argc; + VALUE *argv; + VALUE str; +{ + return str_gsub(argc, argv, str, 1); +} + static VALUE rb_str_gsub(argc, argv, str) int argc; VALUE *argv; VALUE str; { - str = rb_str_dup(str); - rb_str_gsub_bang(argc, argv, str); - return str; + return str_gsub(argc, argv, str, 0); } static VALUE -- cgit v1.2.3