summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--NEWS5
-rw-r--r--io.c39
-rw-r--r--test/ruby/test_argf.rb43
4 files changed, 85 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 51406d4c9b..7a4f14b61e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Sat Jul 18 02:53:06 2015 Eric Wong <e@80x24.org>
+
+ * io.c (argf_read_nonblock): support `exception: false'
+ (io_nonblock_eof): new function
+ (io_read_nonblock): use io_nonblock_eof
+ (argf_getpartial): accept kwargs hash for `exception: false'
+ * test/ruby/test_argf.rb (test_read_nonblock): new test
+ * NEWS: add item for ARGF.read_nonblock
+ [ruby-core:70000] [Feature #11358]
+
Fri Jul 17 23:51:31 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* vm_eval.c (rb_eval_cmd): $SAFE=4 has been deprecated.
diff --git a/NEWS b/NEWS
index f4b4b78539..62ddaece45 100644
--- a/NEWS
+++ b/NEWS
@@ -35,6 +35,11 @@ with all sufficient information, see the ChangeLog file.
true when the receiver is positive and negative respectively.
[Feature #11151]
+* ARGF
+
+ * ARGF.read_nonblock supports `exception: false' like IO#read_nonblock.
+ [Feature #11358]
+
* IO
* new mode flag File::SHARE_DELETE is available.
diff --git a/io.c b/io.c
index ca625008c6..3616d0a66b 100644
--- a/io.c
+++ b/io.c
@@ -2619,6 +2619,15 @@ io_readpartial(int argc, VALUE *argv, VALUE io)
return ret;
}
+static VALUE
+io_nonblock_eof(VALUE opts)
+{
+ if (!no_exception_p(opts)) {
+ rb_eof_error();
+ }
+ return Qnil;
+}
+
/*
* call-seq:
* ios.read_nonblock(maxlen) -> string
@@ -2680,10 +2689,7 @@ io_read_nonblock(int argc, VALUE *argv, VALUE io)
ret = io_getpartial(argc, argv, io, opts, 1);
if (NIL_P(ret)) {
- if (no_exception_p(opts))
- return Qnil;
- else
- rb_eof_error();
+ return io_nonblock_eof(opts);
}
return ret;
}
@@ -11139,7 +11145,8 @@ argf_forward_call(VALUE arg)
return Qnil;
}
-static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock);
+static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts,
+ int nonblock);
/*
* call-seq:
@@ -11164,7 +11171,7 @@ static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock);
static VALUE
argf_readpartial(int argc, VALUE *argv, VALUE argf)
{
- return argf_getpartial(argc, argv, argf, 0);
+ return argf_getpartial(argc, argv, argf, Qnil, 0);
}
/*
@@ -11178,11 +11185,18 @@ argf_readpartial(int argc, VALUE *argv, VALUE argf)
static VALUE
argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
{
- return argf_getpartial(argc, argv, argf, 1);
+ VALUE opts;
+
+ rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
+
+ if (!NIL_P(opts))
+ argc--;
+
+ return argf_getpartial(argc, argv, argf, opts, 1);
}
static VALUE
-argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock)
+argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
{
VALUE tmp, str, length;
@@ -11205,16 +11219,17 @@ argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock)
RUBY_METHOD_FUNC(0), Qnil, rb_eEOFError, (VALUE)0);
}
else {
- tmp = io_getpartial(argc, argv, ARGF.current_file, Qnil, nonblock);
+ tmp = io_getpartial(argc, argv, ARGF.current_file, opts, nonblock);
}
if (NIL_P(tmp)) {
if (ARGF.next_p == -1) {
- rb_eof_error();
+ return io_nonblock_eof(opts);
}
argf_close(argf);
ARGF.next_p = 1;
- if (RARRAY_LEN(ARGF.argv) == 0)
- rb_eof_error();
+ if (RARRAY_LEN(ARGF.argv) == 0) {
+ return io_nonblock_eof(opts);
+ }
if (NIL_P(str))
str = rb_str_new(NULL, 0);
return str;
diff --git a/test/ruby/test_argf.rb b/test/ruby/test_argf.rb
index 6975b83a28..a9ba9f64e2 100644
--- a/test/ruby/test_argf.rb
+++ b/test/ruby/test_argf.rb
@@ -856,4 +856,47 @@ class TestArgf < Test::Unit::TestCase
assert_equal([49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10], Marshal.load(f.read))
end
end
+
+ def test_read_nonblock
+ ruby('-e', <<-SRC) do |f|
+ $stdout.sync = true
+ :wait_readable == ARGF.read_nonblock(1, "", exception: false) or
+ abort "did not return :wait_readable"
+
+ begin
+ ARGF.read_nonblock(1)
+ abort 'fail to raise IO::WaitReadable'
+ rescue IO::WaitReadable
+ end
+ puts 'starting select'
+
+ IO.select([ARGF]) == [[ARGF], [], []] or
+ abort 'did not awaken for readability (before byte)'
+
+ buf = ''
+ buf.object_id == ARGF.read_nonblock(1, buf).object_id or
+ abort "read destination buffer failed"
+ print buf
+
+ IO.select([ARGF]) == [[ARGF], [], []] or
+ abort 'did not awaken for readability (before EOF)'
+
+ ARGF.read_nonblock(1, buf, exception: false) == nil or
+ abort "EOF should return nil if exception: false"
+
+ begin
+ ARGF.read_nonblock(1, buf)
+ abort 'fail to raise IO::WaitReadable'
+ rescue EOFError
+ puts 'done with eof'
+ end
+ SRC
+ f.sync = true
+ assert_equal "starting select\n", f.gets
+ f.write('.') # wake up from IO.select
+ assert_equal '.', f.read(1)
+ f.close_write
+ assert_equal "done with eof\n", f.gets
+ end
+ end
end