Add String#bytesplice
This commit is contained in:
parent
b8e72bd2e9
commit
1107839a7f
Notes:
git
2022-03-18 11:51:26 +09:00
71
string.c
71
string.c
@ -6296,6 +6296,76 @@ rb_str_byteslice(int argc, VALUE *argv, VALUE str)
|
|||||||
return str_byte_aref(str, argv[0]);
|
return str_byte_aref(str, argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* bytesplice(index, length, str) -> string
|
||||||
|
* bytesplice(range, str) -> string
|
||||||
|
*
|
||||||
|
* Replaces some or all of the content of +self+ with +str+, and returns +str+.
|
||||||
|
* The portion of the string affected is determined using
|
||||||
|
* the same criteria as String#byteslice, except that +length+ cannot be omitted.
|
||||||
|
* If the replacement string is not the same length as the text it is replacing,
|
||||||
|
* the string will be adjusted accordingly.
|
||||||
|
* The form that take an Integer will raise an IndexError if the value is out
|
||||||
|
* of range; the Range form will raise a RangeError.
|
||||||
|
* If the beginning or ending offset does not land on character (codepoint)
|
||||||
|
* boundary, an IndexError will be raised.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
rb_str_bytesplice(int argc, VALUE *argv, VALUE str)
|
||||||
|
{
|
||||||
|
long beg, end, len, slen;
|
||||||
|
VALUE val;
|
||||||
|
rb_encoding *enc;
|
||||||
|
int cr;
|
||||||
|
|
||||||
|
rb_check_arity(argc, 2, 3);
|
||||||
|
if (argc == 2) {
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
beg = NUM2LONG(argv[0]);
|
||||||
|
len = NUM2LONG(argv[1]);
|
||||||
|
val = argv[2];
|
||||||
|
}
|
||||||
|
if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
|
||||||
|
slen = RSTRING_LEN(str);
|
||||||
|
if ((slen < beg) || ((beg < 0) && (beg + slen < 0))) {
|
||||||
|
rb_raise(rb_eIndexError, "index %ld out of string", beg);
|
||||||
|
}
|
||||||
|
if (beg < 0) {
|
||||||
|
beg += slen;
|
||||||
|
}
|
||||||
|
assert(beg >= 0);
|
||||||
|
assert(beg <= slen);
|
||||||
|
if (len > slen - beg) {
|
||||||
|
len = slen - beg;
|
||||||
|
}
|
||||||
|
end = beg + len;
|
||||||
|
if (!str_check_byte_pos(str, beg)) {
|
||||||
|
rb_raise(rb_eIndexError,
|
||||||
|
"offset %ld does not land on character boundary", beg);
|
||||||
|
}
|
||||||
|
if (!str_check_byte_pos(str, end)) {
|
||||||
|
rb_raise(rb_eIndexError,
|
||||||
|
"offset %ld does not land on character boundary", end);
|
||||||
|
}
|
||||||
|
StringValue(val);
|
||||||
|
enc = rb_enc_check(str, val);
|
||||||
|
str_modify_keep_cr(str);
|
||||||
|
rb_str_splice_0(str, beg, len, val);
|
||||||
|
rb_enc_associate(str, enc);
|
||||||
|
cr = ENC_CODERANGE_AND(ENC_CODERANGE(str), ENC_CODERANGE(val));
|
||||||
|
if (cr != ENC_CODERANGE_BROKEN)
|
||||||
|
ENC_CODERANGE_SET(str, cr);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* reverse -> string
|
* reverse -> string
|
||||||
@ -12560,6 +12630,7 @@ Init_String(void)
|
|||||||
rb_define_method(rb_cString, "getbyte", rb_str_getbyte, 1);
|
rb_define_method(rb_cString, "getbyte", rb_str_getbyte, 1);
|
||||||
rb_define_method(rb_cString, "setbyte", rb_str_setbyte, 2);
|
rb_define_method(rb_cString, "setbyte", rb_str_setbyte, 2);
|
||||||
rb_define_method(rb_cString, "byteslice", rb_str_byteslice, -1);
|
rb_define_method(rb_cString, "byteslice", rb_str_byteslice, -1);
|
||||||
|
rb_define_method(rb_cString, "bytesplice", rb_str_bytesplice, -1);
|
||||||
rb_define_method(rb_cString, "scrub", str_scrub, -1);
|
rb_define_method(rb_cString, "scrub", str_scrub, -1);
|
||||||
rb_define_method(rb_cString, "scrub!", str_scrub_bang, -1);
|
rb_define_method(rb_cString, "scrub!", str_scrub_bang, -1);
|
||||||
rb_define_method(rb_cString, "freeze", rb_str_freeze, 0);
|
rb_define_method(rb_cString, "freeze", rb_str_freeze, 0);
|
||||||
|
@ -3395,6 +3395,50 @@ CODE
|
|||||||
assert_nil(S("こ").byterindex(S("こんにちは")))
|
assert_nil(S("こ").byterindex(S("こんにちは")))
|
||||||
assert_nil(S("").byterindex(S("こんにちは")))
|
assert_nil(S("").byterindex(S("こんにちは")))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_bytesplice
|
||||||
|
assert_bytesplice_raise(IndexError, S("hello"), -6, 0, "xxx")
|
||||||
|
assert_bytesplice_result("xxxhello", S("hello"), -5, 0, "xxx")
|
||||||
|
assert_bytesplice_result("xxxhello", S("hello"), 0, 0, "xxx")
|
||||||
|
assert_bytesplice_result("xxxello", S("hello"), 0, 1, "xxx")
|
||||||
|
assert_bytesplice_result("xxx", S("hello"), 0, 5, "xxx")
|
||||||
|
assert_bytesplice_result("xxx", S("hello"), 0, 6, "xxx")
|
||||||
|
|
||||||
|
assert_bytesplice_raise(RangeError, S("hello"), -6...-6, "xxx")
|
||||||
|
assert_bytesplice_result("xxxhello", S("hello"), -5...-5, "xxx")
|
||||||
|
assert_bytesplice_result("xxxhello", S("hello"), 0...0, "xxx")
|
||||||
|
assert_bytesplice_result("xxxello", S("hello"), 0..0, "xxx")
|
||||||
|
assert_bytesplice_result("xxxello", S("hello"), 0...1, "xxx")
|
||||||
|
assert_bytesplice_result("xxxllo", S("hello"), 0..1, "xxx")
|
||||||
|
assert_bytesplice_result("xxx", S("hello"), 0..-1, "xxx")
|
||||||
|
assert_bytesplice_result("xxx", S("hello"), 0...5, "xxx")
|
||||||
|
assert_bytesplice_result("xxx", S("hello"), 0...6, "xxx")
|
||||||
|
|
||||||
|
assert_bytesplice_raise(TypeError, S("hello"), 0, "xxx")
|
||||||
|
|
||||||
|
assert_bytesplice_raise(IndexError, S("こんにちは"), -16, 0, "xxx")
|
||||||
|
assert_bytesplice_result("xxxこんにちは", S("こんにちは"), -15, 0, "xxx")
|
||||||
|
assert_bytesplice_result("xxxこんにちは", S("こんにちは"), 0, 0, "xxx")
|
||||||
|
assert_bytesplice_raise(IndexError, S("こんにちは"), 1, 0, "xxx")
|
||||||
|
assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 1, "xxx")
|
||||||
|
assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 2, "xxx")
|
||||||
|
assert_bytesplice_result("xxxんにちは", S("こんにちは"), 0, 3, "xxx")
|
||||||
|
assert_bytesplice_result("こんにちはxxx", S("こんにちは"), 15, 0, "xxx")
|
||||||
|
|
||||||
|
assert_bytesplice_result("", S(""), 0, 0, "")
|
||||||
|
assert_bytesplice_result("xxx", S(""), 0, 0, "xxx")
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def assert_bytesplice_result(expected, s, *args)
|
||||||
|
assert_equal(args.last, s.send(:bytesplice, *args))
|
||||||
|
assert_equal(expected, s)
|
||||||
|
end
|
||||||
|
|
||||||
|
def assert_bytesplice_raise(e, s, *args)
|
||||||
|
assert_raise(e) { s.send(:bytesplice, *args) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class TestString2 < TestString
|
class TestString2 < TestString
|
||||||
|
Loading…
x
Reference in New Issue
Block a user