String#bytesplice
static VALUE
rb_str_bytesplice(int argc, VALUE *argv, VALUE str)
{
long beg, len, vbeg, vlen;
VALUE val;
int cr;
rb_check_arity(argc, 2, 5);
if (!(argc == 2 || argc == 3 || argc == 5)) {
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 2, 3, or 5)", argc);
}
if (argc == 2 || (argc == 3 && !RB_INTEGER_TYPE_P(argv[0]))) {
if (!rb_range_beg_len(argv[0], &beg, &len, RSTRING_LEN(str), 2)) {
rb_raise(rb_eTypeError, "wrong argument type %s (expected Range)",
rb_builtin_class_name(argv[0]));
}
val = argv[1];
StringValue(val);
if (argc == 2) {
/* bytesplice(range, str) */
vbeg = 0;
vlen = RSTRING_LEN(val);
}
else {
/* bytesplice(range, str, str_range) */
if (!rb_range_beg_len(argv[2], &vbeg, &vlen, RSTRING_LEN(val), 2)) {
rb_raise(rb_eTypeError, "wrong argument type %s (expected Range)",
rb_builtin_class_name(argv[2]));
}
}
}
else {
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
val = argv[2];
StringValue(val);
if (argc == 3) {
/* bytesplice(index, length, str) */
vbeg = 0;
vlen = RSTRING_LEN(val);
}
else {
/* bytesplice(index, length, str, str_index, str_length) */
vbeg = NUM2LONG(argv[3]);
vlen = NUM2LONG(argv[4]);
}
}
str_check_beg_len(str, &beg, &len);
str_check_beg_len(val, &vbeg, &vlen);
str_modify_keep_cr(str);
if (RB_UNLIKELY(ENCODING_GET_INLINED(str) != ENCODING_GET_INLINED(val))) {
rb_enc_associate(str, rb_enc_check(str, val));
}
rb_str_update_1(str, beg, len, val, vbeg, vlen);
cr = ENC_CODERANGE_AND(ENC_CODERANGE(str), ENC_CODERANGE(val));
if (cr != ENC_CODERANGE_BROKEN)
ENC_CODERANGE_SET(str, cr);
return str;
}
Replaces target bytes in self with source bytes from the given string str; returns self.
In the first form, arguments offset and length determine the target bytes, and the source bytes are all of the given str:
'0123456789'.bytesplice(0, 3, 'abc') # => "abc3456789" '0123456789'.bytesplice(3, 3, 'abc') # => "012abc6789" '0123456789'.bytesplice(0, 50, 'abc') # => "abc" '0123456789'.bytesplice(50, 3, 'abc') # Raises IndexError.
The counts of the target bytes and source source bytes may be different:
'0123456789'.bytesplice(0, 6, 'abc') # => "abc6789" # Shorter source. '0123456789'.bytesplice(0, 1, 'abc') # => "abc123456789" # Shorter target.
And either count may be zero (i.e., specifying an empty string):
'0123456789'.bytesplice(0, 3, '') # => "3456789" # Empty source. '0123456789'.bytesplice(0, 0, 'abc') # => "abc0123456789" # Empty target.
In the second form, just as in the first, arugments offset and length determine the target bytes; argument str contains the source bytes, and the additional arguments str_offset and str_length determine the actual source bytes:
'0123456789'.bytesplice(0, 3, 'abc', 0, 3) # => "abc3456789" '0123456789'.bytesplice(0, 3, 'abc', 1, 1) # => "b3456789" # Shorter source. '0123456789'.bytesplice(0, 1, 'abc', 0, 3) # => "abc123456789" # Shorter target. '0123456789'.bytesplice(0, 3, 'abc', 1, 0) # => "3456789" # Empty source. '0123456789'.bytesplice(0, 0, 'abc', 0, 3) # => "abc0123456789" # Empty target.
In the third form, argument range determines the target bytes and the source bytes are all of the given str:
'0123456789'.bytesplice(0..2, 'abc') # => "abc3456789" '0123456789'.bytesplice(3..5, 'abc') # => "012abc6789" '0123456789'.bytesplice(0..5, 'abc') # => "abc6789" # Shorter source. '0123456789'.bytesplice(0..0, 'abc') # => "abc123456789" # Shorter target. '0123456789'.bytesplice(0..2, '') # => "3456789" # Empty source. '0123456789'.bytesplice(0...0, 'abc') # => "abc0123456789" # Empty target.
In the fourth form, just as in the third, arugment range determines the target bytes; argument str contains the source bytes, and the additional argument str_range determines the actual source bytes:
'0123456789'.bytesplice(0..2, 'abc', 0..2) # => "abc3456789" '0123456789'.bytesplice(3..5, 'abc', 0..2) # => "012abc6789" '0123456789'.bytesplice(0..2, 'abc', 0..1) # => "ab3456789" # Shorter source. '0123456789'.bytesplice(0..1, 'abc', 0..2) # => "abc23456789" # Shorter target. '0123456789'.bytesplice(0..2, 'abc', 0...0) # => "3456789" # Empty source. '0123456789'.bytesplice(0...0, 'abc', 0..2) # => "abc0123456789" # Empty target.
In any of the forms, the beginnings and endings of both source and target must be on character boundaries.
In these examples, self has five 3-byte characters, and so has character boundaries at offsets 0, 3, 6, 9, 12, and 15.
'こんにちは'.bytesplice(0, 3, 'abc') # => "abcんにちは" 'こんにちは'.bytesplice(1, 3, 'abc') # Raises IndexError. 'こんにちは'.bytesplice(0, 2, 'abc') # Raises IndexError.
Ruby version changes
-
3.3
-
String#bytesplicenow accepts new arguments index/length or range of the source string to be copied. [Feature #19314]
-
-
3.2
-
String#bytesplicehas been added. [Feature #18598]
-