* io.c (read_buffered_data): extracted from rb_io_fread.
(io_readpartial): new method IO#readpartial. [ruby-dev:24055] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6756 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
9492165db2
commit
8f8de7782e
@ -1,3 +1,9 @@
|
|||||||
|
Thu Aug 12 01:53:10 2004 Tanaka Akira <akr@m17n.org>
|
||||||
|
|
||||||
|
* io.c (read_buffered_data): extracted from rb_io_fread.
|
||||||
|
(io_readpartial): new method IO#readpartial.
|
||||||
|
[ruby-dev:24055]
|
||||||
|
|
||||||
Wed Aug 11 17:17:50 2004 WATANABE Hirofumi <eban@ruby-lang.org>
|
Wed Aug 11 17:17:50 2004 WATANABE Hirofumi <eban@ruby-lang.org>
|
||||||
|
|
||||||
* configure.in (RPATHFLAG): stop setting RPATHFLAG on Interix.
|
* configure.in (RPATHFLAG): stop setting RPATHFLAG on Interix.
|
||||||
|
157
io.c
157
io.c
@ -907,6 +907,27 @@ rb_io_to_io(io)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* reading functions */
|
/* reading functions */
|
||||||
|
static long
|
||||||
|
read_buffered_data(ptr, len, f)
|
||||||
|
char *ptr;
|
||||||
|
long len;
|
||||||
|
FILE *f;
|
||||||
|
{
|
||||||
|
long n;
|
||||||
|
|
||||||
|
#ifdef READ_DATA_PENDING_COUNT
|
||||||
|
n = READ_DATA_PENDING_COUNT(f);
|
||||||
|
if (n <= 0) return 0;
|
||||||
|
if (n > len) n = len;
|
||||||
|
return fread(ptr, 1, n, f);
|
||||||
|
#else
|
||||||
|
for (n = 0; n < len && READ_DATA_PENDING(f); ++n) {
|
||||||
|
*ptr++ = getc(f);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
long
|
long
|
||||||
rb_io_fread(ptr, len, f)
|
rb_io_fread(ptr, len, f)
|
||||||
char *ptr;
|
char *ptr;
|
||||||
@ -917,28 +938,12 @@ rb_io_fread(ptr, len, f)
|
|||||||
int c;
|
int c;
|
||||||
|
|
||||||
while (n > 0) {
|
while (n > 0) {
|
||||||
#ifdef READ_DATA_PENDING_COUNT
|
c = read_buffered_data(ptr, n, f);
|
||||||
long i = READ_DATA_PENDING_COUNT(f);
|
if (c < 0) goto eof;
|
||||||
if (i <= 0) {
|
if (c > 0) {
|
||||||
rb_thread_wait_fd(fileno(f));
|
|
||||||
i = READ_DATA_PENDING_COUNT(f);
|
|
||||||
}
|
|
||||||
if (i > 0) {
|
|
||||||
if (i > n) i = n;
|
|
||||||
TRAP_BEG;
|
|
||||||
c = fread(ptr, 1, i, f);
|
|
||||||
TRAP_END;
|
|
||||||
if (c < 0) goto eof;
|
|
||||||
ptr += c;
|
ptr += c;
|
||||||
n -= c;
|
if ((n -= c) <= 0) break;
|
||||||
if (c < i) goto eof;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if (!READ_DATA_PENDING(f)) {
|
|
||||||
rb_thread_wait_fd(fileno(f));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
TRAP_BEG;
|
TRAP_BEG;
|
||||||
c = getc(f);
|
c = getc(f);
|
||||||
TRAP_END;
|
TRAP_END;
|
||||||
@ -1040,6 +1045,113 @@ read_all(fptr, siz, str)
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* ios.readpartial(integer[, outbuf]) => string, outbuf
|
||||||
|
*
|
||||||
|
* Reads at most <i>integer</i> bytes from the I/O stream but
|
||||||
|
* it blocks only if <em>ios</em> has no data immediately available.
|
||||||
|
* If the optional <i>outbuf</i> argument is present,
|
||||||
|
* it must reference a String, which will receive the data.
|
||||||
|
* It raises <code>EOFError</code> on end of file.
|
||||||
|
*
|
||||||
|
* readpartial is designed for streams such as pipe, socket, etc.
|
||||||
|
* It blocks only when no data immediately available.
|
||||||
|
* This means that it blocks only when following all conditions hold.
|
||||||
|
* * the stdio buffer in the IO object is empty.
|
||||||
|
* * the content of the stream is empty.
|
||||||
|
* * the stream is not reached to EOF.
|
||||||
|
*
|
||||||
|
* When readpartial blocks, it waits data or EOF on the stream.
|
||||||
|
* If some data is reached, readpartial returns with the data.
|
||||||
|
* If EOF is reached, readpartial raises EOFError.
|
||||||
|
*
|
||||||
|
* When readpartial doesn't blocks, it returns or raises immediately.
|
||||||
|
* If the stdio buffer is not empty, it returns the data in the buffer.
|
||||||
|
* Otherwise if the stream has some content,
|
||||||
|
* it returns the data in the stream.
|
||||||
|
* Otherwise if the stream is reached to EOF, it raises EOFError.
|
||||||
|
*
|
||||||
|
* r, w = IO.pipe # stdio buffer pipe content
|
||||||
|
* w << "abc" # "" "abc".
|
||||||
|
* r.readpartial(4096) #=> "abc" "" ""
|
||||||
|
* r.readpartial(4096) # blocks because buffer and pipe is empty.
|
||||||
|
*
|
||||||
|
* r, w = IO.pipe # stdio buffer pipe content
|
||||||
|
* w << "abc" # "" "abc"
|
||||||
|
* w.close # "" "abc" EOF
|
||||||
|
* r.readpartial(4096) #=> "abc" "" EOF
|
||||||
|
* r.readpartial(4096) # raises EOFError
|
||||||
|
*
|
||||||
|
* r, w = IO.pipe # stdio buffer pipe content
|
||||||
|
* w << "abc\ndef\n" # "" "abc\ndef\n"
|
||||||
|
* r.gets #=> "abc\n" "def\n" ""
|
||||||
|
* w << "ghi\n" # "def\n" "ghi\n"
|
||||||
|
* r.readpartial(4096) #=> "def\n" "" "ghi\n"
|
||||||
|
* r.readpartial(4096) #=> "ghi\n" "" ""
|
||||||
|
*
|
||||||
|
* Note that readpartial is nonblocking-flag insensitive.
|
||||||
|
* It blocks even if the nonblocking-flag is set.
|
||||||
|
*
|
||||||
|
* Also note that readpartial behaves similar to sysread in blocking mode.
|
||||||
|
* The behavior is identical when the stdio buffer is empty.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
io_readpartial(argc, argv, io)
|
||||||
|
int argc;
|
||||||
|
VALUE *argv;
|
||||||
|
VALUE io;
|
||||||
|
{
|
||||||
|
OpenFile *fptr;
|
||||||
|
VALUE length, str;
|
||||||
|
long n, len;
|
||||||
|
|
||||||
|
rb_scan_args(argc, argv, "11", &length, &str);
|
||||||
|
|
||||||
|
GetOpenFile(io, fptr);
|
||||||
|
rb_io_check_readable(fptr);
|
||||||
|
|
||||||
|
if ((len = NUM2LONG(length)) < 0) {
|
||||||
|
rb_raise(rb_eArgError, "negative length %ld given", len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NIL_P(str)) {
|
||||||
|
str = rb_str_new(0, len);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
StringValue(str);
|
||||||
|
rb_str_modify(str);
|
||||||
|
rb_str_resize(str, len);
|
||||||
|
}
|
||||||
|
OBJ_TAINT(str);
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
return str;
|
||||||
|
|
||||||
|
READ_CHECK(fptr->f);
|
||||||
|
n = read_buffered_data(RSTRING(str)->ptr, len, fptr->f);
|
||||||
|
if (n <= 0) {
|
||||||
|
again:
|
||||||
|
TRAP_BEG;
|
||||||
|
n = read(fileno(fptr->f), RSTRING(str)->ptr, len);
|
||||||
|
TRAP_END;
|
||||||
|
if (n < 0) {
|
||||||
|
if (rb_io_wait_readable(fileno(fptr->f)))
|
||||||
|
goto again;
|
||||||
|
rb_str_resize(str, 0);
|
||||||
|
rb_sys_fail(fptr->path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rb_str_resize(str, n);
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
rb_eof_error();
|
||||||
|
else
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* ios.read([integer [, buffer]]) => string, buffer, or nil
|
* ios.read([integer [, buffer]]) => string, buffer, or nil
|
||||||
@ -2072,11 +2184,13 @@ rb_io_syswrite(io, str)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* ios.sysread(integer ) => string
|
* ios.sysread(integer[, outbuf]) => string
|
||||||
*
|
*
|
||||||
* Reads <i>integer</i> bytes from <em>ios</em> using a low-level
|
* Reads <i>integer</i> bytes from <em>ios</em> using a low-level
|
||||||
* read and returns them as a string. Do not mix with other methods
|
* read and returns them as a string. Do not mix with other methods
|
||||||
* that read from <em>ios</em> or you may get unpredictable results.
|
* that read from <em>ios</em> or you may get unpredictable results.
|
||||||
|
* If the optional <i>outbuf</i> argument is present, it must reference
|
||||||
|
* a String, which will receive the data.
|
||||||
* Raises <code>SystemCallError</code> on error and
|
* Raises <code>SystemCallError</code> on error and
|
||||||
* <code>EOFError</code> at end of file.
|
* <code>EOFError</code> at end of file.
|
||||||
*
|
*
|
||||||
@ -5439,6 +5553,7 @@ Init_IO()
|
|||||||
|
|
||||||
rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
|
rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
|
||||||
|
|
||||||
|
rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
|
||||||
rb_define_method(rb_cIO, "read", io_read, -1);
|
rb_define_method(rb_cIO, "read", io_read, -1);
|
||||||
rb_define_method(rb_cIO, "write", io_write, 1);
|
rb_define_method(rb_cIO, "write", io_write, 1);
|
||||||
rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
|
rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user