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

ruby-changes:4593

From: ko1@a...
Date: Sun, 20 Apr 2008 04:47:37 +0900 (JST)
Subject: [ruby-changes:4593] akr - Ruby:r16087 (trunk): * io.c (copy_stream_body): use readpartial and write method for

akr	2008-04-20 04:47:16 +0900 (Sun, 20 Apr 2008)

  New Revision: 16087

  Modified files:
    trunk/ChangeLog
    trunk/io.c
    trunk/test/ruby/test_io.rb

  Log:
    * io.c (copy_stream_body): use readpartial and write method for
      non-IOs such as StringIO and ARGF.


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/test/ruby/test_io.rb?r1=16087&r2=16086&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=16087&r2=16086&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/io.c?r1=16087&r2=16086&diff_format=u

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 16086)
+++ ChangeLog	(revision 16087)
@@ -1,3 +1,8 @@
+Sun Apr 20 04:45:13 2008  Tanaka Akira  <akr@f...>
+
+	* io.c (copy_stream_body): use readpartial and write method for
+	  non-IOs such as StringIO and ARGF.
+
 Fri Apr 18 20:57:33 2008  Yusuke Endoh  <mame@t...>
 
 	* test/ruby/test_array.rb: add tests to achieve over 95% test coverage
Index: io.c
===================================================================
--- io.c	(revision 16086)
+++ io.c	(revision 16087)
@@ -124,7 +124,7 @@
 
 static VALUE argf;
 
-static ID id_write, id_read, id_getc, id_flush, id_encode;
+static ID id_write, id_read, id_getc, id_flush, id_encode, id_readpartial;
 
 struct timeval rb_time_interval(VALUE);
 
@@ -6250,10 +6250,11 @@
 struct copy_stream_struct {
     VALUE src;
     VALUE dst;
+    off_t copy_length; /* (off_t)-1 if not specified */
+    off_t src_offset; /* (off_t)-1 if not specified */
+
     int src_fd;
     int dst_fd;
-    off_t copy_length;
-    off_t src_offset;
     int close_src;
     int close_dst;
     off_t total;
@@ -6567,6 +6568,49 @@
 }
 
 static VALUE
+copy_stream_fallback_body(VALUE arg)
+{
+    struct copy_stream_struct *stp = (struct copy_stream_struct *)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);
+        }
+    }
+    else {
+        long rest = stp->copy_length;
+        while (0 < rest) {
+            long l = buflen < rest ? buflen : rest;
+            long numwrote;
+            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;
+        }
+    }
+    return Qnil;
+}
+
+static VALUE
+copy_stream_fallback(struct copy_stream_struct *stp)
+{
+    if (stp->src_offset != (off_t)-1) {
+	rb_raise(rb_eArgError, "cannot specify src_offset");
+    }
+    rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
+               (VALUE (*) (ANYARGS))0, (VALUE)0,
+               rb_eEOFError, (VALUE)0);
+    return Qnil;
+}
+
+static VALUE
 copy_stream_body(VALUE arg)
 {
     struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
@@ -6577,6 +6621,21 @@
 
     stp->th = GET_THREAD();
 
+    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);
@@ -6616,8 +6675,6 @@
     }
     stp->dst_fd = dst_fd;
 
-    stp->total = 0;
-
     if (src_fptr && dst_fptr && src_fptr->rbuf_len && dst_fptr->wbuf_len) {
         long len = src_fptr->rbuf_len;
         VALUE str;
@@ -6708,6 +6765,9 @@
 
     rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
 
+    st.src = src;
+    st.dst = dst;
+
     if (NIL_P(length))
         st.copy_length = (off_t)-1;
     else
@@ -6718,9 +6778,6 @@
     else
         st.src_offset = NUM2OFFT(src_offset);
 
-    st.src = src;
-    st.dst = dst;
-
     rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
 
     return OFFT2NUM(st.total);
@@ -7344,6 +7401,7 @@
     id_getc = rb_intern("getc");
     id_flush = rb_intern("flush");
     id_encode = rb_intern("encode");
+    id_readpartial = rb_intern("readpartial");
 
     rb_define_global_function("syscall", rb_f_syscall, -1);
 
Index: test/ruby/test_io.rb
===================================================================
--- test/ruby/test_io.rb	(revision 16086)
+++ test/ruby/test_io.rb	(revision 16087)
@@ -2,6 +2,7 @@
 require 'tmpdir'
 require 'io/nonblock'
 require 'socket'
+require 'stringio'
 
 class TestIO < Test::Unit::TestCase
   def test_gets_rs
@@ -393,8 +394,33 @@
         result = t.value
         assert_equal(megacontent, result)
       }
+    }
+  end
 
+  def test_copy_stream_strio
+    src = StringIO.new("abcd")
+    dst = StringIO.new
+    ret = IO.copy_stream(src, dst)
+    assert_equal(4, ret)
+    assert_equal("abcd", dst.string)
+    assert_equal(4, src.pos)
+  end
 
+  def test_copy_stream_strio_len
+    src = StringIO.new("abcd")
+    dst = StringIO.new
+    ret = IO.copy_stream(src, dst, 3)
+    assert_equal(3, ret)
+    assert_equal("abc", dst.string)
+    assert_equal(3, src.pos)
+  end
+
+  def test_copy_stream_strio_off
+    src = StringIO.new("abcd")
+    dst = StringIO.new
+    assert_raise(ArgumentError) {
+      IO.copy_stream(src, dst, 3, 1)
     }
   end
+
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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