* io.c (copy_stream_fallback): read directly (bypassing readpartial)

if possible.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16088 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2008-04-20 03:51:57 +00:00
parent 9579647fe1
commit a16e0c29db
3 changed files with 126 additions and 56 deletions

View File

@ -1,3 +1,8 @@
Sun Apr 20 12:49:03 2008 Tanaka Akira <akr@fsij.org>
* io.c (copy_stream_fallback): read directly (bypassing readpartial)
if possible.
Sun Apr 20 04:45:13 2008 Tanaka Akira <akr@fsij.org> Sun Apr 20 04:45:13 2008 Tanaka Akira <akr@fsij.org>
* io.c (copy_stream_body): use readpartial and write method for * io.c (copy_stream_body): use readpartial and write method for

64
io.c
View File

@ -6574,34 +6574,49 @@ copy_stream_fallback_body(VALUE arg)
const int buflen = 16*1024; const int buflen = 16*1024;
VALUE n; VALUE n;
VALUE buf = rb_str_buf_new(buflen); VALUE buf = rb_str_buf_new(buflen);
if (stp->copy_length == (off_t)-1) { long rest = stp->copy_length;
off_t off = stp->src_offset;
while (1) { while (1) {
rb_funcall(stp->src, id_readpartial, long numwrote;
2, INT2FIX(buflen), buf); long l = buflen < rest ? buflen : rest;
n = rb_io_write(stp->dst, buf); if (stp->copy_length == (off_t)-1) {
stp->total += NUM2LONG(n); l = buflen;
}
} }
else { else {
long rest = stp->copy_length; if (rest == 0)
while (0 < rest) { break;
long l = buflen < rest ? buflen : rest; l = buflen < rest ? buflen : rest;
long numwrote; }
if (stp->src_fd == -1) {
rb_funcall(stp->src, id_readpartial, rb_funcall(stp->src, id_readpartial,
2, INT2FIX(l), buf); 2, INT2FIX(l), buf);
}
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); n = rb_io_write(stp->dst, buf);
numwrote = NUM2LONG(n); numwrote = NUM2LONG(n);
stp->total += numwrote; stp->total += numwrote;
rest -= numwrote; rest -= numwrote;
} }
}
return Qnil; return Qnil;
} }
static VALUE static VALUE
copy_stream_fallback(struct copy_stream_struct *stp) 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_raise(rb_eArgError, "cannot specify src_offset");
} }
rb_rescue2(copy_stream_fallback_body, (VALUE)stp, rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
@ -6624,18 +6639,13 @@ copy_stream_body(VALUE arg)
stp->total = 0; stp->total = 0;
if (stp->src == argf || if (stp->src == argf ||
stp->dst == argf ||
!(TYPE(stp->src) == T_FILE || !(TYPE(stp->src) == T_FILE ||
rb_respond_to(stp->src, rb_intern("to_io")) || rb_respond_to(stp->src, rb_intern("to_io")) ||
TYPE(stp->src) == T_STRING || TYPE(stp->src) == T_STRING ||
rb_respond_to(stp->src, rb_intern("to_path"))) || rb_respond_to(stp->src, rb_intern("to_path")))) {
!(TYPE(stp->dst) == T_FILE || src_fd = -1;
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);
} }
else {
src_io = rb_check_convert_type(stp->src, T_FILE, "IO", "to_io"); src_io = rb_check_convert_type(stp->src, T_FILE, "IO", "to_io");
if (!NIL_P(src_io)) { if (!NIL_P(src_io)) {
GetOpenFile(src_io, src_fptr); GetOpenFile(src_io, src_fptr);
@ -6653,8 +6663,17 @@ copy_stream_body(VALUE arg)
if (src_fd == -1) { rb_sys_fail(src_path); } if (src_fd == -1) { rb_sys_fail(src_path); }
stp->close_src = 1; stp->close_src = 1;
} }
}
stp->src_fd = src_fd; stp->src_fd = src_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_io = rb_check_convert_type(stp->dst, T_FILE, "IO", "to_io"); dst_io = rb_check_convert_type(stp->dst, T_FILE, "IO", "to_io");
if (!NIL_P(dst_io)) { if (!NIL_P(dst_io)) {
dst_io = GetWriteIO(dst_io); dst_io = GetWriteIO(dst_io);
@ -6673,8 +6692,13 @@ copy_stream_body(VALUE arg)
if (dst_fd == -1) { rb_sys_fail(dst_path); } if (dst_fd == -1) { rb_sys_fail(dst_path); }
stp->close_dst = 1; stp->close_dst = 1;
} }
}
stp->dst_fd = dst_fd; 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) { if (src_fptr && dst_fptr && src_fptr->rbuf_len && dst_fptr->wbuf_len) {
long len = src_fptr->rbuf_len; long len = src_fptr->rbuf_len;
VALUE str; VALUE str;

View File

@ -417,9 +417,50 @@ class TestIO < Test::Unit::TestCase
def test_copy_stream_strio_off def test_copy_stream_strio_off
src = StringIO.new("abcd") src = StringIO.new("abcd")
dst = StringIO.new with_pipe {|r, w|
assert_raise(ArgumentError) { assert_raise(ArgumentError) {
IO.copy_stream(src, dst, 3, 1) 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