aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--io.c20
-rw-r--r--spec/ruby/core/io/puts_spec.rb9
-rw-r--r--test/ruby/test_io.rb13
3 files changed, 32 insertions, 10 deletions
diff --git a/io.c b/io.c
index 818399271e..03cd40e7e8 100644
--- a/io.c
+++ b/io.c
@@ -1686,6 +1686,16 @@ rb_io_write(VALUE io, VALUE str)
return rb_funcallv(io, id_write, 1, &str);
}
+static VALUE
+rb_io_writev(VALUE io, int argc, VALUE *argv)
+{
+ if (argc > 1 && rb_obj_method_arity(io, id_write) == 1) {
+ do rb_io_write(io, *argv++); while (--argc);
+ return argv[0]; /* unused right now */
+ }
+ return rb_funcallv(io, id_write, argc, argv);
+}
+
/*
* call-seq:
* ios << obj -> ios
@@ -7572,8 +7582,8 @@ io_puts_ary(VALUE ary, VALUE out, int recur)
VALUE
rb_io_puts(int argc, const VALUE *argv, VALUE out)
{
- int i;
- VALUE line;
+ int i, n;
+ VALUE line, args[2];
/* if no argument given, print newline. */
if (argc == 0) {
@@ -7590,11 +7600,13 @@ rb_io_puts(int argc, const VALUE *argv, VALUE out)
}
line = rb_obj_as_string(argv[i]);
string:
- rb_io_write(out, line);
+ n = 0;
+ args[n++] = line;
if (RSTRING_LEN(line) == 0 ||
!rb_str_end_with_asciichar(line, '\n')) {
- rb_io_write(out, rb_default_rs);
+ args[n++] = rb_default_rs;
}
+ rb_io_writev(out, n, args);
}
return Qnil;
diff --git a/spec/ruby/core/io/puts_spec.rb b/spec/ruby/core/io/puts_spec.rb
index 8f2f4f2c81..51240eed73 100644
--- a/spec/ruby/core/io/puts_spec.rb
+++ b/spec/ruby/core/io/puts_spec.rb
@@ -43,18 +43,16 @@ describe "IO#puts" do
object.should_receive(:method_missing).with(:to_ary)
object.should_receive(:to_s).and_return("#<Object:0x...>")
- @io.should_receive(:write).with("#<Object:0x...>")
- @io.should_receive(:write).with("\n")
@io.puts(object).should == nil
+ ScratchPad.recorded.should == "#<Object:0x...>\n"
end
it "calls :to_ary before writing non-string objects" do
object = mock('hola')
object.should_receive(:to_ary).and_return(["hola"])
- @io.should_receive(:write).with("hola")
- @io.should_receive(:write).with("\n")
@io.puts(object).should == nil
+ ScratchPad.recorded.should == "hola\n"
end
it "calls :to_s before writing non-string objects that don't respond to :to_ary" do
@@ -69,9 +67,8 @@ describe "IO#puts" do
object = mock('hola')
object.should_receive(:to_s).and_return(false)
- @io.should_receive(:write).with(object.inspect.split(" ")[0] + ">")
- @io.should_receive(:write).with("\n")
@io.puts(object).should == nil
+ ScratchPad.recorded.should == object.inspect.split(" ")[0] + ">\n"
end
it "writes each arg if given several" do
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index c7de83784b..a32369eca5 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -2445,6 +2445,19 @@ End
end)
end
+ def test_puts_parallel
+ pipe(proc do |w|
+ threads = []
+ 100.times do
+ threads << Thread.new { w.puts "hey" }
+ end
+ threads.each(&:join)
+ w.close
+ end, proc do |r|
+ assert_equal("hey\n" * 100, r.read)
+ end)
+ end
+
def test_display
pipe(proc do |w|
"foo".display(w)