Revision: 3828 http://trac.macosforge.org/projects/ruby/changeset/3828 Author: lsansonetti@apple.com Date: 2010-03-19 15:26:15 -0700 (Fri, 19 Mar 2010) Log Message: ----------- added #slice!, fixed some bugs in #[] Modified Paths: -------------- MacRuby/trunk/string.c Modified: MacRuby/trunk/string.c =================================================================== --- MacRuby/trunk/string.c 2010-03-19 11:35:23 UTC (rev 3827) +++ MacRuby/trunk/string.c 2010-03-19 22:26:15 UTC (rev 3828) @@ -1179,9 +1179,6 @@ if (len < 0) { return Qnil; } - if (len == 0) { - return str_new(); - } const long n = str_length(RSTR(str), false); if (beg < 0) { @@ -1190,6 +1187,9 @@ if (beg > n || beg < 0) { return Qnil; } + if (len == 0 || beg == n) { + return str_new(); + } if (beg + len > n) { len = n - beg; } @@ -1642,11 +1642,17 @@ VALUE rstr_aref(VALUE str, SEL sel, int argc, VALUE *argv) { + VALUE result = Qnil; + bool tainted = OBJ_TAINTED(str); + if (argc == 2) { if (TYPE(argv[0]) == T_REGEXP) { - return rb_str_subpat(str, argv[0], NUM2INT(argv[1])); + result = rb_str_subpat(str, argv[0], NUM2INT(argv[1])); } - return rstr_substr(str, NUM2LONG(argv[0]), NUM2LONG(argv[1])); + else { + result = rstr_substr(str, NUM2LONG(argv[0]), NUM2LONG(argv[1])); + } + goto bail; } if (argc != 1) { @@ -1656,21 +1662,24 @@ VALUE indx = argv[0]; switch (TYPE(indx)) { case T_FIXNUM: - str = rstr_substr(str, FIX2LONG(indx), 1); - if (!NIL_P(str) && str_length(RSTR(str), true) == 0) { + result = rstr_substr(str, FIX2LONG(indx), 1); + if (NIL_P(result) || rb_str_chars_len(result) == 0) { return Qnil; } - return str; + break; case T_REGEXP: - return rb_str_subpat(str, indx, 0); + result = rb_str_subpat(str, indx, 0); + break; case T_STRING: { + tainted = false; if (IS_RSTR(indx)) { rb_str_t *searched = RSTR(indx); if (str_include_string(RSTR(str), searched)) { - return (VALUE)str_dup(searched); + result = (VALUE)str_dup(searched); + goto bail; } } else { @@ -1679,7 +1688,8 @@ if (str_include_string(RSTR(str), searched)) { // no need to duplicate the string as we just // created it - return (VALUE)searched; + result = (VALUE)searched; + goto bail; } } return Qnil; @@ -1695,15 +1705,30 @@ case Qnil: return Qnil; default: - return rstr_substr(str, beg, len); + result = rstr_substr(str, beg, len); + goto bail; } - str = rstr_substr(str, NUM2LONG(indx), 1); - if (!NIL_P(str) && str_length(RSTR(str), true) == 0) { + result = rstr_substr(str, NUM2LONG(indx), 1); + if (NIL_P(result) || rb_str_chars_len(result) == 0) { return Qnil; } - return str; + break; } } + +bail: + if (!tainted) { + for (int i = 0; i < argc; i++) { + if (OBJ_TAINTED(argv[i])) { + tainted = true; + break; + } + } + } + if (tainted) { + OBJ_TAINT(result); + } + return result; } /* @@ -1821,6 +1846,48 @@ /* * call-seq: + * str.slice!(fixnum) => fixnum or nil + * str.slice!(fixnum, fixnum) => new_str or nil + * str.slice!(range) => new_str or nil + * str.slice!(regexp) => new_str or nil + * str.slice!(other_str) => new_str or nil + * + * Deletes the specified portion from <i>str</i>, and returns the portion + * deleted. + * + * string = "this is a string" + * string.slice!(2) #=> "i" + * string.slice!(3..6) #=> " is " + * string.slice!(/s.*t/) #=> "sa st" + * string.slice!("r") #=> "r" + * string #=> "thing" + */ + +static VALUE +rstr_slice_bang(VALUE str, SEL sel, int argc, VALUE *argv) +{ + if (argc < 1 || 2 < argc) { + rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc); + } + + rstr_modify(str); + + int i; + VALUE buf[3]; + for (i=0; i < argc; i++) { + buf[i] = argv[i]; + } + buf[i] = rb_str_new(NULL, 0); + + VALUE result = rstr_aref(str, 0, argc, buf); + if (!NIL_P(result)) { + rstr_aset(str, 0, argc + 1, buf); + } + return result; +} + +/* + * call-seq: * str.insert(index, other_str) => str * * Inserts <i>other_str</i> before the character at the given @@ -5344,6 +5411,7 @@ rb_objc_define_method(rb_cRubyString, "[]", rstr_aref, -1); rb_objc_define_method(rb_cRubyString, "[]=", rstr_aset, -1); rb_objc_define_method(rb_cRubyString, "slice", rstr_aref, -1); + rb_objc_define_method(rb_cRubyString, "slice!", rstr_slice_bang, -1); rb_objc_define_method(rb_cRubyString, "insert", rstr_insert, 2); rb_objc_define_method(rb_cRubyString, "index", rstr_index, -1); rb_objc_define_method(rb_cRubyString, "rindex", rstr_rindex, -1);