mruby-io/io.c: implement IO#write in C

And now `write` takes multiple string arguments
This commit is contained in:
Yukihiro "Matz" Matsumoto
2022-12-29 14:35:29 +09:00
parent 663d5715bc
commit 14a374c6bc
2 changed files with 60 additions and 11 deletions
-11
View File
@@ -86,17 +86,6 @@ class IO
self.__id__
end
def write(string)
str = string.is_a?(String) ? string : string.to_s
return 0 if str.empty?
unless @buf.empty?
# reset real pos ignore buf
seek(pos, SEEK_SET)
end
len = syswrite(str)
len
end
def <<(str)
write(str)
self
+60
View File
@@ -1030,6 +1030,65 @@ io_syswrite(mrb_state *mrb, mrb_value io)
return io_syswrite_common(mrb, syswrite, io, buf, 0);
}
/* def write(string) */
/* str = string.is_a?(String) ? string : string.to_s */
/* return 0 if str.empty? */
/* len = syswrite(str) */
/* len */
/* end */
static mrb_int
fd_write(mrb_state *mrb, int fd, mrb_value str)
{
fssize_t len, sum, n;
str = mrb_obj_as_string(mrb, str);
len = (fssize_t)RSTRING_LEN(str);
if (len == 0)return 0;
for (sum=0; sum<len; sum+=n) {
n = write(fd, RSTRING_PTR(str), (fsize_t)len);
if (n == -1) {
mrb_sys_fail(mrb, "syswrite");
}
}
return len;
}
static mrb_value
io_write(mrb_state *mrb, mrb_value self)
{
int fd = io_get_write_fd(mrb, self);
mrb_int len = 0;
mrb_value buf = mrb_iv_get(mrb, self, MRB_IVSYM(buf));
if (RSTRING_LEN(buf) > 0) {
off_t n;
/* get current position */
n = lseek(fd, 0, SEEK_CUR);
if (n == -1) mrb_sys_fail(mrb, "lseek");
/* move cursor */
n = lseek(fd, n - RSTRING_LEN(buf), SEEK_SET);
if (n == -1) mrb_sys_fail(mrb, "lseek(2)");
mrb_str_resize(mrb, buf, 0);
}
if (mrb_get_argc(mrb) == 1) {
len = fd_write(mrb, fd, mrb_get_arg1(mrb));
}
else {
mrb_value *argv;
mrb_int argc;
mrb_get_args(mrb, "*", &argv, &argc);
while (argc--) {
len += fd_write(mrb, fd, *argv++);
}
}
return mrb_int_value(mrb, len);
}
static mrb_value
io_close(mrb_state *mrb, mrb_value self)
{
@@ -1569,6 +1628,7 @@ mrb_init_io(mrb_state *mrb)
mrb_define_method(mrb, io, "closed?", io_closed, MRB_ARGS_NONE()); /* 15.2.20.5.2 */
mrb_define_method(mrb, io, "pid", io_pid, MRB_ARGS_NONE()); /* 15.2.20.5.2 */
mrb_define_method(mrb, io, "fileno", io_fileno, MRB_ARGS_NONE());
mrb_define_method(mrb, io, "write", io_write, MRB_ARGS_ANY()); /* 15.2.20.5.20 */
mrb_define_method(mrb, io, "pread", io_pread, MRB_ARGS_ANY()); /* ruby 2.5 feature */
mrb_define_method(mrb, io, "pwrite", io_pwrite, MRB_ARGS_ANY()); /* ruby 2.5 feature */