GitHub

@@ -2945,6 +2945,87 @@ sub_replace(mrb_state *mrb, mrb_value self)

29452945

return result;

29462946

}

294729472948+2949+

static mrb_value

2950+

str_bytesplice(mrb_state *mrb, mrb_value str, mrb_int idx1, mrb_int len1, mrb_value replace, mrb_int idx2, mrb_int len2)

2951+

{

2952+

struct RString *s = RSTRING(str);

2953+

if (RSTR_LEN(s) <= idx1 || RSTRING_LEN(replace) <= idx2) {

2954+

mrb_raise(mrb, E_INDEX_ERROR, "index out of string");

2955+

}

2956+

if (RSTR_LEN(s) <= idx1+len1) {

2957+

len1 = RSTR_LEN(s) - idx1;

2958+

}

2959+

if (RSTRING_LEN(replace) <= idx2+len2) {

2960+

len2 = RSTRING_LEN(replace) - idx2;

2961+

}

2962+

if (len2 == 0) return replace;

2963+

mrb_str_modify(mrb, s);

2964+

if (len1 >= len2) {

2965+

memmove(RSTR_PTR(s)+idx1, RSTRING_PTR(replace)+idx2, len2);

2966+

if (len1 > len2) {

2967+

memmove(RSTR_PTR(s)+idx1+len2, RSTR_PTR(s)+idx1+len1, RSTR_LEN(s)-(idx1+len1));

2968+

RSTR_SET_LEN(s, RSTR_LEN(s)-(len1-len2));

2969+

}

2970+

}

2971+

else { /* len1 < len2 */

2972+

mrb_int slen = RSTR_LEN(s);

2973+

mrb_str_resize(mrb, str, slen+len2-len1);

2974+

memmove(RSTR_PTR(s)+idx1+len2, RSTR_PTR(s)+idx1+len1, slen-(idx1+len1));

2975+

memmove(RSTR_PTR(s)+idx1, RSTRING_PTR(replace)+idx2, len2);

2976+

}

2977+

return replace;

2978+

}

2979+2980+

/*

2981+

* call-seq:

2982+

* bytesplice(index, length, str) -> string

2983+

* bytesplice(index, length, str, str_index, str_length) -> string

2984+

* bytesplice(range, str) -> string

2985+

* bytesplice(range, str, str_range) -> string

2986+

*

2987+

* Replaces some or all of the content of +self+ with +str+, and returns +self+.

2988+

* The portion of the string affected is determined using

2989+

* the same criteria as String#byteslice, except that +length+ cannot be omitted.

2990+

* If the replacement string is not the same length as the text it is replacing,

2991+

* the string will be adjusted accordingly.

2992+

*

2993+

* If +str_index+ and +str_length+, or +str_range+ are given, the content of +self+ is replaced by str.byteslice(str_index, str_length) or str.byteslice(str_range); however the substring of +str+ is not allocated as a new string.

2994+

*

2995+

* The form that take an Integer will raise an IndexError if the value is out

2996+

* of range; the Range form will raise a RangeError.

2997+

* If the beginning or ending offset does not land on character (codepoint)

2998+

* boundary, an IndexError will be raised.

2999+

*/

3000+

static mrb_value

3001+

mrb_str_bytesplice(mrb_state *mrb, mrb_value str)

3002+

{

3003+

mrb_int idx1, len1, idx2, len2;

3004+

mrb_value range1, range2, replace;

3005+

switch (mrb_get_argc(mrb)) {

3006+

case 3:

3007+

mrb_get_args(mrb, "ooo", &range1, &replace, &range2);

3008+

if (mrb_integer_p(range1)) {

3009+

mrb_get_args(mrb, "iiS", &idx1, &len1, &replace);

3010+

return str_bytesplice(mrb, str, idx1, len1, replace, 0, RSTRING_LEN(replace));

3011+

}

3012+

if (mrb_range_beg_len(mrb, range1, &idx1, &len1, RSTRING_LEN(str), FALSE) != MRB_RANGE_OK) break;

3013+

if (mrb_range_beg_len(mrb, range2, &idx2, &len2, RSTRING_LEN(replace), FALSE) != MRB_RANGE_OK) break;

3014+

return str_bytesplice(mrb, str, idx1, len1, replace, idx2, len2);

3015+

case 5:

3016+

mrb_get_args(mrb, "iiSii", &idx1, &len1, &replace, &idx2, &len2);

3017+

return str_bytesplice(mrb, str, idx1, len1, replace, idx2, len2);

3018+

case 2:

3019+

mrb_get_args(mrb, "oS", &range1, &replace);

3020+

if (mrb_range_beg_len(mrb, range1, &idx1, &len1, RSTRING_LEN(str), FALSE) == MRB_RANGE_OK) {

3021+

return str_bytesplice(mrb, str, idx1, len1, replace, 0, RSTRING_LEN(replace));

3022+

}

3023+

default:

3024+

break;

3025+

}

3026+

mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arumgnts");

3027+

}

3028+29483029

/* ---------------------------*/

29493030

void

29503031

mrb_init_string(mrb_state *mrb)

@@ -3008,6 +3089,7 @@ mrb_init_string(mrb_state *mrb)

30083089

mrb_define_method(mrb, s, "byteindex", mrb_str_byteindex_m, MRB_ARGS_ARG(1,1));

30093090

mrb_define_method(mrb, s, "byterindex", mrb_str_byterindex_m, MRB_ARGS_ARG(1,1));

30103091

mrb_define_method(mrb, s, "byteslice", mrb_str_byteslice, MRB_ARGS_ARG(1,1));

3092+

mrb_define_method(mrb, s, "bytesplice", mrb_str_bytesplice, MRB_ARGS_ANY());

3011309330123094

mrb_define_method(mrb, s, "__sub_replace", sub_replace, MRB_ARGS_REQ(3)); /* internal */

30133095

}

Read the original on github.com ↗