なかだです。

At Sun, 28 Mar 2004 14:02:08 +0900,
Tanaka Akira wrote in [ruby-dev:23247]:
> なお、実装はまだ試験的なもので、IO にしか実装してません。また、効率の
> 点からは可能なら READ_DATA_PENDING_COUNT を使うべきですが、まだそうし
> ていません。

対応してみました。しかし、READ_DATA_PENDING()の場合はバッファに
あるデータだけを読むというのはなんででしょうか。そのままread(2)
にいってしまうのはまずい?

[ruby-dev:23247]の差分です。

Index: io.c =================================================================== RCS file: /cvs/ruby/src/ruby/io.c,v retrieving revision 1.265.100.1 diff -u -2 -p -d -E -r1.265.100.1 io.c --- io.c 28 Mar 2004 05:12:37 -0000 1.265.100.1 +++ io.c 28 Mar 2004 06:48:48 -0000 @@ -889,4 +889,25 @@ rb_io_to_io(io) /* 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 rb_io_fread(ptr, len, f) @@ -899,26 +920,10 @@ rb_io_fread(ptr, len, f) while (n > 0) { -#ifdef READ_DATA_PENDING_COUNT - long i = READ_DATA_PENDING_COUNT(f); - if (i <= 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; + c = read_buffered_data(ptr, n, f); + if (c < 0) goto eof; + if (c > 0) { ptr += c; - n -= c; - if (c < i) goto eof; - continue; + if ((n -= c) <= 0) break; } -#else - if (!READ_DATA_PENDING(f)) { - rb_thread_wait_fd(fileno(f)); - } -#endif TRAP_BEG; c = getc(f); @@ -1046,11 +1051,13 @@ io_readpartial(argc, argv, io) VALUE length, str; - rb_scan_args(argc, argv, "11", &length, &str); + rb_scan_args(argc, argv, "02", &length, &str); GetOpenFile(io, fptr); rb_io_check_readable(fptr); - len = NUM2LONG(length); - if (len < 0) { + if (NIL_P(length)) { + len = BUFSIZ; + } + else if ((len = NUM2LONG(length)) < 0) { rb_raise(rb_eArgError, "negative length %ld given", len); } @@ -1062,28 +1069,41 @@ io_readpartial(argc, argv, io) StringValue(str); rb_str_modify(str); - rb_str_resize(str,len); + if (NIL_P(length) && len <= RSTRING(str)->len) { + len = RSTRING(str)->len; + } + else { + rb_str_resize(str, len); + } + } + + if (len == 0) { + rb_str_resize(str, 0); + return str; } - if (len == 0) return str; READ_CHECK(fptr->f); { char *ptr = RSTRING(str)->ptr; - if (READ_DATA_PENDING(fptr->f)) { - for (n = 0; n < len && READ_DATA_PENDING(fptr->f); n++) { - int c; - TRAP_BEG; - c = getc(fptr->f); - TRAP_END; - *ptr++ = c; - } + int c; + + n = read_buffered_data(ptr, len, fptr->f); + if (n > 0) { + ptr += n; + len -= n; } else { - for (;;) { + while (len > 0) { TRAP_BEG; - n = read(fileno(fptr->f), ptr, len); + c = read(fileno(fptr->f), ptr, len); TRAP_END; - if (n != -1) - break; - if (!rb_io_wait_readable(fileno(fptr->f))) { + if (c != -1) { + n += c; + if (!NIL_P(length)) break; + rb_str_resize(str, n + BUFSIZ); + ptr = RSTRING(str)->ptr + n; + len = RSTRING(str)->len - n; + } + else if (!rb_io_wait_readable(fileno(fptr->f))) { + if (n > 0) break; rb_str_resize(str, 0); rb_sys_fail(fptr->path);
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