From 4c6d524c473ebb9174d0183dc1d1ac0530337314 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sat, 1 Feb 2020 16:25:39 +0900 Subject: Implement `IO#pread` and `IO#pwrite` It is available by default in environments where `__unix__` is defined. Other environments are enabled by defining `MRB_WITH_IO_PREAD_PWRITE` (requires an implementation of `pread()` and `pwrite()` functions). In any case, you can disable it by defining `MRB_WITHOUT_IO_PREAD_PWRITE`. --- mrbgems/mruby-io/src/io.c | 113 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 105 insertions(+), 8 deletions(-) (limited to 'mrbgems/mruby-io/src') diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index 4be41ef31..b7f70a5f8 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -31,6 +31,7 @@ typedef long ftime_t; typedef long fsuseconds_t; typedef int fmode_t; + typedef int mrb_io_read_write_size; #ifndef O_TMPFILE #define O_TMPFILE O_TEMPORARY @@ -43,6 +44,7 @@ typedef time_t ftime_t; typedef suseconds_t fsuseconds_t; typedef mode_t fmode_t; + typedef ssize_t mrb_io_read_write_size; #endif #ifdef _MSC_VER @@ -845,15 +847,35 @@ mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass) return mrb_fixnum_value(fd); } +static mrb_value mrb_io_sysread_common(mrb_state *mrb, + mrb_io_read_write_size (*readfunc)(int, void *, fsize_t, off_t), + mrb_value io, mrb_value buf, mrb_int maxlen, off_t offset); + +static mrb_io_read_write_size +mrb_sysread_dummy(int fd, void *buf, fsize_t nbytes, off_t offset) +{ + return (mrb_io_read_write_size)read(fd, buf, nbytes); +} + mrb_value mrb_io_sysread(mrb_state *mrb, mrb_value io) { - struct mrb_io *fptr; mrb_value buf = mrb_nil_value(); mrb_int maxlen; - int ret; mrb_get_args(mrb, "i|S", &maxlen, &buf); + + return mrb_io_sysread_common(mrb, mrb_sysread_dummy, io, buf, maxlen, 0); +} + +static mrb_value +mrb_io_sysread_common(mrb_state *mrb, + mrb_io_read_write_size (*readfunc)(int, void *, fsize_t, off_t), + mrb_value io, mrb_value buf, mrb_int maxlen, off_t offset) +{ + struct mrb_io *fptr; + int ret; + if (maxlen < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative expanding string size"); } @@ -875,7 +897,7 @@ mrb_io_sysread(mrb_state *mrb, mrb_value io) if (!fptr->readable) { mrb_raise(mrb, E_IO_ERROR, "not opened for reading"); } - ret = read(fptr->fd, RSTRING_PTR(buf), (fsize_t)maxlen); + ret = readfunc(fptr->fd, RSTRING_PTR(buf), (fsize_t)maxlen, offset); switch (ret) { case 0: /* EOF */ if (maxlen == 0) { @@ -925,11 +947,31 @@ mrb_io_sysseek(mrb_state *mrb, mrb_value io) } } +static mrb_value mrb_io_syswrite_common(mrb_state *mrb, + mrb_io_read_write_size (*writefunc)(int, const void *, fsize_t, off_t), + mrb_value io, mrb_value buf, off_t offset); + +static mrb_io_read_write_size +mrb_syswrite_dummy(int fd, const void *buf, fsize_t nbytes, off_t offset) +{ + return (mrb_io_read_write_size)write(fd, buf, nbytes); +} + mrb_value mrb_io_syswrite(mrb_state *mrb, mrb_value io) +{ + mrb_value buf; + + mrb_get_args(mrb, "S", &buf); + + return mrb_io_syswrite_common(mrb, mrb_syswrite_dummy, io, buf, 0); +} + +static mrb_value mrb_io_syswrite_common(mrb_state *mrb, + mrb_io_read_write_size (*writefunc)(int, const void *, fsize_t, off_t), + mrb_value io, mrb_value buf, off_t offset) { struct mrb_io *fptr; - mrb_value str, buf; int fd, length; fptr = io_get_open_fptr(mrb, io); @@ -937,15 +979,12 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io) mrb_raise(mrb, E_IO_ERROR, "not opened for writing"); } - mrb_get_args(mrb, "S", &str); - buf = str; - if (fptr->fd2 == -1) { fd = fptr->fd; } else { fd = fptr->fd2; } - length = write(fd, RSTRING_PTR(buf), (fsize_t)RSTRING_LEN(buf)); + length = writefunc(fd, RSTRING_PTR(buf), (fsize_t)RSTRING_LEN(buf), offset); if (length == -1) { mrb_sys_fail(mrb, 0); } @@ -1328,6 +1367,62 @@ mrb_io_sync(mrb_state *mrb, mrb_value self) return mrb_bool_value(fptr->sync); } +#ifndef MRB_WITH_IO_PREAD_PWRITE +# define mrb_io_pread mrb_notimplement_m +# define mrb_io_pwrite mrb_notimplement_m +#else +static off_t +value2off(mrb_state *mrb, mrb_value offv) +{ + switch (mrb_type(offv)) { +#ifndef MRB_WITHOUT_FLOAT + case MRB_TT_FLOAT: + { + mrb_float tmp = mrb_float(offv); + if (tmp < INT64_MIN || tmp > INT64_MAX) { + /* fall through to use convert by `mrb_int()` (and raise error if out of range) */ + } else { + return (off_t)tmp; + } + } + /* fall through */ +#endif /* MRB_WITHOUT_FLOAT */ + default: + return (off_t)mrb_int(mrb, offv); + } +} + +/* + * call-seq: + * pread(maxlen, offset, outbuf = "") -> outbuf + */ +static mrb_value +mrb_io_pread(mrb_state *mrb, mrb_value io) +{ + mrb_value buf = mrb_nil_value(); + mrb_value off; + mrb_int maxlen; + + mrb_get_args(mrb, "io|S!", &maxlen, &off, &buf); + + return mrb_io_sysread_common(mrb, pread, io, buf, maxlen, value2off(mrb, off)); +} + +/* + * call-seq: + * pwrite(buffer, offset) -> wrote_bytes + */ +static mrb_value +mrb_io_pwrite(mrb_state *mrb, mrb_value io) +{ + mrb_value buf, off; + + mrb_get_args(mrb, "So", &buf, &off); + + return mrb_io_syswrite_common(mrb, pwrite, io, buf, value2off(mrb, off)); +} +#endif /* MRB_WITH_IO_PREAD_PWRITE */ + static mrb_value io_bufread(mrb_state *mrb, mrb_value self) { @@ -1383,6 +1478,8 @@ mrb_init_io(mrb_state *mrb) mrb_define_method(mrb, io, "closed?", mrb_io_closed, MRB_ARGS_NONE()); /* 15.2.20.5.2 */ mrb_define_method(mrb, io, "pid", mrb_io_pid, MRB_ARGS_NONE()); /* 15.2.20.5.2 */ mrb_define_method(mrb, io, "fileno", mrb_io_fileno_m, MRB_ARGS_NONE()); + 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)); } -- cgit v1.2.3 From 690175272335ecc8a7a177de91c2e7f49c662846 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 7 Mar 2020 19:03:45 +0900 Subject: Use in-house macro `ISALPHA` instead of `isalpha`; ref #4950 --- mrbgems/mruby-io/src/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-io/src') diff --git a/mrbgems/mruby-io/src/file.c b/mrbgems/mruby-io/src/file.c index ffce0ddcb..3f3b6bb25 100644 --- a/mrbgems/mruby-io/src/file.c +++ b/mrbgems/mruby-io/src/file.c @@ -284,7 +284,7 @@ mrb_file_is_absolute_path(const char *path) { #ifdef _WIN32 #define IS_PATHSEP(x) (x == '/' || x == '\\') - if (isalpha(path[0])) + if (ISALPHA(path[0])) return (strlen(path) > 2 && path[1] == ':' && IS_PATHSEP(path[2])); else return (IS_PATHSEP(path[0]) && IS_PATHSEP(path[1])); -- cgit v1.2.3 From 20f9128f732c3f4f51834fc0096abb0382cc4837 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 7 Mar 2020 19:06:46 +0900 Subject: Small refactoring on #4939 --- mrbgems/mruby-io/src/io.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'mrbgems/mruby-io/src') diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index 0ddb04325..41d6b6120 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -948,27 +948,8 @@ mrb_io_sysseek(mrb_state *mrb, mrb_value io) } } -static mrb_value mrb_io_syswrite_common(mrb_state *mrb, - mrb_io_read_write_size (*writefunc)(int, const void *, fsize_t, off_t), - mrb_value io, mrb_value buf, off_t offset); - -static mrb_io_read_write_size -mrb_syswrite_dummy(int fd, const void *buf, fsize_t nbytes, off_t offset) -{ - return (mrb_io_read_write_size)write(fd, buf, nbytes); -} - -mrb_value -mrb_io_syswrite(mrb_state *mrb, mrb_value io) -{ - mrb_value buf; - - mrb_get_args(mrb, "S", &buf); - - return mrb_io_syswrite_common(mrb, mrb_syswrite_dummy, io, buf, 0); -} - -static mrb_value mrb_io_syswrite_common(mrb_state *mrb, +static mrb_value +mrb_io_syswrite_common(mrb_state *mrb, mrb_io_read_write_size (*writefunc)(int, const void *, fsize_t, off_t), mrb_value io, mrb_value buf, off_t offset) { @@ -993,6 +974,22 @@ static mrb_value mrb_io_syswrite_common(mrb_state *mrb, return mrb_fixnum_value(length); } +static mrb_io_read_write_size +mrb_syswrite_dummy(int fd, const void *buf, fsize_t nbytes, off_t offset) +{ + return (mrb_io_read_write_size)write(fd, buf, nbytes); +} + +mrb_value +mrb_io_syswrite(mrb_state *mrb, mrb_value io) +{ + mrb_value buf; + + mrb_get_args(mrb, "S", &buf); + + return mrb_io_syswrite_common(mrb, mrb_syswrite_dummy, io, buf, 0); +} + mrb_value mrb_io_close(mrb_state *mrb, mrb_value self) { -- cgit v1.2.3