sorah_implementation.diff

Shota Fukumori, 05/30/2011 10:57 AM

Download (7.46 KB)

View differences:

io.c
805 805
    long length;
806 806
};
807 807

  
808
struct write_arg {
809
    VALUE io;
810
    VALUE str;
811
    int nosync;
812
};
813

  
808 814
static VALUE
809 815
io_binwrite_string(VALUE arg)
810 816
{
......
8366 8372
    return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
8367 8373
}
8368 8374

  
8375
static VALUE
8376
io_s_write(struct write_arg *arg)
8377
{
8378
    return io_write(arg->io,arg->str,arg->nosync);
8379
}
8380

  
8381
/*
8382
 *  call-seq:
8383
 *     IO.write(name, string, [offset] )   => fixnum
8384
 *     IO.write(name, string, [offset], open_args )   => fixnum
8385
 *
8386
 *  Opens the file, optionally seeks to the given <i>offset</i>, writes
8387
 *  <i>string</i>, then returns the length written.
8388
 *  <code>write</code> ensures the file is closed before returning.
8389
 *  If <i>offset</i> is not given, the file is truncated.  Otherwise,
8390
 *  it is not truncated.
8391
 *
8392
 *  If the last argument is a hash, it specifies option for internal
8393
 *  open().  The key would be the following.  open_args: is exclusive
8394
 *  to others.
8395
 *
8396
 *   encoding: string or encoding
8397
 *
8398
 *    specifies encoding of the read string.  encoding will be ignored
8399
 *    if length is specified.
8400
 *
8401
 *   mode: string
8402
 *
8403
 *    specifies mode argument for open().  it should start with "w" or "a" or "r+"
8404
 *    otherwise it would cause error.
8405
 *
8406
 *   perm: fixnum
8407
 *
8408
 *    specifies perm argument for open().
8409
 *
8410
 *   open_args: array of strings
8411
 *
8412
 *    specifies arguments for open() as an array.
8413
 *
8414
 *     IO.write("testfile", "0123456789")      #=> "0123456789"
8415
 *     IO.write("testfile", "0123456789", 20)  #=> "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
8416
 */
8417

  
8418
static VALUE
8419
rb_io_s_write(int argc, VALUE *argv, VALUE io)
8420
{
8421
    VALUE opt, offset, string;
8422
    struct foreach_arg arg;
8423
    struct write_arg warg;
8424

  
8425
    rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
8426

  
8427
    if(NIL_P(opt)) opt = rb_hash_new();
8428
    else opt = rb_hash_dup(opt);
8429

  
8430
    if(NIL_P(rb_hash_aref(opt,sym_mode))) {
8431
	if(NIL_P(offset)) {
8432
	    rb_hash_aset(opt,sym_mode,INT2NUM(O_WRONLY|O_TRUNC|O_CREAT));
8433
	}else{
8434
	    rb_hash_aset(opt,sym_mode,INT2NUM(O_WRONLY|O_CREAT));
8435
	}
8436
    }
8437

  
8438
    open_key_args(argc,argv,opt,&arg);
8439

  
8440
    if(NIL_P(arg.io)) return Qnil;
8441
    if(!NIL_P(offset)) {
8442
	struct seek_arg sarg;
8443
	int state = 0;
8444
	sarg.io = arg.io;
8445
	sarg.offset = offset;
8446
	sarg.mode = SEEK_SET;
8447
	rb_protect(seek_before_access, (VALUE)&sarg, &state);
8448
	if (state) {
8449
	    rb_io_close(arg.io);
8450
	    rb_jump_tag(state);
8451
	}
8452
    }
8453

  
8454
    warg.io = arg.io;
8455
    warg.str = string;
8456
    warg.nosync = 0;
8457

  
8458
    return rb_ensure(io_s_write, (VALUE)&warg, rb_io_close, arg.io);
8459
}
8460

  
8461
/*
8462
 *  call-seq:
8463
 *     IO.binwrite(name, string, [offset] )   => fixnum
8464
 *
8465
 *  Opens the file, optionally seeks to the given <i>offset</i>, write
8466
 *  <i>string</i> then returns the length written.
8467
 *  <code>binwrite</code> ensures the file is closed before returning.
8468
 *  The open mode would be "wb:ASCII-8BIT".
8469
 *  If <i>offset</i> is not given, the file is truncated.  Otherwise,
8470
 *  it is not truncated.
8471
 *
8472
 *     IO.binwrite("testfile", "0123456789")      #=> "0123456789"
8473
 *     IO.binwrite("testfile", "0123456789", 20)  #=> "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
8474
 */
