зеркало из https://github.com/github/ruby.git
[Feature #19314] Add new arguments of String#bytesplice
bytesplice(index, length, str, str_index, str_length) -> string bytesplice(range, str, str_range) -> string In these forms, 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.
This commit is contained in:
Родитель
845f6275b2
Коммит
cce3960964
107
string.c
107
string.c
|
@ -5257,10 +5257,10 @@ rb_str_drop_bytes(VALUE str, long len)
|
|||
}
|
||||
|
||||
static void
|
||||
rb_str_splice_0(VALUE str, long beg, long len, VALUE val)
|
||||
rb_str_splice_1(VALUE str, long beg, long len, VALUE val, long vbeg, long vlen)
|
||||
{
|
||||
char *sptr;
|
||||
long slen, vlen = RSTRING_LEN(val);
|
||||
long slen;
|
||||
int cr;
|
||||
|
||||
if (beg == 0 && vlen == 0) {
|
||||
|
@ -5290,7 +5290,7 @@ rb_str_splice_0(VALUE str, long beg, long len, VALUE val)
|
|||
MEMZERO(sptr + slen, char, -len);
|
||||
}
|
||||
if (vlen > 0) {
|
||||
memmove(sptr + beg, RSTRING_PTR(val), vlen);
|
||||
memmove(sptr + beg, RSTRING_PTR(val) + vbeg, vlen);
|
||||
}
|
||||
slen += vlen - len;
|
||||
STR_SET_LEN(str, slen);
|
||||
|
@ -5298,6 +5298,12 @@ rb_str_splice_0(VALUE str, long beg, long len, VALUE val)
|
|||
ENC_CODERANGE_SET(str, cr);
|
||||
}
|
||||
|
||||
static inline void
|
||||
rb_str_splice_0(VALUE str, long beg, long len, VALUE val)
|
||||
{
|
||||
rb_str_splice_1(str, beg, len, val, 0, RSTRING_LEN(val));
|
||||
}
|
||||
|
||||
void
|
||||
rb_str_update(VALUE str, long beg, long len, VALUE val)
|
||||
{
|
||||
|
@ -6263,16 +6269,49 @@ rb_str_byteslice(int argc, VALUE *argv, VALUE str)
|
|||
return str_byte_aref(str, argv[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
str_check_beg_len(VALUE str, long *beg, long *len)
|
||||
{
|
||||
long end, slen = RSTRING_LEN(str);
|
||||
|
||||
if (*len < 0) rb_raise(rb_eIndexError, "negative length %ld", *len);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* bytesplice(index, length, str) -> string
|
||||
* bytesplice(range, str) -> string
|
||||
* bytesplice(index, length, str, str_index, str_length) -> string
|
||||
* bytesplice(range, str) -> string
|
||||
* bytesplice(range, str, str_range) -> string
|
||||
*
|
||||
* Replaces some or all of the content of +self+ with +str+, and returns +self+.
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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)
|
||||
|
@ -6282,50 +6321,56 @@ rb_str_byteslice(int argc, VALUE *argv, VALUE str)
|
|||
static VALUE
|
||||
rb_str_bytesplice(int argc, VALUE *argv, VALUE str)
|
||||
{
|
||||
long beg, end, len, slen;
|
||||
long beg, len, vbeg, vlen;
|
||||
VALUE val;
|
||||
rb_encoding *enc;
|
||||
int cr;
|
||||
|
||||
rb_check_arity(argc, 2, 3);
|
||||
if (argc == 2) {
|
||||
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]);
|
||||
}
|
||||
}
|
||||
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);
|
||||
str_check_beg_len(str, &beg, &len);
|
||||
str_check_beg_len(val, &vbeg, &vlen);
|
||||
enc = rb_enc_check(str, val);
|
||||
str_modify_keep_cr(str);
|
||||
rb_str_splice_0(str, beg, len, val);
|
||||
rb_str_splice_1(str, beg, len, val, vbeg, vlen);
|
||||
rb_enc_associate(str, enc);
|
||||
cr = ENC_CODERANGE_AND(ENC_CODERANGE(str), ENC_CODERANGE(val));
|
||||
if (cr != ENC_CODERANGE_BROKEN)
|
||||
|
|
|
@ -3454,36 +3454,80 @@ CODE
|
|||
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(IndexError, S("hello"), -6, 0, "bye")
|
||||
assert_bytesplice_result("byehello", S("hello"), -5, 0, "bye")
|
||||
assert_bytesplice_result("byehello", S("hello"), 0, 0, "bye")
|
||||
assert_bytesplice_result("byeello", S("hello"), 0, 1, "bye")
|
||||
assert_bytesplice_result("bye", S("hello"), 0, 5, "bye")
|
||||
assert_bytesplice_result("bye", S("hello"), 0, 6, "bye")
|
||||
|
||||
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(IndexError, S("hello"), -5, 0, "bye", -4, 0)
|
||||
assert_bytesplice_result("byehello", S("hello"), 0, 0, "bye", 0, 3)
|
||||
assert_bytesplice_result("yehello", S("hello"), 0, 0, "bye", 1, 3)
|
||||
assert_bytesplice_result("yehello", S("hello"), 0, 0, "bye", 1, 2)
|
||||
assert_bytesplice_result("ehello", S("hello"), 0, 0, "bye", 2, 1)
|
||||
assert_bytesplice_result("hello", S("hello"), 0, 0, "bye", 3, 0)
|
||||
assert_bytesplice_result("hello", s = S("hello"), 0, 5, s, 0, 5)
|
||||
assert_bytesplice_result("elloo", s = S("hello"), 0, 4, s, 1, 4)
|
||||
assert_bytesplice_result("llolo", s = S("hello"), 0, 3, s, 2, 3)
|
||||
assert_bytesplice_result("lollo", s = S("hello"), 0, 2, s, 3, 2)
|
||||
assert_bytesplice_result("oello", s = S("hello"), 0, 1, s, 4, 1)
|
||||
assert_bytesplice_result("hhell", s = S("hello"), 1, 4, s, 0, 4)
|
||||
assert_bytesplice_result("hehel", s = S("hello"), 2, 3, s, 0, 3)
|
||||
assert_bytesplice_result("helhe", s = S("hello"), 3, 2, s, 0, 2)
|
||||
assert_bytesplice_result("hellh", s = S("hello"), 4, 1, s, 0, 1)
|
||||
|
||||
assert_bytesplice_raise(TypeError, S("hello"), 0, "xxx")
|
||||
assert_bytesplice_raise(RangeError, S("hello"), -6...-6, "bye")
|
||||
assert_bytesplice_result("byehello", S("hello"), -5...-5, "bye")
|
||||
assert_bytesplice_result("byehello", S("hello"), 0...0, "bye")
|
||||
assert_bytesplice_result("byeello", S("hello"), 0..0, "bye")
|
||||
assert_bytesplice_result("byeello", S("hello"), 0...1, "bye")
|
||||
assert_bytesplice_result("byello", S("hello"), 0..1, "bye")
|
||||
assert_bytesplice_result("bye", S("hello"), 0..-1, "bye")
|
||||
assert_bytesplice_result("bye", S("hello"), 0...5, "bye")
|
||||
assert_bytesplice_result("bye", S("hello"), 0...6, "bye")
|
||||
assert_bytesplice_result("llolo", s = S("hello"), 0..2, s, 2..4)
|
||||
|
||||
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_raise(RangeError, S("hello"), -5...-5, "bye", -6...-6)
|
||||
assert_bytesplice_result("byehello", S("hello"), -5...-5, "bye", 0..-1)
|
||||
assert_bytesplice_result("byehello", S("hello"), 0...0, "bye", 0..-1)
|
||||
assert_bytesplice_result("bhello", S("hello"), 0...0, "bye", 0..0)
|
||||
assert_bytesplice_result("byhello", S("hello"), 0...0, "bye", 0..1)
|
||||
assert_bytesplice_result("byehello", S("hello"), 0...0, "bye", 0..2)
|
||||
assert_bytesplice_result("yehello", S("hello"), 0...0, "bye", 1..2)
|
||||
|
||||
assert_bytesplice_raise(TypeError, S("hello"), 0, "bye")
|
||||
|
||||
assert_bytesplice_raise(IndexError, S("こんにちは"), -16, 0, "bye")
|
||||
assert_bytesplice_result("byeこんにちは", S("こんにちは"), -15, 0, "bye")
|
||||
assert_bytesplice_result("byeこんにちは", S("こんにちは"), 0, 0, "bye")
|
||||
assert_bytesplice_raise(IndexError, S("こんにちは"), 1, 0, "bye")
|
||||
assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 1, "bye")
|
||||
assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 2, "bye")
|
||||
assert_bytesplice_result("byeんにちは", S("こんにちは"), 0, 3, "bye")
|
||||
assert_bytesplice_result("こんにちはbye", S("こんにちは"), 15, 0, "bye")
|
||||
|
||||
assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 0, "さようなら", -16, 0)
|
||||
assert_bytesplice_result("こんにちはさようなら", S("こんにちは"), 15, 0, "さようなら", 0, 15)
|
||||
assert_bytesplice_result("さようなら", S("こんにちは"), 0, 15, "さようなら", 0, 15)
|
||||
assert_bytesplice_result("さんにちは", S("こんにちは"), 0, 3, "さようなら", 0, 3)
|
||||
assert_bytesplice_result("さようちは", S("こんにちは"), 0, 9, "さようなら", 0, 9)
|
||||
assert_bytesplice_result("ようなちは", S("こんにちは"), 0, 9, "さようなら", 3, 9)
|
||||
assert_bytesplice_result("ようちは", S("こんにちは"), 0, 9, "さようなら", 3, 6)
|
||||
assert_bytesplice_result("ようならちは", S("こんにちは"), 0, 9, "さようなら", 3, 12)
|
||||
assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 15, "さようなら", -16, 0)
|
||||
assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 15, "さようなら", 1, 0)
|
||||
assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 15, "さようなら", 2, 0)
|
||||
assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 15, "さようなら", 0, 1)
|
||||
assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 15, "さようなら", 0, 2)
|
||||
assert_bytesplice_result("にちはちは", s = S("こんにちは"), 0, 9, s, 6, 9)
|
||||
|
||||
assert_bytesplice_result("", S(""), 0, 0, "")
|
||||
assert_bytesplice_result("xxx", S(""), 0, 0, "xxx")
|
||||
|
||||
assert_bytesplice_raise(ArgumentError, S("hello"), 0, 5, "bye", 0)
|
||||
assert_bytesplice_raise(ArgumentError, S("hello"), 0, 5, "bye", 0..-1)
|
||||
assert_bytesplice_raise(ArgumentError, S("hello"), 0..-1, "bye", 0, 3)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
Загрузка…
Ссылка в новой задаче