diff options
| author | ksss <[email protected]> | 2017-12-17 14:50:43 +0900 |
|---|---|---|
| committer | ksss <[email protected]> | 2017-12-17 18:02:37 +0900 |
| commit | 35185e69bff725e0f11d49db9b2793185fe9927f (patch) | |
| tree | 93c0a3f5fdb0a012a697e429ad535645d508fa1c | |
| parent | ddb1aae41de507efb9ab3d7ec2edb23911888783 (diff) | |
| download | mruby-35185e69bff725e0f11d49db9b2793185fe9927f.tar.gz mruby-35185e69bff725e0f11d49db9b2793185fe9927f.zip | |
Implement IO#initialize_copy
| -rw-r--r-- | mrbgems/mruby-io/README.md | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-io/src/io.c | 49 | ||||
| -rw-r--r-- | mrbgems/mruby-io/test/io.rb | 29 |
3 files changed, 79 insertions, 1 deletions
diff --git a/mrbgems/mruby-io/README.md b/mrbgems/mruby-io/README.md index 0f50e24ec..256fb8195 100644 --- a/mrbgems/mruby-io/README.md +++ b/mrbgems/mruby-io/README.md @@ -40,7 +40,7 @@ Add the line below to your `build_config.rb`: | IO#binmode? | | | | IO#bytes | | obsolete | | IO#chars | | obsolete | -| IO#clone, IO#dup | | | +| IO#clone, IO#dup | o | | | IO#close | o | | | IO#close_on_exec= | o | | | IO#close_on_exec? | o | | diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index afd6dc7c3..643671d1e 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -530,6 +530,54 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass) } #endif +static int +mrb_dup(mrb_state *mrb, int fd) +{ + int new_fd; + + if (fd < 0) + return fd; + + new_fd = dup(fd); + if (new_fd == -1) + mrb_sys_fail(mrb, 0); + return new_fd; +} + +mrb_value +mrb_io_initialize_copy(mrb_state *mrb, mrb_value copy) +{ + mrb_value orig; + mrb_value buf; + struct mrb_io *fptr_copy; + struct mrb_io *fptr_orig; + + mrb_get_args(mrb, "o", &orig); + fptr_copy = (struct mrb_io *)DATA_PTR(copy); + if (fptr_copy != NULL) { + fptr_finalize(mrb, fptr_copy, FALSE); + mrb_free(mrb, fptr_copy); + } + fptr_copy = (struct mrb_io *)mrb_io_alloc(mrb); + fptr_orig = io_get_open_fptr(mrb, orig); + + buf = mrb_iv_get(mrb, orig, mrb_intern_cstr(mrb, "@buf")); + mrb_iv_set(mrb, copy, mrb_intern_cstr(mrb, "@buf"), buf); + + fptr_copy->fd = mrb_dup(mrb, fptr_orig->fd); + fptr_copy->fd2 = mrb_dup(mrb, fptr_orig->fd2); + fptr_copy->pid = fptr_orig->pid; + fptr_copy->readable = fptr_orig->readable; + fptr_copy->writable = fptr_orig->writable; + fptr_copy->sync = fptr_orig->sync; + fptr_copy->is_socket = fptr_orig->is_socket; + + DATA_TYPE(copy) = &mrb_io_type; + DATA_PTR(copy) = fptr_copy; + + return copy; +} + mrb_value mrb_io_initialize(mrb_state *mrb, mrb_value io) { @@ -1238,6 +1286,7 @@ mrb_init_io(mrb_state *mrb) #endif mrb_define_method(mrb, io, "initialize", mrb_io_initialize, MRB_ARGS_ANY()); /* 15.2.20.5.21 (x)*/ + mrb_define_method(mrb, io, "initialize_copy", mrb_io_initialize_copy, MRB_ARGS_REQ(1)); mrb_define_method(mrb, io, "_check_readable", mrb_io_check_readable, MRB_ARGS_NONE()); mrb_define_method(mrb, io, "isatty", mrb_io_isatty, MRB_ARGS_NONE()); mrb_define_method(mrb, io, "sync", mrb_io_sync, MRB_ARGS_NONE()); diff --git a/mrbgems/mruby-io/test/io.rb b/mrbgems/mruby-io/test/io.rb index 9a6328ea4..96c3495d0 100644 --- a/mrbgems/mruby-io/test/io.rb +++ b/mrbgems/mruby-io/test/io.rb @@ -211,6 +211,35 @@ assert('IO#<<') do true end +assert('IO#dup for readable') do + io = IO.new(IO.sysopen($mrbtest_io_rfname)) + dup = io.dup + assert_true io != dup + assert_true io.fileno != dup.fileno + assert_equal 'm', dup.sysread(1) + assert_equal 'r', io.sysread(1) + assert_equal 'u', dup.sysread(1) + assert_equal 'b', io.sysread(1) + assert_equal 'y', dup.sysread(1) + dup.close + assert_false io.closed? + io.close + true +end + +assert('IO#dup for writable') do + io = IO.open(IO.sysopen($mrbtest_io_wfname, 'w+'), 'w+') + dup = io.dup + io.syswrite "mruby" + assert_equal 5, dup.sysseek(0, IO::SEEK_CUR) + io.sysseek 0, IO::SEEK_SET + assert_equal 0, dup.sysseek(0, IO::SEEK_CUR) + assert_equal "mruby", dup.sysread(5) + dup.close + io.close + true +end + assert('IO.for_fd') do fd = IO.sysopen($mrbtest_io_rfname) io = IO.for_fd(fd) |
