diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb index 572418313..70fb113b1 100644 --- a/mrbgems/mruby-string-ext/mrblib/string.rb +++ b/mrbgems/mruby-string-ext/mrblib/string.rb @@ -54,19 +54,6 @@ class String # "abcd".insert(-3, 'X') #=> "abXcd" # "abcd".insert(-1, 'X') #=> "abcdX" # - def insert(idx, str) - if idx == -1 - return self << str - elsif idx < 0 - idx += 1 - end - self[idx, 0] = str - self - end - - - - ## # Call the given block for each character of diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index da34a9a12..8c710e453 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -2106,6 +2106,54 @@ mrb_str_rpartition(mrb_state *mrb, mrb_value self) return result_ary; } +/* + * call-seq: + * str.insert(index, other_str) -> str + * + * Inserts other_str before the character at the given + * index, modifying str. Negative indices count from the + * end of the string, and insert after the given character. + * The intent is insert aString so that it starts at the given + * index. + * + * "abcd".insert(0, 'X') #=> "Xabcd" + * "abcd".insert(3, 'X') #=> "abcXd" + * "abcd".insert(4, 'X') #=> "abcdX" + * "abcd".insert(-3, 'X') #=> "abXcd" + * "abcd".insert(-1, 'X') #=> "abcdX" + */ +static mrb_value +mrb_str_insert(mrb_state *mrb, mrb_value self) +{ + mrb_int idx; + mrb_value str_to_insert; + mrb_get_args(mrb, "iS", &idx, &str_to_insert); + + struct RString *s = mrb_str_ptr(self); + mrb_int self_len = RSTRING_LEN(self); + mrb_int insert_len = RSTRING_LEN(str_to_insert); + const char *insert_ptr = RSTRING_PTR(str_to_insert); + + mrb_check_frozen(mrb, s); + + if (idx < 0) { + idx = self_len + idx + 1; + } + + if (idx < 0 || idx > self_len) { + mrb_raisef(mrb, E_INDEX_ERROR, "index %S out of string", mrb_int_value(mrb, idx)); + } + + mrb_str_modify(mrb, s); + mrb_str_resize(mrb, self, self_len + insert_len); + + char *p = RSTRING_PTR(self); + memmove(p + idx + insert_len, p + idx, self_len - idx); + memcpy(p + idx, insert_ptr, insert_len); + + return self; +} + void mrb_mruby_string_ext_gem_init(mrb_state* mrb) { @@ -2122,6 +2170,7 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb) mrb_define_method_id(mrb, s, MRB_SYM(tr), str_tr_m, MRB_ARGS_REQ(2)); mrb_define_method_id(mrb, s, MRB_SYM(partition), mrb_str_partition, MRB_ARGS_REQ(1)); mrb_define_method_id(mrb, s, MRB_SYM(rpartition), mrb_str_rpartition, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, s, MRB_SYM(insert), mrb_str_insert, MRB_ARGS_REQ(2)); mrb_define_method_id(mrb, s, MRB_SYM_B(tr), str_tr_bang, MRB_ARGS_REQ(2)); mrb_define_method_id(mrb, s, MRB_SYM(tr_s), str_tr_s, MRB_ARGS_REQ(2)); mrb_define_method_id(mrb, s, MRB_SYM_B(tr_s), str_tr_s_bang, MRB_ARGS_REQ(2));