[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]