Project

General

Profile

Feature #1081 » latest.diff

rogerdpack (Roger Pack), 04/30/2010 02:32 AM

View differences:

io.c (working copy)
};
static void
open_key_args(int argc, VALUE *argv, struct foreach_arg *arg)
open_key_args_with_opt(int argc, VALUE *argv, struct foreach_arg *arg, int mandatory_argc, int default_mode, int default_perm)
{
VALUE opt, v;
......
arg->io = 0;
arg->argc = argc - 1;
arg->argv = argv + 1;
if (argc == 1) {
if (argc == mandatory_argc) {
no_key:
arg->io = rb_io_open(argv[0], INT2NUM(O_RDONLY), INT2FIX(0666), Qnil);
arg->io = rb_io_open(argv[0], INT2NUM(default_mode), INT2FIX(default_perm), Qnil);
return;
}
opt = pop_last_hash(&arg->argc, arg->argv);
......
rb_ary_clear(args); /* prevent from GC */
return;
}
if (default_mode != O_RDONLY && NIL_P(rb_hash_aref(opt, sym_mode))) {
opt = rb_hash_dup(opt);
rb_hash_aset(opt, sym_mode, INT2NUM(default_mode));
}
if (default_perm != 0666 && NIL_P(rb_hash_aref(opt, sym_perm))) {
opt = rb_hash_dup(opt);
rb_hash_aset(opt, sym_perm, INT2FIX(default_perm));
}
arg->io = rb_io_open(argv[0], Qnil, Qnil, opt);
}
static void
open_key_args(int argc, VALUE *argv, struct foreach_arg *arg)
{
open_key_args_with_opt(argc, argv, arg, 1, O_RDONLY, 0666);
}
static VALUE
io_s_foreach(struct foreach_arg *arg)
{
......
return io_read(arg->argc, arg->argv, arg->io);
}
struct write_arg {
VALUE io, str;
};
static VALUE
io_s_write(struct write_arg *arg)
{
return io_write(arg->io, arg->str, 0);
}
struct seek_arg {
VALUE io;
VALUE offset;
......
return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}
static VALUE rb_io_s_write_helper(int argc, VALUE *argv, VALUE io, int use_binary);
/*
* 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)
{
return rb_io_s_write_helper(argc, argv, io, 0);
}
static VALUE
rb_io_s_write_helper(int argc, VALUE *argv, VALUE io, int use_binary)
{
VALUE offset;
struct foreach_arg arg;
struct write_arg warg;
int mode = O_WRONLY | O_CREAT, mandatory_argc;
#ifdef O_BINARY
if(use_binary)
mode |= O_BINARY;
#endif
rb_scan_args(argc, argv, "22", NULL, &warg.str, &offset, NULL);
if (!NIL_P(offset) && FIXNUM_P(offset)) {
mandatory_argc = 3;
}
else {
mode |= O_TRUNC;
mandatory_argc = 2;
}
open_key_args_with_opt(argc, argv, &arg, mandatory_argc, mode, 0666);
if (NIL_P(arg.io)) return Qnil;
if (!NIL_P(offset) && FIXNUM_P(offset)) {
struct seek_arg sarg;
int state = 0;
sarg.io = arg.io;
sarg.offset = offset;
sarg.mode = SEEK_SET;
rb_protect((VALUE (*)(VALUE))seek_before_access, (VALUE)&sarg, &state);
if (state) {
rb_io_close(arg.io);
rb_jump_tag(state);
}
if (arg.argc == 2) arg.argc = 1;
}
warg.io = arg.io;
return rb_ensure(io_s_write, (VALUE)&warg, rb_io_close, arg.io);
}
/*
* 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)
{
return rb_io_s_write_helper(argc, argv, io, 1);
}
struct copy_stream_struct {
VALUE src;
VALUE dst;
......
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);
test/ruby/test_io.rb (working copy)
t.close
assert_raise(IOError) {t.binmode}
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))
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) }
t.unlink
end
end
(3-3/6)