Add support for passing a block to IO#readlines and IO.readlines.

This commit is contained in:
Samuel Williams 2023-11-24 13:44:08 +13:00 committed by Hiroshi SHIBATA
parent 2230ac4a28
commit a4f0e5141a
2 changed files with 32 additions and 5 deletions

19
io.c
View file

@ -4472,15 +4472,24 @@ rb_io_readlines(int argc, VALUE *argv, VALUE io)
static VALUE
io_readlines(const struct getline_arg *arg, VALUE io)
{
VALUE line, ary;
VALUE line;
if (arg->limit == 0)
rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
ary = rb_ary_new();
while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
rb_ary_push(ary, line);
// If a block is provided, yield lines.
if (rb_block_given_p()) {
while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
rb_yield(line);
}
return Qnil;
} else {
VALUE ary = rb_ary_new();
while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
rb_ary_push(ary, line);
}
return ary;
}
return ary;
}
/*

View file

@ -20,6 +20,16 @@ describe "IO#readlines" do
-> { @io.readlines }.should raise_error(IOError)
end
ruby_version_is "3.3" do
describe "when invoked with a block" do
it "yields each line to the block" do
lines = []
@io.readlines { |line| lines << line }
lines.should == IOSpecs.lines
end
end
end
describe "when passed no arguments" do
before :each do
suppress_warning {@sep, $/ = $/, " "}
@ -214,6 +224,14 @@ describe "IO.readlines" do
IO.readlines(cmd)
}.should complain(/IO process creation with a leading '\|'/)
end
describe "when invoked with a block" do
it "yields each line to the block" do
lines = []
IO.readlines(@name) { |line| lines << line }
lines.should == IOSpecs.lines
end
end
end
it_behaves_like :io_readlines, :readlines