ruby-changes:4594
From: ko1@a...
Date: Sun, 20 Apr 2008 12:52:15 +0900 (JST)
Subject: [ruby-changes:4594] akr - Ruby:r16088 (trunk): * io.c (copy_stream_fallback): read directly (bypassing readpartial)
akr 2008-04-20 12:51:57 +0900 (Sun, 20 Apr 2008) New Revision: 16088 Modified files: trunk/ChangeLog trunk/io.c trunk/test/ruby/test_io.rb Log: * io.c (copy_stream_fallback): read directly (bypassing readpartial) if possible. http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/test/ruby/test_io.rb?r1=16088&r2=16087&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=16088&r2=16087&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/io.c?r1=16088&r2=16087&diff_format=u Index: ChangeLog =================================================================== --- ChangeLog (revision 16087) +++ ChangeLog (revision 16088) @@ -1,3 +1,8 @@ +Sun Apr 20 12:49:03 2008 Tanaka Akira <akr@f...> + + * io.c (copy_stream_fallback): read directly (bypassing readpartial) + if possible. + Sun Apr 20 04:45:13 2008 Tanaka Akira <akr@f...> * io.c (copy_stream_body): use readpartial and write method for Index: io.c =================================================================== --- io.c (revision 16087) +++ io.c (revision 16088) @@ -6574,34 +6574,49 @@ const int buflen = 16*1024; VALUE n; VALUE buf = rb_str_buf_new(buflen); - if (stp->copy_length == (off_t)-1) { - while (1) { - rb_funcall(stp->src, id_readpartial, - 2, INT2FIX(buflen), buf); - n = rb_io_write(stp->dst, buf); - stp->total += NUM2LONG(n); + long rest = stp->copy_length; + off_t off = stp->src_offset; + + while (1) { + long numwrote; + long l = buflen < rest ? buflen : rest; + if (stp->copy_length == (off_t)-1) { + l = buflen; } - } - else { - long rest = stp->copy_length; - while (0 < rest) { - long l = buflen < rest ? buflen : rest; - long numwrote; + else { + if (rest == 0) + break; + l = buflen < rest ? buflen : rest; + } + if (stp->src_fd == -1) { rb_funcall(stp->src, id_readpartial, 2, INT2FIX(l), buf); - n = rb_io_write(stp->dst, buf); - numwrote = NUM2LONG(n); - stp->total += numwrote; - rest -= numwrote; } + else { + ssize_t ss; + rb_str_resize(buf, buflen); + ss = copy_stream_read(stp, RSTRING_PTR(buf), l, off); + if (ss == -1) + return Qnil; + if (ss == 0) + rb_eof_error(); + rb_str_resize(buf, ss); + if (off != (off_t)-1) + off += ss; + } + n = rb_io_write(stp->dst, buf); + numwrote = NUM2LONG(n); + stp->total += numwrote; + rest -= numwrote; } + return Qnil; } static VALUE copy_stream_fallback(struct copy_stream_struct *stp) { - if (stp->src_offset != (off_t)-1) { + if (stp->src_fd == -1 && stp->src_offset != (off_t)-1) { rb_raise(rb_eArgError, "cannot specify src_offset"); } rb_rescue2(copy_stream_fallback_body, (VALUE)stp, @@ -6624,57 +6639,66 @@ stp->total = 0; if (stp->src == argf || - stp->dst == argf || !(TYPE(stp->src) == T_FILE || rb_respond_to(stp->src, rb_intern("to_io")) || TYPE(stp->src) == T_STRING || - rb_respond_to(stp->src, rb_intern("to_path"))) || - !(TYPE(stp->dst) == T_FILE || - rb_respond_to(stp->dst, rb_intern("to_io")) || - TYPE(stp->dst) == T_STRING || - rb_respond_to(stp->dst, rb_intern("to_path")))) { - return copy_stream_fallback(stp); + rb_respond_to(stp->src, rb_intern("to_path")))) { + src_fd = -1; } - - src_io = rb_check_convert_type(stp->src, T_FILE, "IO", "to_io"); - if (!NIL_P(src_io)) { - GetOpenFile(src_io, src_fptr); - src_fd = src_fptr->fd; - } else { - src_fptr = 0; - FilePathValue(stp->src); - src_path = StringValueCStr(stp->src); + src_io = rb_check_convert_type(stp->src, T_FILE, "IO", "to_io"); + if (!NIL_P(src_io)) { + GetOpenFile(src_io, src_fptr); + src_fd = src_fptr->fd; + } + else { + src_fptr = 0; + FilePathValue(stp->src); + src_path = StringValueCStr(stp->src); #ifdef O_NOCTTY - src_fd = rb_sysopen_internal(src_path, O_RDONLY|O_NOCTTY, 0); + src_fd = rb_sysopen_internal(src_path, O_RDONLY|O_NOCTTY, 0); #else - src_fd = rb_sysopen_internal(src_path, O_RDONLY, 0); + src_fd = rb_sysopen_internal(src_path, O_RDONLY, 0); #endif - if (src_fd == -1) { rb_sys_fail(src_path); } - stp->close_src = 1; + if (src_fd == -1) { rb_sys_fail(src_path); } + stp->close_src = 1; + } } stp->src_fd = src_fd; - dst_io = rb_check_convert_type(stp->dst, T_FILE, "IO", "to_io"); - if (!NIL_P(dst_io)) { - dst_io = GetWriteIO(dst_io); - GetOpenFile(dst_io, dst_fptr); - dst_fd = dst_fptr->fd; + if (stp->dst == argf || + !(TYPE(stp->dst) == T_FILE || + rb_respond_to(stp->dst, rb_intern("to_io")) || + TYPE(stp->dst) == T_STRING || + rb_respond_to(stp->dst, rb_intern("to_path")))) { + dst_fd = -1; } else { - dst_fptr = 0; - FilePathValue(stp->dst); - dst_path = StringValueCStr(stp->dst); + dst_io = rb_check_convert_type(stp->dst, T_FILE, "IO", "to_io"); + if (!NIL_P(dst_io)) { + dst_io = GetWriteIO(dst_io); + GetOpenFile(dst_io, dst_fptr); + dst_fd = dst_fptr->fd; + } + else { + dst_fptr = 0; + FilePathValue(stp->dst); + dst_path = StringValueCStr(stp->dst); #ifdef O_NOCTTY - dst_fd = rb_sysopen_internal(dst_path, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0600); + dst_fd = rb_sysopen_internal(dst_path, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0600); #else - dst_fd = rb_sysopen_internal(dst_path, O_WRONLY|O_CREAT|O_TRUNC, 0600); + dst_fd = rb_sysopen_internal(dst_path, O_WRONLY|O_CREAT|O_TRUNC, 0600); #endif - if (dst_fd == -1) { rb_sys_fail(dst_path); } - stp->close_dst = 1; + if (dst_fd == -1) { rb_sys_fail(dst_path); } + stp->close_dst = 1; + } } stp->dst_fd = dst_fd; + if (stp->src_fd == -1 || stp->dst_fd == -1) { + return copy_stream_fallback(stp); + } + if (src_fptr && dst_fptr && src_fptr->rbuf_len && dst_fptr->wbuf_len) { long len = src_fptr->rbuf_len; VALUE str; Index: test/ruby/test_io.rb =================================================================== --- test/ruby/test_io.rb (revision 16087) +++ test/ruby/test_io.rb (revision 16088) @@ -417,10 +417,51 @@ def test_copy_stream_strio_off src = StringIO.new("abcd") - dst = StringIO.new - assert_raise(ArgumentError) { - IO.copy_stream(src, dst, 3, 1) + with_pipe {|r, w| + assert_raise(ArgumentError) { + IO.copy_stream(src, w, 3, 1) + } } end + def test_copy_stream_non_io + mkcdtmpdir {|d| + # filename to StringIO + File.open("foo", "w") {|f| f << "abcd" } + src = "foo" + dst = StringIO.new + ret = IO.copy_stream(src, dst, 3) + assert_equal(3, ret) + assert_equal("abc", dst.string) + + # StringIO to filename + src = StringIO.new("abcd") + ret = File.open("fooo", "w") {|dst| + IO.copy_stream(src, dst, 3) + } + assert_equal(3, ret) + assert_equal("abc", dst.string) + assert_equal(3, src.pos) + + # IO to StringIO + File.open("bar", "w") {|f| f << "abcd" } + File.open("bar") {|src| + dst = StringIO.new + ret = IO.copy_stream(src, dst, 3) + assert_equal(3, ret) + assert_equal("abc", dst.string) + assert_equal(3, src.pos) + } + + # StringIO to IO + src = StringIO.new("abcd") + ret = File.open("baz", "w") {|dst| + IO.copy_stream(src, dst, 3) + } + assert_equal(3, ret) + assert_equal("abc", File.read("baz")) + assert_equal(3, src.pos) + } + end + end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/