mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Fix IO#readchar to return broken UTF-8 rather than EOF error.
The behavior is different from CRuby, but we believe this is a right behavior for mruby, which only supports either ASCII or UTF-8 exclusively; fix #4983, ref #4982 ``` $ printf '\xe3\x81' | ruby -e 'p STDIN.readchar' "\xE3\x81" ``` ``` $ printf '\xe3\x81' | mruby -e 'p STDIN.readchar' "\xE3" ```
This commit is contained in:
@@ -284,15 +284,14 @@ class IO
|
||||
def readchar
|
||||
_read_buf
|
||||
_readchar(@buf)
|
||||
# c = @buf[0]
|
||||
# @buf[0] = ""
|
||||
# c
|
||||
end
|
||||
|
||||
def getc
|
||||
begin
|
||||
readchar
|
||||
rescue EOFError
|
||||
c = @buf[0]
|
||||
@buf[0,1]="" if c
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1492,14 +1492,25 @@ mrb_io_readchar(mrb_state *mrb, mrb_value self)
|
||||
|
||||
mrb_get_args(mrb, "S", &buf);
|
||||
mrb_assert(RSTRING_PTR(buf) > 0);
|
||||
mrb_str_modify(mrb, RSTRING(buf));
|
||||
#ifdef MRB_UTF8_STRING
|
||||
c = RSTRING_PTR(buf)[0];
|
||||
if (c & 0x80) {
|
||||
len = mrb_utf8len(RSTRING_PTR(buf), RSTRING_END(buf));
|
||||
if (len == 1 && RSTRING_LEN(buf) < 5) { /* partial UTF-8 */
|
||||
if (len == 1 && RSTRING_LEN(buf) < 4) { /* partial UTF-8 */
|
||||
mrb_int blen = RSTRING_LEN(buf);
|
||||
ssize_t n;
|
||||
|
||||
struct mrb_io *fptr = (struct mrb_io*)io_get_open_fptr(mrb, self);
|
||||
|
||||
if (!fptr->readable) {
|
||||
mrb_raise(mrb, E_IO_ERROR, "not opened for reading");
|
||||
}
|
||||
/* refill the buffer */
|
||||
mrb_value b = mrb_io_sysread_common(mrb, mrb_sysread_dummy, self, mrb_nil_value(), 4096, 0);
|
||||
mrb_str_concat(mrb, buf, b);
|
||||
mrb_str_resize(mrb, buf, 4096);
|
||||
n = read(fptr->fd, RSTRING_PTR(buf)+blen, 4096-blen);
|
||||
if (n < 0) mrb_sys_fail(mrb, "sysread failed");
|
||||
mrb_str_resize(mrb, buf, blen+n);
|
||||
}
|
||||
len = mrb_utf8len(RSTRING_PTR(buf), RSTRING_END(buf));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user