Project

General

Profile

Feature #15588 ยป patch.diff

Glass_saga (Masaki Matsushita), 02/06/2019 01:35 AM

View differences:

string.c
return rb_str_enumerate_chars(str, 0);
}
static long
each_chunk_size(VALUE str, VALUE rb_len)
{
long len, str_len, size;
len = NUM2LONG(rb_len);
if (len <= 0) {
return 0;
}
str_len = rb_str_strlen(str);
size = (str_len + (len - 1)) / len; /* ceil */
return size;
}
static VALUE
rb_str_each_chunk_size(VALUE str, VALUE args, VALUE eobj)
{
VALUE rb_len = RARRAY_AREF(args, 0);
long size = each_chunk_size(str, rb_len);
if (size > 0) {
return LONG2NUM(size);
} else {
return Qnil;
}
}
static VALUE rb_str_strip(VALUE str);
static VALUE
rb_str_enumerate_chunk(int argc, VALUE *argv, VALUE str, VALUE ary)
{
VALUE rb_len, opts, substr, strip = Qfalse, orig = str;
long i, len, str_len;
rb_scan_args(argc, argv, "1:", &rb_len, &opts);
len = NUM2LONG(rb_len);
if (len <= 0) {
rb_raise(rb_eArgError, "length of chunk should be a positive number");
}
if (!NIL_P(opts)) {
static ID keywords[1];
if (!keywords[0]) {
keywords[0] = rb_intern_const("strip");
}
rb_get_kwargs(opts, keywords, 0, 1, &strip);
strip = (strip!= Qundef && RTEST(strip));
}
str = rb_str_new_frozen(str);
str_len = rb_str_strlen(str);
for (i = 0; i*len < str_len; i++) {
substr = rb_str_substr(str, i*len, len);
if (strip) {
substr = rb_str_strip(substr);
}
ENUM_ELEM(ary, substr);
}
RB_GC_GUARD(str);
if (ary)
return ary;
else
return orig;
}
/*
* call-seq:
* str.each_chunk(length, strip: false) {|chunk| block } -> str
* str.each_chunk(length, strip: false) -> an_enumerator
*
* Passes each chunk size of length in <i>str</i> to the given block,
* or returns an enumerator if no block is given.
*
* "hello hello\nhello".each_chunk(6) {|c| p c }
* "hello hello\nhello".each_chunk(6, strip: true) {|c| p c }
*
* <em>produces:</em>
*
* "hello "
* "hello\n"
* "hello"
*
* "hello"
* "hello"
* "hello"
*/
static VALUE
rb_str_each_chunk(int argc, VALUE *argv, VALUE str)
{
RETURN_SIZED_ENUMERATOR(str, argc, argv, rb_str_each_chunk_size);
return rb_str_enumerate_chunk(argc, argv, str, 0);
}
/*
* call-seq:
* str.chunks(length, strip: false) -> an_array
*
* Returns an array of chunks size of length in <i>str</i>. This is a
* shorthand for <code>str.each_chunk(length, strip: bool).to_a</code>.
*
* "hello hello\nhello".chunks(6) #=> ["hello ", "hello\n", "hello"]
* "hello hello\nhello".chunks(6, strip: true) #=> ["hello", "hello", "hello"]
*
*/
static VALUE
rb_str_chunks(int argc, VALUE *argv, VALUE str)
{
VALUE rb_len, opts, ary;
rb_scan_args(argc, argv, "1:", &rb_len, &opts);
ary = WANTARRAY("chunks", each_chunk_size(str, rb_len));
return rb_str_enumerate_chunk(argc, argv, str, ary);
}
/*
* call-seq:
* str.chars -> an_array
......
rb_define_method(rb_cString, "chars", rb_str_chars, 0);
rb_define_method(rb_cString, "codepoints", rb_str_codepoints, 0);
rb_define_method(rb_cString, "grapheme_clusters", rb_str_grapheme_clusters, 0);
rb_define_method(rb_cString, "chunks", rb_str_chunks, -1);
rb_define_method(rb_cString, "reverse", rb_str_reverse, 0);
rb_define_method(rb_cString, "reverse!", rb_str_reverse_bang, 0);
rb_define_method(rb_cString, "concat", rb_str_concat_multi, -1);
......
rb_define_method(rb_cString, "each_char", rb_str_each_char, 0);
rb_define_method(rb_cString, "each_codepoint", rb_str_each_codepoint, 0);
rb_define_method(rb_cString, "each_grapheme_cluster", rb_str_each_grapheme_cluster, 0);
rb_define_method(rb_cString, "each_chunk", rb_str_each_chunk, -1);
rb_define_method(rb_cString, "sum", rb_str_sum, -1);
test/ruby/test_string.rb
end
end
def test_each_chunk
s = S("hello world\nhello")
res = []
s.each_chunk(6) {|x| res << x }
assert_equal([S("hello "), S("world\n"), S("hello")], res)
res = []
s.each_chunk(6, strip: true) {|x| res << x }
assert_equal([S("hello"), S("world"), S("hello")], res)
assert_equal s.each_chunk(s.size).to_a, [s]
assert_equal s.each_chunk(65536).to_a, [s]
assert_equal s.each_chunk(6).size, 3
assert_equal s.each_chunk(0).size, nil
assert_equal s.each_chunk(-1).size, nil
assert_equal s.each_chunk(s.size).size, 1
assert_equal s.each_chunk(65536).size, 1
assert_raise(ArgumentError) { s.each_chunk(0).each {} }
assert_raise(ArgumentError) { s.each_chunk(-1).each {} }
s = S("\u{3053 3093 306b 3061 306f 0020 3053 3093 306b 3061 306f 000a 3053 3093 306b 3061 306f}")
res = []
s.each_chunk(6) {|x| res << x }
assert_equal([S("\u{3053 3093 306b 3061 306f 0020}"), S("\u{3053 3093 306b 3061 306f 000a}"), S("\u{3053 3093 306b 3061 306f}")], res)
res = []
s.each_chunk(6, strip: true) {|x| res << x }
assert_equal([S("\u{3053 3093 306b 3061 306f}"), S("\u{3053 3093 306b 3061 306f}"), S("\u{3053 3093 306b 3061 306f}")], res)
assert_equal s.each_chunk(6).size, 3
assert_equal s.each_chunk(s.size).size, 1
end
def test_chunks
s = S("hello world\nhello")
assert_equal ["hello ", "world\n", "hello"], s.chunks(6)
assert_equal ["hello", "world", "hello"], s.chunks(6, strip: true)
assert_equal s.chunks(1), s.chars
assert_equal s.chunks(65536), [s]
s = S("\u{3053 3093 306b 3061 306f 0020 3053 3093 306b 3061 306f 000a 3053 3093 306b 3061 306f}")
assert_equal [S("\u{3053 3093 306b 3061 306f 0020}"), S("\u{3053 3093 306b 3061 306f 000a}"), S("\u{3053 3093 306b 3061 306f}")], s.chunks(6)
assert_equal [S("\u{3053 3093 306b 3061 306f}"), S("\u{3053 3093 306b 3061 306f}"), S("\u{3053 3093 306b 3061 306f}")], s.chunks(6, strip: true)
assert_equal s.chunks(1), s.chars
s = S("hello world\nhello")
assert_raise(ArgumentError) { s.chunks(0) }
assert_raise(ArgumentError) { s.chunks(-1) }
s = S("")
assert_equal s.chunks(1), []
end
def test_empty?
assert_empty(S(""))
assert_not_empty(S("not"))
    (1-1/1)