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

ruby-changes:19855

From: sorah <ko1@a...>
Date: Thu, 2 Jun 2011 16:34:20 +0900 (JST)
Subject: [ruby-changes:19855] sorah:r31902 (trunk): * io.c: Add File.write, File.binwrite. [Feature #1081]

sorah	2011-06-02 16:30:11 +0900 (Thu, 02 Jun 2011)

  New Revision: 31902

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=31902

  Log:
    * io.c: Add File.write, File.binwrite. [Feature #1081] [ruby-core:21701]
    
    * test/ruby/test_io.rb: Test for File.write, File.binwrite.
    
    * NEWS: News for above.

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

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 31901)
+++ ChangeLog	(revision 31902)
@@ -1,3 +1,11 @@
+Thu Jun  2 16:29:34 2011  Shota Fukumori  <sorah@t...>
+
+	* io.c: Add File.write, File.binwrite. [Feature #1081] [ruby-core:21701]
+
+	* test/ruby/test_io.rb: Test for File.write, File.binwrite.
+
+	* NEWS: News for above.
+
 Thu Jun  2 12:33:09 2011  NAKAMURA Usaku  <usa@r...>
 
 	* io.c (io_flush, rb_io_flush): need to fsync() when ruby calls internal
Index: io.c
===================================================================
--- io.c	(revision 31901)
+++ io.c	(revision 31902)
@@ -808,6 +808,12 @@
     long length;
 };
 
+struct write_arg {
+    VALUE io;
+    VALUE str;
+    int nosync;
+};
+
 static VALUE
 io_binwrite_string(VALUE arg)
 {
@@ -8371,6 +8377,124 @@
     return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
 }
 
+static VALUE
+io_s_write0(struct write_arg *arg)
+{
+    return io_write(arg->io,arg->str,arg->nosync);
+}
+
+static VALUE
+io_s_write(int argc, VALUE *argv, int binary)
+{
+    VALUE string, offset, opt;
+    struct foreach_arg arg;
+    struct write_arg warg;
+
+    rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
+
+    if (NIL_P(opt)) opt = rb_hash_new();
+    else opt = rb_hash_dup(opt);
+
+
+    if (NIL_P(rb_hash_aref(opt,sym_mode))) {
+       int mode = O_WRONLY|O_CREAT;
+#ifdef O_BINARY
+       if (binary) mode |= O_BINARY;
+#endif
+       if (NIL_P(offset)) mode |= O_TRUNC;
+       rb_hash_aset(opt,sym_mode,INT2NUM(mode));
+    }
+    open_key_args(argc,argv,opt,&arg);
+
+#ifndef O_BINARY
+    if (binary) rb_io_binmode_m(arg.io);
+#endif
+
+    if (NIL_P(arg.io)) return Qnil;
+    if (!NIL_P(offset)) {
+       struct seek_arg sarg;
+       int state = 0;
+       sarg.io = arg.io;
+       sarg.offset = offset;
+       sarg.mode = SEEK_SET;
+       rb_protect(seek_before_access, (VALUE)&sarg, &state);
+       if (state) {
+           rb_io_close(arg.io);
+           rb_jump_tag(state);
+       }
+    }
+
+    warg.io = arg.io;
+    warg.str = string;
+    warg.nosync = 0;
+
+    return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
+}
+
+/*
+ *  call-seq:
+ *     IO.write(name, string, [offset] )   => fixnum
+ *     IO.write(name, string, [offset], open_args )   => fixnum
+ *
+ *  Opens the file, optionally seeks to the given <i>offset</i>, writes
+ *  <i>string</i>, then returns the length written.
+ *  <code>write</code> ensures the file is closed before returning.
+ *  If <i>offset</i> is not given, the file is truncated.  Otherwise,
+ *  it is not truncated.
+ *
+ *  If the last argument is a hash, it specifies option for internal
+ *  open().  The key would be the following.  open_args: is exclusive
+ *  to others.
+ *
+ *   encoding: string or encoding
+ *
+ *    specifies encoding of the read string.  encoding will be ignored
+ *    if length is specified.
+ *
+ *   mode: string
+ *
+ *    specifies mode argument for open().  it should start with "w" or "a" or "r+"
+ *    otherwise it would cause error.
+ *
+ *   perm: fixnum
+ *
+ *    specifies perm argument for open().
+ *
+ *   open_args: array of strings
+ *
+ *    specifies arguments for open() as an array.
+ *
+ *     IO.write("testfile", "0123456789")      #=> "0123456789"
+ *     IO.write("testfile", "0123456789", 20)  #=> "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
+ */
+
+static VALUE
+rb_io_s_write(int argc, VALUE *argv, VALUE io)
+{
+    io_s_write(argc, argv, 0);
+}
+
+/*
+ *  call-seq:
+ *     IO.binwrite(name, string, [offset] )   => fixnum
+ *
+ *  Opens the file, optionally seeks to the given <i>offset</i>, write
+ *  <i>string</i> then returns the length written.
+ *  <code>binwrite</code> ensures the file is closed before returning.
+ *  The open mode would be "wb:ASCII-8BIT".
+ *  If <i>offset</i> is not given, the file is truncated.  Otherwise,
+ *  it is not truncated.
+ *
+ *     IO.binwrite("testfile", "0123456789")      #=> "0123456789"
+ *     IO.binwrite("testfile", "0123456789", 20)  #=> "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
+ */
+
+static VALUE
+rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
+{
+    io_s_write(argc, argv, 1);
+}
+
 struct copy_stream_struct {
     VALUE src;
     VALUE dst;
@@ -10320,6 +10444,8 @@
     rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
     rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
     rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
+    rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
+    rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
     rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
     rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
     rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
Index: NEWS
===================================================================
--- NEWS	(revision 31901)
+++ NEWS	(revision 31902)
@@ -57,8 +57,13 @@
   * IO
     * extended method:
       * IO#putc supports multibyte characters
-    * new method:
+    * new methods:
       * IO#advise
+      * IO.write(name, string, [offset] )
+        Write `string` to file `name`.
+        Opposite with File.read.
+      * IO.binwrite(name, string, [offset] )
+        binary virsion of IO.write.
 
   * Kernel
     * Kernel#respond_to? now returns false for protected methods.
Index: test/ruby/test_io.rb
===================================================================
--- test/ruby/test_io.rb	(revision 31901)
+++ test/ruby/test_io.rb	(revision 31902)
@@ -1865,4 +1865,61 @@
     end
   end
 
+  def test_s_write
+    t = Tempfile.new("foo")
+    path = t.path
+    t.close(false)
+    File.write(path, "foo\nbar\nbaz")
+    assert_equal("foo\nbar\nbaz", File.read(path))
+    File.write(path, "FOO", 0)
+    assert_equal("FOO\nbar\nbaz", File.read(path))
+    File.write(path, "BAR")
+    assert_equal("BAR", File.read(path))
+    File.write(path, "\u{3042}", mode: "w", encoding: "EUC-JP")
+    assert_equal("\u{3042}".encode("EUC-JP"), File.read(path, encoding: "EUC-JP"))
+    File.delete t
+    assert_equal(6, File.write(path,'string',2))
+    File.delete t
+    assert_raise(Errno::EINVAL) { File.write('/tmp/nonexisting','string',-2) }
+    assert_equal(6, File.write(path, 'string'))
+    assert_equal(3, File.write(path, 'sub', 1))
+    assert_equal("ssubng", File.read(path))
+    File.delete t
+    assert_equal(3, File.write(path, "foo", encoding: "UTF-8"))
+    File.delete t
+    assert_equal(3, File.write(path, "foo", 0, encoding: "UTF-8"))
+    assert_equal("foo", File.read(path))
+    assert_equal(1, File.write(path, "f", 1, encoding: "UTF-8"))
+    assert_equal("ffo", File.read(path))
+    File.delete t
+    assert_equal(1, File.write(path, "f", 1, encoding: "UTF-8"))
+    assert_equal("\00f", File.read(path))
+    assert_equal(1, File.write(path, "f", 0, encoding: "UTF-8"))
+    assert_equal("ff", File.read(path))
+    t.unlink
+  end
+
+  def test_s_binwrite
+    t = Tempfile.new("foo")
+    path = t.path
+    t.close(false)
+    File.binwrite(path, "foo\nbar\nbaz")
+    assert_equal("foo\nbar\nbaz", File.read(path))
+    File.binwrite(path, "FOO", 0)
+    assert_equal("FOO\nbar\nbaz", File.read(path))
+    File.binwrite(path, "BAR")
+    assert_equal("BAR", File.read(path))
+    File.binwrite(path, "\u{3042}")
+    assert_equal("\u{3042}".force_encoding("ASCII-8BIT"), File.binread(path))
+    File.delete t
+    assert_equal(6, File.binwrite(path,'string',2))
+    File.delete t
+    assert_equal(6, File.binwrite(path, 'string'))
+    assert_equal(3, File.binwrite(path, 'sub', 1))
+    assert_equal("ssubng", File.binread(path))
+    assert_equal(6, File.size(path))
+    assert_raise(Errno::EINVAL) { File.binwrite('/tmp/nonexisting','string',-2) }
+    assert_nothing_raised(TypeError) { File.binwrite(path, "string", mode: "w", encoding: "EUC-JP") }
+    t.unlink
+  end
 end

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

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