From 7611dc8338471979d4ed6b585453ac428e149a60 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sat, 16 Dec 2023 14:42:52 +0900 Subject: [PATCH] Fixed `IO#read` with `buf`. I hit the following two problems. - `io.read(0, buf)` always returned a new empty string object. - `io.read(num, buf)` was appending data to the given `buf`. This also meant that `buf` was never empty if EOF was reached. --- mrbgems/mruby-io/src/io.c | 13 ++++++++++++- mrbgems/mruby-io/test/io.rb | 24 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index f796cf660..2b331801e 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -1702,7 +1702,14 @@ io_read(mrb_state *mrb, mrb_value io) mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative length %d given", length); } if (length == 0) { - return mrb_str_new(mrb, NULL, 0); + if (mrb_nil_p(outbuf)) { + outbuf = mrb_str_new(mrb, NULL, 0); + } + else { + mrb_str_modify(mrb, mrb_str_ptr(outbuf)); + RSTR_SET_LEN(mrb_str_ptr(outbuf), 0); + } + return outbuf; } } } @@ -1710,6 +1717,10 @@ io_read(mrb_state *mrb, mrb_value io) if (mrb_nil_p(outbuf)) { outbuf = mrb_str_new_capa(mrb, MRB_IO_BUF_SIZE); } + else { + mrb_str_modify(mrb, mrb_str_ptr(outbuf)); + RSTR_SET_LEN(mrb_str_ptr(outbuf), 0); + } if (!length_given) { /* read as much as possible */ return io_read_all(mrb, fptr, outbuf); } diff --git a/mrbgems/mruby-io/test/io.rb b/mrbgems/mruby-io/test/io.rb index d146d6d8b..811038ff4 100644 --- a/mrbgems/mruby-io/test/io.rb +++ b/mrbgems/mruby-io/test/io.rb @@ -150,6 +150,30 @@ assert "IO#read(n) with n > IO::BUF_SIZE" do end end +assert "IO#read(n, buf)" do + IO.open(IO.sysopen($mrbtest_io_rfname)) do |io| + buf = "12345" + assert_same buf, io.read(0, buf) + assert_equal "", buf + + buf = "12345" + assert_same buf, io.read(5, buf) + assert_equal "mruby", buf + + buf = "12345" + assert_same buf, io.read(nil, buf) + assert_equal " io test\n", buf + + buf = "12345" + assert_nil io.read(99, buf) + assert_equal "", buf + + buf = "12345" + assert_same buf, io.read(0, buf) + assert_equal "", buf + end +end + assert('IO#readchar', '15.2.20.5.15') do # almost same as IO#getc IO.open(IO.sysopen($mrbtest_io_rfname)) do |io|