8475

  
8476
static VALUE
8477
rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
8478
{
8479
    VALUE path, string, offset, mode;
8480
    struct write_arg arg;
8481

  
8482
    rb_scan_args(argc, argv, "21", &path, &string, &offset);
8483

  
8484
#ifdef O_BINARY
8485
    if(NIL_P(offset)){
8486
	mode = INT2NUM(O_WRONLY|O_TRUNC|O_CREAT|O_BINARY);
8487
    }else{
8488
	mode = INT2NUM(O_RDWR|O_CREAT|O_BINARY);
8489
    }
8490
#else
8491
    if(NIL_P(offset)) {
8492
	mode = INT2NUM(O_WRONLY|O_TRUNC|O_CREAT);
8493
    }else{
8494
	mode = INT2NUM(O_RDWR|O_CREAT);
8495
    }
8496
#endif
8497

  
8498
    arg.io = rb_io_open(path,mode,INT2FIX(0666),Qnil);
8499
    arg.str = string;
8500
    arg.nosync = 0;
8501

  
8502
    if(NIL_P(arg.io)) return Qnil;
8503

  
8504
#ifndef O_BINARY
8505
    rb_io_binmode_m(arg.io);
8506
#endif
8507

  
8508
    if(!NIL_P(offset)) {
8509
	struct seek_arg sarg;
8510
	int state = 0;
8511
	sarg.io = arg.io;
8512
	sarg.offset = offset;
8513
	sarg.mode = SEEK_SET;
8514
	rb_protect(seek_before_access, (VALUE)&sarg, &state);
8515
	if (state) {
8516
	    rb_io_close(arg.io);
8517
	    rb_jump_tag(state);
8518
	}
8519
    }
8520

  
8521
    return rb_ensure(io_s_write, (VALUE)&arg, rb_io_close, arg.io);
8522
}
8523

  
8369 8524
struct copy_stream_struct {
8370 8525
    VALUE src;
8371 8526
    VALUE dst;
......
10315 10470
    rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
10316 10471
    rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
10317 10472
    rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
10473
    rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
10474
    rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
10318 10475
    rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
10319 10476
    rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
10320 10477
    rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
test/ruby/test_io.rb
1861 1861
    end
1862 1862
  end
1863 1863

  
1864
  def test_s_write
1865
    t = Tempfile.new("foo")
1866
    path = t.path
1867
    t.close(false)
1868
    File.write(path, "foo\nbar\nbaz")
1869
    assert_equal("foo\nbar\nbaz", File.read(path))
1870
    File.write(path, "FOO", 0)
1871
    assert_equal("FOO\nbar\nbaz", File.read(path))
1872
    File.write(path, "BAR")
1873
    assert_equal("BAR", File.read(path))
1874
    File.write(path, "\u{3042}", mode: "w", encoding: "EUC-JP")
1875
    assert_equal("\u{3042}".encode("EUC-JP"), File.read(path, encoding: "EUC-JP"))
1876
    File.delete t
1877
    assert_equal(6, File.write(path,'string',2))
1878
    File.delete t
1879
    assert_raise(Errno::EINVAL) { File.write('/tmp/nonexisting','string',-2) }
1880
    assert_equal(6, File.write(path, 'string'))
1881
    assert_equal(3, File.write(path, 'sub', 1))
1882
    assert_equal("ssubng", File.read(path))
1883
    File.delete t
1884
    assert_equal(3, File.write(path, "foo", encoding: "UTF-8"))
1885
    File.delete t
1886
    assert_equal(3, File.write(path, "foo", 0, encoding: "UTF-8"))
1887
    assert_equal("foo", File.read(path))
1888
    assert_equal(1, File.write(path, "f", 1, encoding: "UTF-8"))
1889
    assert_equal("ffo", File.read(path))
1890
    File.delete t
1891
    assert_equal(1, File.write(path, "f", 1, encoding: "UTF-8"))
1892
    assert_equal("\00f", File.read(path))
1893
    assert_equal(1, File.write(path, "f", 0, encoding: "UTF-8"))
1894
    assert_equal("ff", File.read(path))
1895
    t.unlink
1896
  end
1897

  
1898
  def test_s_binwrite
1899
    t = Tempfile.new("foo")
1900
    path = t.path
1901
    t.close(false)
1902
    File.binwrite(path, "foo\nbar\nbaz")
1903
    assert_equal("foo\nbar\nbaz", File.read(path))
1904
    File.binwrite(path, "FOO", 0)
1905
    assert_equal("FOO\nbar\nbaz", File.read(path))
1906
    File.binwrite(path, "BAR")
1907
    assert_equal("BAR", File.read(path))
1908
    File.binwrite(path, "\u{3042}")
1909
    assert_equal("\u{3042}".force_encoding("ASCII-8BIT"), File.binread(path))
1910
    File.delete t
1911
    assert_equal(6, File.binwrite(path,'string',2))
1912
    File.delete t
1913
    assert_equal(6, File.binwrite(path, 'string'))
1914
    assert_equal(3, File.binwrite(path, 'sub', 1))
1915
    assert_equal("ssubng", File.binread(path))
1916
    assert_equal(6, File.size(path))
1917
    assert_raise(Errno::EINVAL) { File.binwrite('/tmp/nonexisting','string',-2) }
1918
    assert_raise(TypeError) { File.binwrite(path, "string", mode: "w", encoding: "EUC-JP") }
1919
    t.unlink
1920
  end
1864 1921
end