diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-04-28 13:18:43 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-04-28 13:57:46 +0900 |
| commit | b87268f130c4a29f4be4172409dbe12cddb4e2f9 (patch) | |
| tree | 60844bf4eb077b0de53b1f45dc73dc945010404a /mrbgems/mruby-io/src | |
| parent | a395f8e2c829706eb7c9e0dccaab077f189ddb6e (diff) | |
| download | mruby-b87268f130c4a29f4be4172409dbe12cddb4e2f9.tar.gz mruby-b87268f130c4a29f4be4172409dbe12cddb4e2f9.zip | |
Fix `IO#readchar` to support UTF-8 char reading; fix #4712
This fix only effective when `MRB_UTF8_STRING` is set.
Diffstat (limited to 'mrbgems/mruby-io/src')
| -rw-r--r-- | mrbgems/mruby-io/src/io.c | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index 8d278289e..794a3c491 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -1454,14 +1454,13 @@ mrb_io_pwrite(mrb_state *mrb, mrb_value io) #endif /* MRB_WITH_IO_PREAD_PWRITE */ static mrb_value -io_bufread(mrb_state *mrb, mrb_value self) +io_bufread(mrb_state *mrb, mrb_value str, mrb_int len) { - mrb_value str, str2; - mrb_int len, newlen; + mrb_value str2; + mrb_int newlen; struct RString *s; char *p; - mrb_get_args(mrb, "Si", &str, &len); s = RSTRING(str); mrb_str_modify(mrb, s); p = RSTR_PTR(s); @@ -1474,6 +1473,40 @@ io_bufread(mrb_state *mrb, mrb_value self) return str2; } +static mrb_value +mrb_io_bufread(mrb_state *mrb, mrb_value self) +{ + mrb_value str; + mrb_int len; + + mrb_get_args(mrb, "Si", &str, &len); + return io_bufread(mrb, str, len); +} + +static mrb_value +mrb_io_readchar(mrb_state *mrb, mrb_value self) +{ + mrb_value buf; + unsigned char c; + mrb_int len = 1; + + mrb_get_args(mrb, "S", &buf); + mrb_assert(RSTRING_PTR(buf) > 0); +#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 */ + /* 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); + } + len = mrb_utf8len(RSTRING_PTR(buf), RSTRING_END(buf)); + } +#endif + return io_bufread(mrb, buf, len); +} + void mrb_init_io(mrb_state *mrb) { @@ -1511,5 +1544,6 @@ mrb_init_io(mrb_state *mrb) mrb_define_method(mrb, io, "pread", mrb_io_pread, MRB_ARGS_ANY()); /* ruby 2.5 feature */ mrb_define_method(mrb, io, "pwrite", mrb_io_pwrite, MRB_ARGS_ANY()); /* ruby 2.5 feature */ - mrb_define_class_method(mrb, io, "_bufread", io_bufread, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, io, "_readchar", mrb_io_readchar, MRB_ARGS_REQ(1)); + mrb_define_class_method(mrb, io, "_bufread", mrb_io_bufread, MRB_ARGS_REQ(2)); } |
