* io.c (fill_cbuf): extracted from more_char.

(io_shift_cbuf): fix memmove condition.
  (read_all): use fill_cbuf directly to avoid ECONV_AFTER_OUTPUT.
  [ruby-dev:39708]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25845 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2009-11-18 13:02:14 +00:00
parent 817f503001
commit 4c6eda226a
2 changed files with 48 additions and 25 deletions

View File

@ -1,3 +1,10 @@
Wed Nov 18 22:00:13 2009 Tanaka Akira <akr@fsij.org>
* io.c (fill_cbuf): extracted from more_char.
(io_shift_cbuf): fix memmove condition.
(read_all): use fill_cbuf directly to avoid ECONV_AFTER_OUTPUT.
[ruby-dev:39708]
Wed Nov 18 18:25:09 2009 Nobuyoshi Nakada <nobu@ruby-lang.org> Wed Nov 18 18:25:09 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
* thread.c (rb_thread_atfork_internal): reinitialize global lock * thread.c (rb_thread_atfork_internal): reinitialize global lock

58
io.c
View File

@ -1582,17 +1582,22 @@ make_readconv(rb_io_t *fptr, int size)
} }
} }
static int #define MORE_CHAR_CBUF_FULL Qtrue
more_char(rb_io_t *fptr) #define MORE_CHAR_FINISHED Qnil
static VALUE
fill_cbuf(rb_io_t *fptr, int ec_flags)
{ {
const unsigned char *ss, *sp, *se; const unsigned char *ss, *sp, *se;
unsigned char *ds, *dp, *de; unsigned char *ds, *dp, *de;
rb_econv_result_t res; rb_econv_result_t res;
int putbackable; int putbackable;
int cbuf_len0; int cbuf_len0;
VALUE exc;
ec_flags |= ECONV_PARTIAL_INPUT;
if (fptr->cbuf_len == fptr->cbuf_capa) if (fptr->cbuf_len == fptr->cbuf_capa)
return 0; /* cbuf full */ return MORE_CHAR_CBUF_FULL; /* cbuf full */
if (fptr->cbuf_len == 0) if (fptr->cbuf_len == 0)
fptr->cbuf_off = 0; fptr->cbuf_off = 0;
else if (fptr->cbuf_off + fptr->cbuf_len == fptr->cbuf_capa) { else if (fptr->cbuf_off + fptr->cbuf_len == fptr->cbuf_capa) {
@ -1607,7 +1612,7 @@ more_char(rb_io_t *fptr)
se = sp + fptr->rbuf_len; se = sp + fptr->rbuf_len;
ds = dp = (unsigned char *)fptr->cbuf + fptr->cbuf_off + fptr->cbuf_len; ds = dp = (unsigned char *)fptr->cbuf + fptr->cbuf_off + fptr->cbuf_len;
de = (unsigned char *)fptr->cbuf + fptr->cbuf_capa; de = (unsigned char *)fptr->cbuf + fptr->cbuf_capa;
res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT); res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
fptr->rbuf_off += (int)(sp - ss); fptr->rbuf_off += (int)(sp - ss);
fptr->rbuf_len -= (int)(sp - ss); fptr->rbuf_len -= (int)(sp - ss);
fptr->cbuf_len += (int)(dp - ds); fptr->cbuf_len += (int)(dp - ds);
@ -1619,13 +1624,15 @@ more_char(rb_io_t *fptr)
fptr->rbuf_len += putbackable; fptr->rbuf_len += putbackable;
} }
rb_econv_check_error(fptr->readconv); exc = rb_econv_make_exception(fptr->readconv);
if (!NIL_P(exc))
return exc;
if (cbuf_len0 != fptr->cbuf_len) if (cbuf_len0 != fptr->cbuf_len)
return 0; return MORE_CHAR_CBUF_FULL;
if (res == econv_finished) { if (res == econv_finished) {
return -1; return MORE_CHAR_FINISHED;
} }
if (res == econv_source_buffer_empty) { if (res == econv_source_buffer_empty) {
@ -1644,6 +1651,16 @@ more_char(rb_io_t *fptr)
} }
} }
static VALUE
more_char(rb_io_t *fptr)
{
VALUE v;
v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
if (v != MORE_CHAR_CBUF_FULL && v != MORE_CHAR_FINISHED)
rb_exc_raise(v);
return v;
}
static VALUE static VALUE
io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp) io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
{ {
@ -1665,7 +1682,7 @@ io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
/* xxx: set coderange */ /* xxx: set coderange */
if (fptr->cbuf_len == 0) if (fptr->cbuf_len == 0)
fptr->cbuf_off = 0; fptr->cbuf_off = 0;
if (fptr->cbuf_off < fptr->cbuf_capa/2) { else if (fptr->cbuf_capa/2 < fptr->cbuf_off) {
memmove(fptr->cbuf, fptr->cbuf+fptr->cbuf_off, fptr->cbuf_len); memmove(fptr->cbuf, fptr->cbuf+fptr->cbuf_off, fptr->cbuf_len);
fptr->cbuf_off = 0; fptr->cbuf_off = 0;
} }
@ -1686,20 +1703,18 @@ read_all(rb_io_t *fptr, long siz, VALUE str)
else rb_str_set_len(str, 0); else rb_str_set_len(str, 0);
make_readconv(fptr, 0); make_readconv(fptr, 0);
while (1) { while (1) {
int fin, state = 0; VALUE v;
if (fptr->cbuf_len > fptr->cbuf_capa / 2) {
io_shift_cbuf(fptr, fptr->cbuf_len, &str);
}
fin = rb_protect((VALUE (*)(VALUE))more_char, (VALUE)fptr, &state);
if (fin == -1 || state != 0) {
if (fptr->cbuf_len) { if (fptr->cbuf_len) {
io_shift_cbuf(fptr, fptr->cbuf_len, &str); io_shift_cbuf(fptr, fptr->cbuf_len, &str);
} }
if (state != 0) { v = fill_cbuf(fptr, 0);
rb_jump_tag(state); if (v != MORE_CHAR_CBUF_FULL && v != MORE_CHAR_FINISHED) {
if (fptr->cbuf_len) {
io_shift_cbuf(fptr, fptr->cbuf_len, &str);
} }
rb_exc_raise(v);
}
if (v == MORE_CHAR_FINISHED) {
clear_readconv(fptr); clear_readconv(fptr);
return io_enc_str(str, fptr); return io_enc_str(str, fptr);
} }
@ -2181,7 +2196,7 @@ appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1]; return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
} }
} }
} while (more_char(fptr) != -1); } while (more_char(fptr) != MORE_CHAR_FINISHED);
clear_readconv(fptr); clear_readconv(fptr);
*lp = limit; *lp = limit;
return EOF; return EOF;
@ -2695,7 +2710,8 @@ io_getc(rb_io_t *fptr, rb_encoding *enc)
} }
} }
if (more_char(fptr) == -1) { if (more_char(fptr) == MORE_CHAR_FINISHED) {
clear_readconv(fptr);
if (fptr->cbuf_len == 0) if (fptr->cbuf_len == 0)
return Qnil; return Qnil;
/* return an incomplete character just before EOF */ /* return an incomplete character just before EOF */
@ -2830,7 +2846,7 @@ rb_io_each_codepoint(VALUE io)
rb_raise(rb_eIOError, "too long character"); rb_raise(rb_eIOError, "too long character");
} }
} }
if (more_char(fptr) == -1) { if (more_char(fptr) == MORE_CHAR_FINISHED) {
clear_readconv(fptr); clear_readconv(fptr);
/* ignore an incomplete character before EOF */ /* ignore an incomplete character before EOF */
return io; return io;