summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-04-20 03:51:57 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-04-20 03:51:57 +0000
commit2486fe540072d78ab04703dde94722dfdca618ae (patch)
treec1e4fdd6a6d87e317e93ac513f16a382ee5cd399
parent62ecf80478cb6c5162d1445be6c2d1d1aac86171 (diff)
downloadruby-2486fe540072d78ab04703dde94722dfdca618ae.tar.gz
ruby-2486fe540072d78ab04703dde94722dfdca618ae.tar.xz
ruby-2486fe540072d78ab04703dde94722dfdca618ae.zip
* io.c (copy_stream_fallback): read directly (bypassing readpartial)
if possible. git-svn-id: http://svn.ruby-lang.org/repos/ruby/trunk@16088 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--io.c122
-rw-r--r--test/ruby/test_io.rb47
3 files changed, 122 insertions, 52 deletions
diff --git a/ChangeLog b/ChangeLog
index 492aee213..7cda15be3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
* io.c (copy_stream_body): use readpartial and write method for
diff --git a/io.c b/io.c
index fa8246cf0..363843cee 100644
--- a/io.c
+++ b/io.c
@@ -6574,34 +6574,49 @@ copy_stream_fallback_body(VALUE arg)
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 @@ copy_stream_body(VALUE arg)
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);
- }
-
- 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;
+ rb_respond_to(stp->src, rb_intern("to_path")))) {
+ src_fd = -1;
}
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;
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index d2292446f..1fa164566 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -417,9 +417,50 @@ class TestIO < Test::Unit::TestCase
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