[macruby-changes] [3676] MacRuby/branches/icu/string.c
source_changes at macosforge.org
source_changes at macosforge.org
Tue Mar 2 19:22:13 PST 2010
Revision: 3676
http://trac.macosforge.org/projects/ruby/changeset/3676
Author: lsansonetti at apple.com
Date: 2010-03-02 19:22:13 -0800 (Tue, 02 Mar 2010)
Log Message:
-----------
added #[]=, fixed a bug in str_splice()
Modified Paths:
--------------
MacRuby/branches/icu/string.c
Modified: MacRuby/branches/icu/string.c
===================================================================
--- MacRuby/branches/icu/string.c 2010-03-03 02:55:45 UTC (rev 3675)
+++ MacRuby/branches/icu/string.c 2010-03-03 03:22:13 UTC (rev 3676)
@@ -768,7 +768,8 @@
bytes_to_add = str->length_in_bytes;
}
- if (end.end_offset_in_bytes == self->length_in_bytes) {
+ if (beg.start_offset_in_bytes == end.end_offset_in_bytes
+ && end.end_offset_in_bytes == self->length_in_bytes) {
if (bytes_to_add > 0) {
// We are splicing at the very end.
memcpy(self->data.bytes + self->length_in_bytes, str->data.bytes,
@@ -1159,7 +1160,13 @@
len = slen - beg;
}
+ rstr_modify(self);
+
str_splice(RSTR(self), beg, len, str_need_string(str), false);
+
+ if (OBJ_TAINTED(str)) {
+ OBJ_TAINT(self);
+ }
}
static VALUE
@@ -1636,6 +1643,119 @@
/*
* call-seq:
+ * str[fixnum] = new_str
+ * str[fixnum, fixnum] = new_str
+ * str[range] = aString
+ * str[regexp] = new_str
+ * str[regexp, fixnum] = new_str
+ * str[other_str] = new_str
+ *
+ * Element Assignment---Replaces some or all of the content of <i>str</i>. The
+ * portion of the string affected is determined using the same criteria as
+ * <code>String#[]</code>. If the replacement string is not the same length as
+ * the text it is replacing, the string will be adjusted accordingly. If the
+ * regular expression or string is used as the index doesn't match a position
+ * in the string, <code>IndexError</code> is raised. If the regular expression
+ * form is used, the optional second <code>Fixnum</code> allows you to specify
+ * which portion of the match to replace (effectively using the
+ * <code>MatchData</code> indexing rules. The forms that take a
+ * <code>Fixnum</code> will raise an <code>IndexError</code> if the value is
+ * out of range; the <code>Range</code> form will raise a
+ * <code>RangeError</code>, and the <code>Regexp</code> and <code>String</code>
+ * forms will silently ignore the assignment.
+ */
+
+static void
+rb_str_subpat_set(VALUE str, VALUE re, int nth, VALUE val)
+{
+ if (rb_reg_search(re, str, 0, false) < 0) {
+ rb_raise(rb_eIndexError, "regexp not matched");
+ }
+ VALUE match = rb_backref_get();
+
+ int count = 0;
+ rb_match_result_t *results = rb_reg_match_results(match, &count);
+ assert(count > 0);
+
+ if (nth >= count) {
+out_of_range:
+ rb_raise(rb_eIndexError, "index %d out of regexp", nth);
+ }
+ if (nth < 0) {
+ if (-nth >= count) {
+ goto out_of_range;
+ }
+ nth += count;
+ }
+
+ const long start = results[nth].beg;
+ if (start == -1) {
+ rb_raise(rb_eIndexError, "regexp group %d not matched", nth);
+ }
+ const long end = results[nth].end;
+ const long len = end - start;
+ rstr_splice(str, start, len, val);
+}
+
+static VALUE
+rstr_aset(VALUE str, SEL sel, int argc, VALUE *argv)
+{
+ if (argc == 3) {
+ if (TYPE(argv[0]) == T_REGEXP) {
+ rb_str_subpat_set(str, argv[0], NUM2INT(argv[1]), argv[2]);
+ }
+ else {
+ rstr_splice(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]),
+ argv[2]);
+ }
+ return argv[2];
+ }
+
+ if (argc != 2) {
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
+ }
+
+ VALUE indx = argv[0];
+ VALUE val = argv[1];
+ long pos = 0;
+
+ switch (TYPE(indx)) {
+ case T_FIXNUM:
+ pos = FIX2LONG(indx);
+num_index:
+ rstr_splice(str, pos, 1, val);
+ return val;
+
+ case T_REGEXP:
+ rb_str_subpat_set(str, indx, 0, val);
+ return val;
+
+ case T_STRING:
+ pos = str_index_for_string(RSTR(str), str_need_string(indx),
+ 0, -1, false, true);
+ if (pos < 0) {
+ rb_raise(rb_eIndexError, "string not matched");
+ }
+ rstr_splice(str, pos, rb_str_chars_len(indx), val);
+ return val;
+
+ default:
+ /* check if indx is Range */
+ {
+ long beg, len;
+ if (rb_range_beg_len(indx, &beg, &len,
+ str_length(RSTR(str), true), 2)) {
+ rstr_splice(str, beg, len, val);
+ return val;
+ }
+ }
+ pos = NUM2LONG(indx);
+ goto num_index;
+ }
+}
+
+/*
+ * call-seq:
* str.index(substring [, offset]) => fixnum or nil
* str.index(fixnum [, offset]) => fixnum or nil
* str.index(regexp [, offset]) => fixnum or nil
@@ -4033,6 +4153,7 @@
rstr_is_valid_encoding, 0);
rb_objc_define_method(rb_cRubyString, "ascii_only?", rstr_is_ascii_only, 0);
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, "index", rstr_index, -1);
rb_objc_define_method(rb_cRubyString, "rindex", rstr_rindex, -1);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100302/f05ad2ff/attachment-0001.html>
More information about the macruby-changes
mailing list