6 #include <mruby/array.h>
7 #include <mruby/class.h>
8 #include <mruby/data.h>
9 #include <mruby/hash.h>
10 #include <mruby/string.h>
11 #include <mruby/variable.h>
12 #include <mruby/ext/io.h>
13 #include <mruby/error.h>
14 #include <mruby/internal.h>
15 #include <mruby/presym.h>
17 #include <sys/types.h>
31 #define isatty _isatty
32 #define WEXITSTATUS(x) (x)
35 typedef long fsuseconds_t
;
40 #define O_TMPFILE O_TEMPORARY
47 typedef size_t fsize_t
;
48 typedef time_t ftime_t
;
50 typedef long fsuseconds_t
;
52 typedef suseconds_t fsuseconds_t
;
54 typedef mode_t fmode_t
;
55 typedef ssize_t fssize_t
;
59 typedef mrb_int pid_t
;
67 #define OPEN_ACCESS_MODE_FLAGS (O_RDONLY | O_WRONLY | O_RDWR)
68 #define OPEN_RDONLY_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_RDONLY))
69 #define OPEN_WRONLY_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_WRONLY))
70 #define OPEN_RDWR_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_RDWR))
71 #define OPEN_READABLE_P(f) ((mrb_bool)(OPEN_RDONLY_P(f) || OPEN_RDWR_P(f)))
72 #define OPEN_WRITABLE_P(f) ((mrb_bool)(OPEN_WRONLY_P(f) || OPEN_RDWR_P(f)))
74 static void io_free(mrb_state
*mrb
, void *ptr
);
75 struct mrb_data_type mrb_io_type
= { "IO", io_free
};
78 static int io_modestr_to_flags(mrb_state
*mrb
, const char *modestr
);
79 static int io_mode_to_flags(mrb_state
*mrb
, mrb_value mode
);
80 static void fptr_finalize(mrb_state
*mrb
, struct mrb_io
*fptr
, int quiet
);
83 io_get_open_fptr(mrb_state
*mrb
, mrb_value io
)
85 struct mrb_io
*fptr
= (struct mrb_io
*)mrb_data_get_ptr(mrb
, io
, &mrb_io_type
);
87 mrb_raise(mrb
, E_IO_ERROR
, "uninitialized stream");
90 mrb_raise(mrb
, E_IO_ERROR
, "closed stream");
95 #if !defined(MRB_NO_IO_POPEN) && defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
96 # define MRB_NO_IO_POPEN 1
99 #ifndef MRB_NO_IO_POPEN
101 io_set_process_status(mrb_state
*mrb
, pid_t pid
, int status
)
103 struct RClass
*c_status
= NULL
;
106 if (mrb_class_defined_id(mrb
, MRB_SYM(Process
))) {
107 struct RClass
*c_process
= mrb_module_get_id(mrb
, MRB_SYM(Process
));
108 if (mrb_const_defined(mrb
, mrb_obj_value(c_process
), MRB_SYM(Status
))) {
109 c_status
= mrb_class_get_under_id(mrb
, c_process
, MRB_SYM(Status
));
112 if (c_status
!= NULL
) {
113 v
= mrb_funcall_id(mrb
, mrb_obj_value(c_status
), MRB_SYM(new), 2, mrb_fixnum_value(pid
), mrb_fixnum_value(status
));
116 v
= mrb_fixnum_value(WEXITSTATUS(status
));
118 mrb_gv_set(mrb
, mrb_intern_lit(mrb
, "$?"), v
);
123 io_modestr_to_flags(mrb_state
*mrb
, const char *mode
)
126 const char *m
= mode
;
133 flags
= O_WRONLY
| O_CREAT
| O_TRUNC
;
136 flags
= O_WRONLY
| O_CREAT
| O_APPEND
;
150 if (mode
[0] != 'w') goto modeerr
;
154 flags
= (flags
& ~OPEN_ACCESS_MODE_FLAGS
) | O_RDWR
;
157 /* XXX: PASSTHROUGH*/
166 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "illegal access mode %s", mode
);
167 return 0; /* not reached */
171 io_mode_to_flags(mrb_state
*mrb
, mrb_value mode
)
173 if (mrb_nil_p(mode
)) {
176 else if (mrb_string_p(mode
)) {
177 return io_modestr_to_flags(mrb
, RSTRING_CSTR(mrb
, mode
));
181 mrb_int flags0
= mrb_as_int(mrb
, mode
);
183 switch (flags0
& MRB_O_ACCMODE
) {
194 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "illegal access mode %v", mode
);
197 if (flags0
& MRB_O_APPEND
) flags
|= O_APPEND
;
198 if (flags0
& MRB_O_CREAT
) flags
|= O_CREAT
;
199 if (flags0
& MRB_O_EXCL
) flags
|= O_EXCL
;
200 if (flags0
& MRB_O_TRUNC
) flags
|= O_TRUNC
;
202 if (flags0
& MRB_O_NONBLOCK
) flags
|= O_NONBLOCK
;
205 if (flags0
& MRB_O_NOCTTY
) flags
|= O_NOCTTY
;
208 if (flags0
& MRB_O_BINARY
) flags
|= O_BINARY
;
210 #ifdef O_SHARE_DELETE
211 if (flags0
& MRB_O_SHARE_DELETE
) flags
|= O_SHARE_DELETE
;
214 if (flags0
& MRB_O_SYNC
) flags
|= O_SYNC
;
217 if (flags0
& MRB_O_DSYNC
) flags
|= O_DSYNC
;
220 if (flags0
& MRB_O_RSYNC
) flags
|= O_RSYNC
;
223 if (flags0
& MRB_O_NOFOLLOW
) flags
|= O_NOFOLLOW
;
226 if (flags0
& MRB_O_NOATIME
) flags
|= O_NOATIME
;
229 if (flags0
& MRB_O_DIRECT
) flags
|= O_DIRECT
;
232 if (flags0
& MRB_O_TMPFILE
) flags
|= O_TMPFILE
;
240 io_fd_cloexec(mrb_state
*mrb
, int fd
)
242 #if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
243 int flags
= fcntl(fd
, F_GETFD
);
247 mrb_sys_fail(mrb
, "cloexec GETFD");
250 flags2
= flags
& ~FD_CLOEXEC
; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
253 flags2
= flags
| FD_CLOEXEC
; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
255 if (flags
!= flags2
) {
256 if (fcntl(fd
, F_SETFD
, flags2
) < 0) {
257 mrb_sys_fail(mrb
, "cloexec SETFD");
263 #if !defined(_WIN32) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
265 io_cloexec_pipe(mrb_state
*mrb
, int fildes
[2])
267 int ret
= pipe(fildes
);
270 io_fd_cloexec(mrb
, fildes
[0]);
271 io_fd_cloexec(mrb
, fildes
[1]);
276 io_pipe(mrb_state
*mrb
, int pipes
[2])
278 int ret
= io_cloexec_pipe(mrb
, pipes
);
280 if (errno
== EMFILE
|| errno
== ENFILE
) {
281 mrb_garbage_collect(mrb
);
282 ret
= io_cloexec_pipe(mrb
, pipes
);
289 io_process_exec(const char *pname
)
291 const char *s
= pname
;
293 while (*s
== ' ' || *s
== '\t' || *s
== '\n')
301 execl("/bin/sh", "sh", "-c", pname
, (char*)NULL
);
307 io_free(mrb_state
*mrb
, void *ptr
)
309 struct mrb_io
*io
= (struct mrb_io
*)ptr
;
311 fptr_finalize(mrb
, io
, TRUE
);
317 io_init_buf(mrb_state
*mrb
, struct mrb_io
*fptr
)
319 if (fptr
->readable
) {
320 fptr
->buf
= (struct mrb_io_buf
*)mrb_malloc(mrb
, sizeof(struct mrb_io_buf
));
321 fptr
->buf
->start
= 0;
326 static struct mrb_io
*
327 io_alloc(mrb_state
*mrb
)
329 struct mrb_io
*fptr
= (struct mrb_io
*)mrb_malloc(mrb
, sizeof(struct mrb_io
));
348 #ifdef MRB_NO_IO_POPEN
349 # define io_s_popen mrb_notimplement_m
352 option_to_fd(mrb_state
*mrb
, mrb_value v
)
354 if (mrb_undef_p(v
)) return -1;
355 if (mrb_nil_p(v
)) return -1;
357 switch (mrb_type(v
)) {
358 case MRB_TT_CDATA
: /* IO */
359 return mrb_io_fileno(mrb
, v
);
361 return (int)mrb_integer(v
);
363 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "wrong exec redirect action");
366 return -1; /* never reached */
370 io_s_popen_args(mrb_state
*mrb
, mrb_value klass
,
371 const char **cmd
, int *flags
, int *doexec
,
372 int *opt_in
, int *opt_out
, int *opt_err
)
374 mrb_value mode
= mrb_nil_value();
375 struct { mrb_value opt_in
, opt_out
, opt_err
; } kv
;
376 mrb_sym knames
[3] = {MRB_SYM(in
), MRB_SYM(out
), MRB_SYM(err
)};
377 const mrb_kwargs kw
= {
384 mrb_get_args(mrb
, "zo:", cmd
, &mode
, &kw
);
386 *flags
= io_mode_to_flags(mrb
, mode
);
387 *doexec
= (strcmp("-", *cmd
) != 0);
388 *opt_in
= option_to_fd(mrb
, kv
.opt_in
);
389 *opt_out
= option_to_fd(mrb
, kv
.opt_out
);
390 *opt_err
= option_to_fd(mrb
, kv
.opt_err
);
392 return mrb_obj_value(mrb_data_object_alloc(mrb
, mrb_class_ptr(klass
), NULL
, &mrb_io_type
));
397 io_s_popen(mrb_state
*mrb
, mrb_value klass
)
400 int opt_in
, opt_out
, opt_err
;
406 PROCESS_INFORMATION pi
;
411 ifd
[0] = INVALID_HANDLE_VALUE
;
412 ifd
[1] = INVALID_HANDLE_VALUE
;
413 ofd
[0] = INVALID_HANDLE_VALUE
;
414 ofd
[1] = INVALID_HANDLE_VALUE
;
417 mrb_value io
= io_s_popen_args(mrb
, klass
, &cmd
, &flags
, &doexec
,
418 &opt_in
, &opt_out
, &opt_err
);
420 SECURITY_ATTRIBUTES saAttr
;
421 saAttr
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
422 saAttr
.bInheritHandle
= TRUE
;
423 saAttr
.lpSecurityDescriptor
= NULL
;
425 if (OPEN_READABLE_P(flags
)) {
426 if (!CreatePipe(&ofd
[0], &ofd
[1], &saAttr
, 0)
427 || !SetHandleInformation(ofd
[0], HANDLE_FLAG_INHERIT
, 0)) {
428 mrb_sys_fail(mrb
, "pipe");
432 if (OPEN_WRITABLE_P(flags
)) {
433 if (!CreatePipe(&ifd
[0], &ifd
[1], &saAttr
, 0)
434 || !SetHandleInformation(ifd
[1], HANDLE_FLAG_INHERIT
, 0)) {
435 mrb_sys_fail(mrb
, "pipe");
440 ZeroMemory(&pi
, sizeof(pi
));
441 ZeroMemory(&si
, sizeof(si
));
443 si
.dwFlags
|= STARTF_USESHOWWINDOW
;
444 si
.wShowWindow
= SW_HIDE
;
445 si
.dwFlags
|= STARTF_USESTDHANDLES
;
446 if (OPEN_READABLE_P(flags
)) {
447 si
.hStdOutput
= ofd
[1];
448 si
.hStdError
= ofd
[1];
450 if (OPEN_WRITABLE_P(flags
)) {
451 si
.hStdInput
= ifd
[0];
454 NULL
, (char*)cmd
, NULL
, NULL
,
455 TRUE
, CREATE_NEW_PROCESS_GROUP
, NULL
, NULL
, &si
, &pi
)) {
460 mrb_raisef(mrb
, E_IO_ERROR
, "command not found: %s", cmd
);
462 CloseHandle(pi
.hThread
);
465 pid
= pi
.dwProcessId
;
468 fptr
= io_alloc(mrb
);
469 fptr
->fd
= _open_osfhandle((intptr_t)ofd
[0], 0);
470 fptr
->fd2
= _open_osfhandle((intptr_t)ifd
[1], 0);
472 fptr
->readable
= OPEN_READABLE_P(flags
);
473 fptr
->writable
= OPEN_WRITABLE_P(flags
);
474 io_init_buf(mrb
, fptr
);
476 DATA_TYPE(io
) = &mrb_io_type
;
482 io_s_popen(mrb_state
*mrb
, mrb_value klass
)
485 int opt_in
, opt_out
, opt_err
;
488 int pid
, flags
, write_fd
= -1;
489 int pr
[2] = { -1, -1 };
490 int pw
[2] = { -1, -1 };
493 mrb_value io
= io_s_popen_args(mrb
, klass
, &cmd
, &flags
, &doexec
,
494 &opt_in
, &opt_out
, &opt_err
);
496 if (OPEN_READABLE_P(flags
)) {
497 if (pipe(pr
) == -1) {
498 mrb_sys_fail(mrb
, "pipe");
500 io_fd_cloexec(mrb
, pr
[0]);
501 io_fd_cloexec(mrb
, pr
[1]);
504 if (OPEN_WRITABLE_P(flags
)) {
505 if (pipe(pw
) == -1) {
506 if (pr
[0] != -1) close(pr
[0]);
507 if (pr
[1] != -1) close(pr
[1]);
508 mrb_sys_fail(mrb
, "pipe");
510 io_fd_cloexec(mrb
, pw
[0]);
511 io_fd_cloexec(mrb
, pw
[1]);
519 mrb_value result
= mrb_nil_value();
520 switch (pid
= fork()) {
531 if (OPEN_READABLE_P(flags
)) {
538 if (OPEN_WRITABLE_P(flags
)) {
546 for (int fd
= 3; fd
< NOFILE
; fd
++) {
549 io_process_exec(cmd
);
550 mrb_raisef(mrb
, E_IO_ERROR
, "command not found: %s", cmd
);
553 result
= mrb_nil_value();
556 default: /* parent */
560 if (OPEN_RDWR_P(flags
)) {
566 else if (OPEN_RDONLY_P(flags
)) {
575 struct mrb_io
*fptr
= io_alloc(mrb
);
577 fptr
->fd2
= write_fd
;
579 fptr
->readable
= OPEN_READABLE_P(flags
);
580 fptr
->writable
= OPEN_WRITABLE_P(flags
);
581 io_init_buf(mrb
, fptr
);
583 DATA_TYPE(io
) = &mrb_io_type
;
591 int saved_errno
= errno
;
592 if (OPEN_READABLE_P(flags
)) {
596 if (OPEN_WRITABLE_P(flags
)) {
601 mrb_sys_fail(mrb
, "pipe_open failed");
608 #endif /* TARGET_OS_IPHONE */
611 symdup(mrb_state
*mrb
, int fd
, mrb_bool
*failed
)
620 if (new_fd
> 0) *failed
= FALSE
;
625 io_init_copy(mrb_state
*mrb
, mrb_value copy
)
627 mrb_value orig
= mrb_get_arg1(mrb
);
628 struct mrb_io
*fptr_copy
;
629 struct mrb_io
*fptr_orig
;
630 mrb_bool failed
= TRUE
;
632 fptr_orig
= io_get_open_fptr(mrb
, orig
);
633 fptr_copy
= (struct mrb_io
*)DATA_PTR(copy
);
634 if (fptr_orig
== fptr_copy
) return copy
;
635 if (fptr_copy
!= NULL
) {
636 fptr_finalize(mrb
, fptr_copy
, FALSE
);
637 mrb_free(mrb
, fptr_copy
);
639 fptr_copy
= (struct mrb_io
*)io_alloc(mrb
);
640 fptr_copy
->pid
= fptr_orig
->pid
;
641 fptr_copy
->readable
= fptr_orig
->readable
;
642 fptr_copy
->writable
= fptr_orig
->writable
;
643 fptr_copy
->sync
= fptr_orig
->sync
;
644 fptr_copy
->is_socket
= fptr_orig
->is_socket
;
646 io_init_buf(mrb
, fptr_copy
);
648 DATA_TYPE(copy
) = &mrb_io_type
;
649 DATA_PTR(copy
) = fptr_copy
;
651 fptr_copy
->fd
= symdup(mrb
, fptr_orig
->fd
, &failed
);
653 mrb_sys_fail(mrb
, 0);
655 io_fd_cloexec(mrb
, fptr_copy
->fd
);
657 if (fptr_orig
->fd2
!= -1) {
658 fptr_copy
->fd2
= symdup(mrb
, fptr_orig
->fd2
, &failed
);
660 close(fptr_copy
->fd
);
661 mrb_sys_fail(mrb
, 0);
663 io_fd_cloexec(mrb
, fptr_copy
->fd2
);
670 check_file_descriptor(mrb_state
*mrb
, mrb_int fd
)
675 #if MRB_INT_MIN < INT_MIN || MRB_INT_MAX > INT_MAX
685 int len
= sizeof(err
);
687 if (getsockopt(fdi
, SOL_SOCKET
, SO_ERROR
, (char*)&err
, &len
) == 0) {
692 if (fdi
< 0 || fdi
> _getmaxstdio()) {
698 if (fstat(fdi
, &sb
) == 0) return;
699 if (errno
== EBADF
) goto badfd
;
703 mrb_sys_fail(mrb
, "bad file descriptor");
707 io_init(mrb_state
*mrb
, mrb_value io
)
711 mrb_value mode
, opt
; /* opt (Hash) will be ignored */
714 mode
= opt
= mrb_nil_value();
716 if (mrb_block_given_p(mrb
)) {
717 mrb_warn(mrb
, "File.new() does not take block; use File.open() instead");
719 mrb_get_args(mrb
, "i|oH", &fd
, &mode
, &opt
);
721 case 0: /* STDIN_FILENO */
722 case 1: /* STDOUT_FILENO */
723 case 2: /* STDERR_FILENO */
726 check_file_descriptor(mrb
, fd
);
729 flags
= io_mode_to_flags(mrb
, mode
);
731 fptr
= (struct mrb_io
*)DATA_PTR(io
);
733 fptr_finalize(mrb
, fptr
, TRUE
);
736 fptr
= io_alloc(mrb
);
738 DATA_TYPE(io
) = &mrb_io_type
;
742 fptr
->readable
= OPEN_READABLE_P(flags
);
743 fptr
->writable
= OPEN_WRITABLE_P(flags
);
744 io_init_buf(mrb
, fptr
);
749 fptr_finalize(mrb_state
*mrb
, struct mrb_io
*fptr
, int quiet
)
752 int limit
= quiet
? 3 : 0;
758 if (fptr
->fd
>= limit
) {
760 if (fptr
->is_socket
) {
761 if (fptr
->close_fd
&& closesocket(fptr
->fd
) != 0) {
762 saved_errno
= WSAGetLastError();
767 if (fptr
->fd
!= -1 && fptr
->close_fd
) {
768 if (close(fptr
->fd
) == -1) {
775 if (fptr
->fd2
>= limit
) {
776 if (fptr
->close_fd2
&& close(fptr
->fd2
) == -1) {
777 if (saved_errno
== 0) {
784 #ifndef MRB_NO_IO_POPEN
785 if (fptr
->pid
!= 0) {
790 pid
= waitpid(fptr
->pid
, &status
, 0);
791 } while (pid
== -1 && errno
== EINTR
);
792 if (!quiet
&& pid
== fptr
->pid
) {
793 io_set_process_status(mrb
, pid
, status
);
796 HANDLE h
= OpenProcess(PROCESS_QUERY_INFORMATION
, FALSE
, fptr
->pid
);
798 if (WaitForSingleObject(h
, INFINITE
) && GetExitCodeProcess(h
, &status
))
800 io_set_process_status(mrb
, fptr
->pid
, (int)status
);
804 /* Note: we don't raise an exception when waitpid(3) fails */
809 mrb_free(mrb
, fptr
->buf
);
813 if (!quiet
&& saved_errno
!= 0) {
815 mrb_sys_fail(mrb
, "fptr_finalize failed");
819 static struct mrb_io
*
820 io_get_read_fptr(mrb_state
*mrb
, mrb_value io
)
822 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
823 if (!fptr
->readable
) {
824 mrb_raise(mrb
, E_IO_ERROR
, "not opened for reading");
829 static struct mrb_io
*
830 io_get_write_fptr(mrb_state
*mrb
, mrb_value io
)
832 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
833 if (!fptr
->writable
) {
834 mrb_raise(mrb
, E_IO_ERROR
, "not opened for writing");
840 io_get_write_fd(struct mrb_io
*fptr
)
842 if (fptr
->fd2
== -1) {
851 io_isatty(mrb_state
*mrb
, mrb_value io
)
853 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
854 if (isatty(fptr
->fd
) == 0)
855 return mrb_false_value();
856 return mrb_true_value();
860 io_s_for_fd(mrb_state
*mrb
, mrb_value klass
)
862 struct RClass
*c
= mrb_class_ptr(klass
);
863 enum mrb_vtype ttype
= MRB_INSTANCE_TT(c
);
865 /* copied from mrb_instance_alloc() */
866 if (ttype
== 0) ttype
= MRB_TT_OBJECT
;
868 mrb_value obj
= mrb_obj_value((struct RObject
*)mrb_obj_alloc(mrb
, ttype
, c
));
869 return io_init(mrb
, obj
);
873 io_s_sysclose(mrb_state
*mrb
, mrb_value klass
)
877 mrb_get_args(mrb
, "i", &fd
);
878 if (close((int)fd
) == -1) {
879 mrb_sys_fail(mrb
, "close");
881 return mrb_fixnum_value(0);
885 io_cloexec_open(mrb_state
*mrb
, const char *pathname
, int flags
, fmode_t mode
)
888 char *fname
= mrb_locale_from_utf8(pathname
, -1);
892 /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
894 #elif defined O_NOINHERIT
895 flags
|= O_NOINHERIT
;
898 fd
= open(fname
, flags
, mode
);
904 mrb_garbage_collect(mrb
);
909 mrb_sys_fail(mrb
, RSTRING_CSTR(mrb
, mrb_format(mrb
, "open %s", pathname
)));
911 mrb_locale_free(fname
);
914 io_fd_cloexec(mrb
, fd
);
920 io_s_sysopen(mrb_state
*mrb
, mrb_value klass
)
922 mrb_value path
= mrb_nil_value();
923 mrb_value mode
= mrb_nil_value();
926 mrb_get_args(mrb
, "S|oi", &path
, &mode
, &perm
);
931 const char *pat
= RSTRING_CSTR(mrb
, path
);
932 int flags
= io_mode_to_flags(mrb
, mode
);
933 mrb_int fd
= io_cloexec_open(mrb
, pat
, flags
, (fmode_t
)perm
);
934 return mrb_fixnum_value(fd
);
938 eof_error(mrb_state
*mrb
)
940 mrb_raise(mrb
, E_EOF_ERROR
, "end of file reached");
944 io_read_common(mrb_state
*mrb
,
945 fssize_t (*readfunc
)(int, void*, fsize_t
, off_t
),
946 mrb_value io
, mrb_value buf
, mrb_int maxlen
, off_t offset
)
949 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "negative expanding string size");
951 else if (maxlen
== 0) {
952 return mrb_str_new(mrb
, NULL
, maxlen
);
955 if (mrb_nil_p(buf
)) {
956 buf
= mrb_str_new(mrb
, NULL
, maxlen
);
959 if (RSTRING_LEN(buf
) != maxlen
) {
960 buf
= mrb_str_resize(mrb
, buf
, maxlen
);
963 mrb_str_modify(mrb
, RSTRING(buf
));
966 struct mrb_io
*fptr
= io_get_read_fptr(mrb
, io
);
967 int ret
= readfunc(fptr
->fd
, RSTRING_PTR(buf
), (fsize_t
)maxlen
, offset
);
969 mrb_sys_fail(mrb
, "sysread failed");
971 if (RSTRING_LEN(buf
) != ret
) {
972 buf
= mrb_str_resize(mrb
, buf
, ret
);
974 if (ret
== 0 && maxlen
> 0) {
982 sysread(int fd
, void *buf
, fsize_t nbytes
, off_t offset
)
984 return (fssize_t
)read(fd
, buf
, nbytes
);
988 io_sysread(mrb_state
*mrb
, mrb_value io
)
990 mrb_value buf
= mrb_nil_value();
993 mrb_get_args(mrb
, "i|S", &maxlen
, &buf
);
995 return io_read_common(mrb
, sysread
, io
, buf
, maxlen
, 0);
999 io_sysseek(mrb_state
*mrb
, mrb_value io
)
1001 mrb_int offset
, whence
= -1;
1003 mrb_get_args(mrb
, "i|i", &offset
, &whence
);
1008 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
1009 off_t pos
= lseek(fptr
->fd
, (off_t
)offset
, (int)whence
);
1011 mrb_sys_fail(mrb
, "sysseek");
1014 if (sizeof(off_t
) > sizeof(mrb_int
) && pos
> (off_t
)MRB_INT_MAX
) {
1015 mrb_raise(mrb
, E_IO_ERROR
, "sysseek reached too far for mrb_int");
1017 return mrb_int_value(mrb
, (mrb_int
)pos
);
1021 io_seek(mrb_state
*mrb
, mrb_value io
)
1023 mrb_value pos
= io_sysseek(mrb
, io
);
1024 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
1026 fptr
->buf
->start
= 0;
1033 io_write_common(mrb_state
*mrb
,
1034 fssize_t (*writefunc
)(int, const void*, fsize_t
, off_t
),
1035 struct mrb_io
*fptr
, const void *buf
, mrb_ssize blen
, off_t offset
)
1037 int fd
= io_get_write_fd(fptr
);
1038 fssize_t length
= writefunc(fd
, buf
, (fsize_t
)blen
, offset
);
1040 mrb_sys_fail(mrb
, "syswrite");
1042 return mrb_int_value(mrb
, (mrb_int
)length
);
1046 syswrite(int fd
, const void *buf
, fsize_t nbytes
, off_t offset
)
1048 return (fssize_t
)write(fd
, buf
, nbytes
);
1052 io_syswrite(mrb_state
*mrb
, mrb_value io
)
1056 mrb_get_args(mrb
, "S", &buf
);
1058 return io_write_common(mrb
, syswrite
, io_get_write_fptr(mrb
, io
), RSTRING_PTR(buf
), RSTRING_LEN(buf
), 0);
1061 /* def write(string) */
1062 /* str = string.is_a?(String) ? string : string.to_s */
1063 /* return 0 if str.empty? */
1064 /* len = syswrite(str) */
1069 fd_write(mrb_state
*mrb
, int fd
, mrb_value str
)
1073 str
= mrb_obj_as_string(mrb
, str
);
1074 fssize_t len
= (fssize_t
)RSTRING_LEN(str
);
1075 if (len
== 0) return 0;
1077 for (fssize_t sum
=0; sum
<len
; sum
+=n
) {
1078 n
= write(fd
, RSTRING_PTR(str
), (fsize_t
)len
);
1080 mrb_sys_fail(mrb
, "syswrite");
1087 io_write(mrb_state
*mrb
, mrb_value io
)
1089 struct mrb_io
*fptr
= io_get_write_fptr(mrb
, io
);
1090 int fd
= io_get_write_fd(fptr
);
1092 if (fptr
->buf
&& fptr
->buf
->len
> 0) {
1095 /* get current position */
1096 n
= lseek(fd
, 0, SEEK_CUR
);
1097 if (n
== -1) mrb_sys_fail(mrb
, "lseek");
1099 n
= lseek(fd
, n
- fptr
->buf
->len
, SEEK_SET
);
1100 if (n
== -1) mrb_sys_fail(mrb
, "lseek(2)");
1101 fptr
->buf
->start
= fptr
->buf
->len
= 0;
1105 if (mrb_get_argc(mrb
) == 1) {
1106 len
= fd_write(mrb
, fd
, mrb_get_arg1(mrb
));
1112 mrb_get_args(mrb
, "*", &argv
, &argc
);
1114 len
+= fd_write(mrb
, fd
, *argv
++);
1117 return mrb_int_value(mrb
, len
);
1121 io_close(mrb_state
*mrb
, mrb_value io
)
1123 struct mrb_io
*fptr
;
1124 fptr
= io_get_open_fptr(mrb
, io
);
1125 fptr_finalize(mrb
, fptr
, FALSE
);
1126 return mrb_nil_value();
1130 io_close_write(mrb_state
*mrb
, mrb_value io
)
1132 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
1133 if (close((int)fptr
->fd2
) == -1) {
1134 mrb_sys_fail(mrb
, "close");
1136 return mrb_nil_value();
1140 io_closed(mrb_state
*mrb
, mrb_value io
)
1142 struct mrb_io
*fptr
= (struct mrb_io
*)mrb_data_get_ptr(mrb
, io
, &mrb_io_type
);
1143 if (fptr
== NULL
|| fptr
->fd
>= 0) {
1144 return mrb_false_value();
1147 return mrb_true_value();
1151 io_pos(mrb_state
*mrb
, mrb_value io
)
1153 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
1154 off_t pos
= lseek(fptr
->fd
, 0, SEEK_CUR
);
1155 if (pos
== -1) mrb_sys_fail(mrb
, 0);
1158 return mrb_int_value(mrb
, pos
- fptr
->buf
->len
);
1161 return mrb_int_value(mrb
, pos
);
1166 io_pid(mrb_state
*mrb
, mrb_value io
)
1168 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
1170 if (fptr
->pid
> 0) {
1171 return mrb_fixnum_value(fptr
->pid
);
1174 return mrb_nil_value();
1177 static struct timeval
1178 time2timeval(mrb_state
*mrb
, mrb_value time
)
1180 struct timeval t
= { 0, 0 };
1182 switch (mrb_type(time
)) {
1183 case MRB_TT_INTEGER
:
1184 t
.tv_sec
= (ftime_t
)mrb_integer(time
);
1188 #ifndef MRB_NO_FLOAT
1190 t
.tv_sec
= (ftime_t
)mrb_float(time
);
1191 t
.tv_usec
= (fsuseconds_t
)((mrb_float(time
) - t
.tv_sec
) * 1000000.0);
1196 mrb_raise(mrb
, E_TYPE_ERROR
, "wrong argument class");
1202 #if !defined(_WIN32) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
1204 io_s_pipe(mrb_state
*mrb
, mrb_value klass
)
1208 if (io_pipe(mrb
, pipes
) == -1) {
1209 mrb_sys_fail(mrb
, "pipe");
1212 mrb_value r
= mrb_obj_value(mrb_data_object_alloc(mrb
, mrb_class_ptr(klass
), NULL
, &mrb_io_type
));
1213 struct mrb_io
*fptr_r
= io_alloc(mrb
);
1214 fptr_r
->fd
= pipes
[0];
1215 fptr_r
->readable
= 1;
1216 DATA_TYPE(r
) = &mrb_io_type
;
1217 DATA_PTR(r
) = fptr_r
;
1218 io_init_buf(mrb
, fptr_r
);
1220 mrb_value w
= mrb_obj_value(mrb_data_object_alloc(mrb
, mrb_class_ptr(klass
), NULL
, &mrb_io_type
));
1221 struct mrb_io
*fptr_w
= io_alloc(mrb
);
1222 fptr_w
->fd
= pipes
[1];
1223 fptr_w
->writable
= 1;
1225 DATA_TYPE(w
) = &mrb_io_type
;
1226 DATA_PTR(w
) = fptr_w
;
1228 return mrb_assoc_new(mrb
, r
, w
);
1233 mrb_io_read_data_pending(mrb_state
*mrb
, struct mrb_io
*fptr
)
1235 if (fptr
->buf
&& fptr
->buf
->len
> 0) return 1;
1240 io_s_select(mrb_state
*mrb
, mrb_value klass
)
1242 const mrb_value
*argv
;
1244 mrb_value read_io
, list
;
1245 struct mrb_io
*fptr
;
1249 int interrupt_flag
= 0;
1251 mrb_get_args(mrb
, "*", &argv
, &argc
);
1253 if (argc
< 1 || argc
> 4) {
1254 mrb_argnum_error(mrb
, argc
, 1, 4);
1257 mrb_value timeout
= mrb_nil_value();
1258 mrb_value except
= mrb_nil_value();
1259 mrb_value write
= mrb_nil_value();
1266 mrb_value read
= argv
[0];
1268 struct timeval
*tp
, timerec
;
1269 if (mrb_nil_p(timeout
)) {
1273 timerec
= time2timeval(mrb
, timeout
);
1277 fd_set pset
, rset
, *rp
;
1279 if (!mrb_nil_p(read
)) {
1280 mrb_check_type(mrb
, read
, MRB_TT_ARRAY
);
1283 for (int i
= 0; i
< RARRAY_LEN(read
); i
++) {
1284 read_io
= RARRAY_PTR(read
)[i
];
1285 fptr
= io_get_open_fptr(mrb
, read_io
);
1286 if (fptr
->fd
>= FD_SETSIZE
) continue;
1287 FD_SET(fptr
->fd
, rp
);
1288 if (mrb_io_read_data_pending(mrb
, fptr
)) {
1290 FD_SET(fptr
->fd
, &pset
);
1296 timerec
.tv_sec
= timerec
.tv_usec
= 0;
1305 if (!mrb_nil_p(write
)) {
1306 mrb_check_type(mrb
, write
, MRB_TT_ARRAY
);
1309 for (int i
= 0; i
< RARRAY_LEN(write
); i
++) {
1310 fptr
= io_get_open_fptr(mrb
, RARRAY_PTR(write
)[i
]);
1311 if (fptr
->fd
>= FD_SETSIZE
) continue;
1312 FD_SET(fptr
->fd
, wp
);
1315 if (fptr
->fd2
>= 0) {
1316 FD_SET(fptr
->fd2
, wp
);
1317 if (max
< fptr
->fd2
)
1327 if (!mrb_nil_p(except
)) {
1328 mrb_check_type(mrb
, except
, MRB_TT_ARRAY
);
1331 for (int i
= 0; i
< RARRAY_LEN(except
); i
++) {
1332 fptr
= io_get_open_fptr(mrb
, RARRAY_PTR(except
)[i
]);
1333 if (fptr
->fd
>= FD_SETSIZE
) continue;
1334 FD_SET(fptr
->fd
, ep
);
1337 if (fptr
->fd2
>= 0) {
1338 FD_SET(fptr
->fd2
, ep
);
1339 if (max
< fptr
->fd2
)
1352 n
= select(max
, rp
, wp
, ep
, tp
);
1355 errno
= WSAGetLastError();
1356 if (errno
!= WSAEINTR
)
1357 mrb_sys_fail(mrb
, "select failed");
1360 mrb_sys_fail(mrb
, "select failed");
1367 if (!pending
&& n
== 0)
1368 return mrb_nil_value();
1370 result
= mrb_ary_new_capa(mrb
, 3);
1371 mrb_ary_push(mrb
, result
, rp
? mrb_ary_new(mrb
) : mrb_ary_new_capa(mrb
, 0));
1372 mrb_ary_push(mrb
, result
, wp
? mrb_ary_new(mrb
) : mrb_ary_new_capa(mrb
, 0));
1373 mrb_ary_push(mrb
, result
, ep
? mrb_ary_new(mrb
) : mrb_ary_new_capa(mrb
, 0));
1375 if (interrupt_flag
== 0) {
1377 list
= RARRAY_PTR(result
)[0];
1378 for (int i
= 0; i
< RARRAY_LEN(read
); i
++) {
1379 fptr
= io_get_open_fptr(mrb
, RARRAY_PTR(read
)[i
]);
1380 if (FD_ISSET(fptr
->fd
, rp
) ||
1381 FD_ISSET(fptr
->fd
, &pset
)) {
1382 mrb_ary_push(mrb
, list
, RARRAY_PTR(read
)[i
]);
1388 list
= RARRAY_PTR(result
)[1];
1389 for (int i
= 0; i
< RARRAY_LEN(write
); i
++) {
1390 fptr
= io_get_open_fptr(mrb
, RARRAY_PTR(write
)[i
]);
1391 if (FD_ISSET(fptr
->fd
, wp
)) {
1392 mrb_ary_push(mrb
, list
, RARRAY_PTR(write
)[i
]);
1394 else if (fptr
->fd2
>= 0 && FD_ISSET(fptr
->fd2
, wp
)) {
1395 mrb_ary_push(mrb
, list
, RARRAY_PTR(write
)[i
]);
1401 list
= RARRAY_PTR(result
)[2];
1402 for (int i
= 0; i
< RARRAY_LEN(except
); i
++) {
1403 fptr
= io_get_open_fptr(mrb
, RARRAY_PTR(except
)[i
]);
1404 if (FD_ISSET(fptr
->fd
, ep
)) {
1405 mrb_ary_push(mrb
, list
, RARRAY_PTR(except
)[i
]);
1407 else if (fptr
->fd2
>= 0 && FD_ISSET(fptr
->fd2
, ep
)) {
1408 mrb_ary_push(mrb
, list
, RARRAY_PTR(except
)[i
]);
1418 mrb_io_fileno(mrb_state
*mrb
, mrb_value io
)
1420 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
1425 io_fileno(mrb_state
*mrb
, mrb_value io
)
1427 int fd
= mrb_io_fileno(mrb
, io
);
1428 return mrb_fixnum_value(fd
);
1431 #if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
1433 io_close_on_exec_p(mrb_state
*mrb
, mrb_value io
)
1435 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
1438 if (fptr
->fd2
>= 0) {
1439 if ((ret
= fcntl(fptr
->fd2
, F_GETFD
)) == -1) mrb_sys_fail(mrb
, "F_GETFD failed");
1440 if (!(ret
& FD_CLOEXEC
)) return mrb_false_value();
1443 if ((ret
= fcntl(fptr
->fd
, F_GETFD
)) == -1) mrb_sys_fail(mrb
, "F_GETFD failed");
1444 if (!(ret
& FD_CLOEXEC
)) return mrb_false_value();
1445 return mrb_true_value();
1448 # define io_close_on_exec_p mrb_notimplement_m
1451 #if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
1453 io_set_close_on_exec(mrb_state
*mrb
, mrb_value io
)
1456 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
1459 mrb_get_args(mrb
, "b", &b
);
1461 int flag
= b
? FD_CLOEXEC
: 0;
1464 if (fptr
->fd2
>= 0) {
1465 if ((ret
= fcntl(fptr
->fd2
, F_GETFD
)) == -1) mrb_sys_fail(mrb
, "F_GETFD failed");
1466 if ((ret
& FD_CLOEXEC
) != flag
) {
1467 ret
= (ret
& ~FD_CLOEXEC
) | flag
;
1468 ret
= fcntl(fptr
->fd2
, F_SETFD
, ret
);
1470 if (ret
== -1) mrb_sys_fail(mrb
, "F_SETFD failed");
1474 if ((ret
= fcntl(fptr
->fd
, F_GETFD
)) == -1) mrb_sys_fail(mrb
, "F_GETFD failed");
1475 if ((ret
& FD_CLOEXEC
) != flag
) {
1476 ret
= (ret
& ~FD_CLOEXEC
) | flag
;
1477 ret
= fcntl(fptr
->fd
, F_SETFD
, ret
);
1478 if (ret
== -1) mrb_sys_fail(mrb
, "F_SETFD failed");
1481 return mrb_bool_value(b
);
1484 # define io_set_close_on_exec mrb_notimplement_m
1488 io_set_sync(mrb_state
*mrb
, mrb_value io
)
1490 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
1493 mrb_get_args(mrb
, "b", &b
);
1495 return mrb_bool_value(b
);
1499 io_sync(mrb_state
*mrb
, mrb_value io
)
1501 struct mrb_io
*fptr
= io_get_open_fptr(mrb
, io
);
1502 return mrb_bool_value(fptr
->sync
);
1505 #ifndef MRB_USE_IO_PREAD_PWRITE
1506 # define io_pread mrb_notimplement_m
1507 # define io_pwrite mrb_notimplement_m
1510 value2off(mrb_state
*mrb
, mrb_value offv
)
1512 return (off_t
)mrb_as_int(mrb
, offv
);
1517 * pread(maxlen, offset, outbuf = "") -> outbuf
1520 io_pread(mrb_state
*mrb
, mrb_value io
)
1522 mrb_value buf
= mrb_nil_value();
1526 mrb_get_args(mrb
, "io|S!", &maxlen
, &off
, &buf
);
1528 return io_read_common(mrb
, pread
, io
, buf
, maxlen
, value2off(mrb
, off
));
1533 * pwrite(buffer, offset) -> wrote_bytes
1536 io_pwrite(mrb_state
*mrb
, mrb_value io
)
1540 mrb_get_args(mrb
, "So", &buf
, &off
);
1542 return io_write_common(mrb
, pwrite
, io_get_write_fptr(mrb
, io
), RSTRING_PTR(buf
), RSTRING_LEN(buf
), value2off(mrb
, off
));
1544 #endif /* MRB_USE_IO_PREAD_PWRITE */
1547 io_ungetc(mrb_state
*mrb
, mrb_value io
)
1549 struct mrb_io
*fptr
= io_get_read_fptr(mrb
, io
);
1550 struct mrb_io_buf
*buf
= fptr
->buf
;
1553 mrb_get_args(mrb
, "S", &str
);
1554 mrb_int len
= RSTRING_LEN(str
);
1555 if (len
> SHRT_MAX
) {
1556 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "string too long to ungetc");
1558 if (len
> MRB_IO_BUF_SIZE
- buf
->len
) {
1559 fptr
->buf
= (struct mrb_io_buf
*)mrb_realloc(mrb
, buf
, sizeof(struct mrb_io_buf
)+buf
->len
+len
-MRB_IO_BUF_SIZE
);
1562 memmove(buf
->mem
+len
, buf
->mem
+buf
->start
, buf
->len
);
1563 memcpy(buf
->mem
, RSTRING_PTR(str
), len
);
1565 buf
->len
+= (short)len
;
1566 return mrb_nil_value();
1570 io_buf_reset(struct mrb_io_buf
*buf
)
1577 io_buf_shift(struct mrb_io_buf
*buf
, mrb_int n
)
1579 mrb_assert(n
<= SHRT_MAX
);
1580 buf
->start
+= (short)n
;
1581 buf
->len
-= (short)n
;
1584 #ifdef MRB_UTF8_STRING
1586 io_fill_buf_comp(mrb_state
*mrb
, struct mrb_io
*fptr
)
1588 struct mrb_io_buf
*buf
= fptr
->buf
;
1589 int keep
= buf
->len
;
1591 memmove(buf
->mem
, buf
->mem
+buf
->start
, keep
);
1592 int n
= read(fptr
->fd
, buf
->mem
+keep
, MRB_IO_BUF_SIZE
-keep
);
1593 if (n
< 0) mrb_sys_fail(mrb
, 0);
1594 if (n
== 0) fptr
->eof
= 1;
1596 buf
->len
+= (short)n
;
1601 io_fill_buf(mrb_state
*mrb
, struct mrb_io
*fptr
)
1603 struct mrb_io_buf
*buf
= fptr
->buf
;
1605 if (buf
->len
> 0) return;
1607 int n
= read(fptr
->fd
, buf
->mem
, MRB_IO_BUF_SIZE
);
1608 if (n
< 0) mrb_sys_fail(mrb
, 0);
1609 if (n
== 0) fptr
->eof
= 1;
1611 buf
->len
= (short)n
;
1615 io_eof(mrb_state
*mrb
, mrb_value io
)
1617 struct mrb_io
*fptr
= io_get_read_fptr(mrb
, io
);
1619 if (fptr
->eof
) return mrb_true_value();
1620 if (fptr
->buf
->len
> 0) return mrb_false_value();
1621 io_fill_buf(mrb
, fptr
);
1622 return mrb_bool_value(fptr
->eof
);
1626 io_buf_cat(mrb_state
*mrb
, mrb_value outbuf
, struct mrb_io_buf
*buf
, mrb_int n
)
1628 mrb_assert(n
<= buf
->len
);
1629 mrb_str_cat(mrb
, outbuf
, buf
->mem
+buf
->start
, n
);
1630 io_buf_shift(buf
, n
);
1634 io_buf_cat_all(mrb_state
*mrb
, mrb_value outbuf
, struct mrb_io_buf
*buf
)
1636 mrb_str_cat(mrb
, outbuf
, buf
->mem
+buf
->start
, buf
->len
);
1641 io_read_all(mrb_state
*mrb
, struct mrb_io
*fptr
, mrb_value outbuf
)
1644 io_fill_buf(mrb
, fptr
);
1648 io_buf_cat_all(mrb
, outbuf
, fptr
->buf
);
1653 io_reset_outbuf(mrb_state
*mrb
, mrb_value outbuf
, mrb_int len
)
1655 if (mrb_nil_p(outbuf
)) {
1656 outbuf
= mrb_str_new(mrb
, NULL
, 0);
1659 mrb_str_modify(mrb
, mrb_str_ptr(outbuf
));
1660 RSTR_SET_LEN(mrb_str_ptr(outbuf
), 0);
1666 io_read(mrb_state
*mrb
, mrb_value io
)
1668 mrb_value outbuf
= mrb_nil_value();
1671 mrb_bool length_given
;
1672 struct mrb_io
*fptr
= io_get_read_fptr(mrb
, io
);
1674 mrb_get_args(mrb
, "|o?S", &len
, &length_given
, &outbuf
);
1676 if (mrb_nil_p(len
)) {
1677 length_given
= FALSE
;
1680 length
= mrb_as_int(mrb
, len
);
1682 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "negative length %i given", length
);
1685 return io_reset_outbuf(mrb
, outbuf
, 0);
1690 outbuf
= io_reset_outbuf(mrb
, outbuf
, MRB_IO_BUF_SIZE
);
1691 if (!length_given
) { /* read as much as possible */
1692 return io_read_all(mrb
, fptr
, outbuf
);
1695 struct mrb_io_buf
*buf
= fptr
->buf
;
1698 io_fill_buf(mrb
, fptr
);
1699 if (fptr
->eof
|| length
== 0) {
1700 if (RSTRING_LEN(outbuf
) == 0)
1701 return mrb_nil_value();
1704 if (buf
->len
< length
) {
1706 io_buf_cat_all(mrb
, outbuf
, buf
);
1709 io_buf_cat(mrb
, outbuf
, buf
, length
);
1716 io_find_index(struct mrb_io
*fptr
, const char *rs
, mrb_int rslen
)
1718 struct mrb_io_buf
*buf
= fptr
->buf
;
1720 mrb_assert(rslen
> 0);
1721 const char c
= rs
[0];
1722 const mrb_int limit
= buf
->len
- rslen
+ 1;
1723 const char *p
= buf
->mem
+buf
->start
;
1724 for (mrb_int i
=0; i
<limit
; i
++) {
1725 if (p
[i
] == c
&& (rslen
== 1 || memcmp(p
+i
, rs
, rslen
) == 0)) {
1733 io_gets(mrb_state
*mrb
, mrb_value io
)
1735 mrb_value rs
= mrb_nil_value();
1736 mrb_bool rs_given
= FALSE
; /* newline break */
1738 mrb_bool limit_given
= FALSE
; /* no limit */
1739 struct mrb_io
*fptr
= io_get_read_fptr(mrb
, io
);
1740 struct mrb_io_buf
*buf
= fptr
->buf
;
1742 mrb_get_args(mrb
, "|o?i?", &rs
, &rs_given
, &limit
, &limit_given
);
1744 if (limit_given
== FALSE
) {
1746 if (mrb_nil_p(rs
)) {
1749 else if (mrb_integer_p(rs
)) {
1750 limit
= mrb_integer(rs
);
1752 rs
= mrb_nil_value();
1754 else if (!mrb_string_p(rs
)) {
1755 mrb_ensure_int_type(mrb
, rs
);
1760 if (mrb_nil_p(rs
)) {
1764 mrb_ensure_string_type(mrb
, rs
);
1765 if (RSTRING_LEN(rs
) == 0) { /* paragraph mode */
1766 rs
= mrb_str_new_lit(mrb
, "\n\n");
1771 rs
= mrb_str_new_lit(mrb
, "\n");
1775 /* from now on rs_given==FALSE means no RS */
1776 if (mrb_nil_p(rs
) && !limit_given
) {
1777 return io_read_all(mrb
, fptr
, mrb_str_new_capa(mrb
, MRB_IO_BUF_SIZE
));
1780 io_fill_buf(mrb
, fptr
);
1781 if (fptr
->eof
) return mrb_nil_value();
1785 if (limit
== 0) return mrb_str_new(mrb
, NULL
, 0);
1786 outbuf
= mrb_str_new_capa(mrb
, limit
);
1789 outbuf
= mrb_str_new(mrb
, NULL
, 0);
1793 if (rs_given
) { /* with RS */
1794 mrb_int rslen
= RSTRING_LEN(rs
);
1795 mrb_int idx
= io_find_index(fptr
, RSTRING_PTR(rs
), rslen
);
1796 if (idx
>= 0) { /* found */
1797 mrb_int n
= idx
+rslen
;
1798 if (limit_given
&& limit
< n
) {
1801 io_buf_cat(mrb
, outbuf
, buf
, n
);
1806 if (limit
<= buf
->len
) {
1807 io_buf_cat(mrb
, outbuf
, buf
, limit
);
1812 io_buf_cat_all(mrb
, outbuf
, buf
);
1813 io_fill_buf(mrb
, fptr
);
1815 if (RSTRING_LEN(outbuf
) == 0) return mrb_nil_value();
1822 io_readline(mrb_state
*mrb
, mrb_value io
)
1824 mrb_value result
= io_gets(mrb
, io
);
1825 if (mrb_nil_p(result
)) {
1832 io_readlines(mrb_state
*mrb
, mrb_value io
)
1834 mrb_value ary
= mrb_ary_new(mrb
);
1836 mrb_value line
= io_gets(mrb
, io
);
1838 if (mrb_nil_p(line
)) return ary
;
1839 mrb_ary_push(mrb
, ary
, line
);
1844 io_getc(mrb_state
*mrb
, mrb_value io
)
1847 struct mrb_io
*fptr
= io_get_read_fptr(mrb
, io
);
1848 struct mrb_io_buf
*buf
= fptr
->buf
;
1850 io_fill_buf(mrb
, fptr
);
1851 if (fptr
->eof
) return mrb_nil_value();
1852 #ifdef MRB_UTF8_STRING
1853 const char *p
= &buf
->mem
[buf
->start
];
1855 len
= mrb_utf8len(p
, p
+buf
->len
);
1856 if (len
== 1 && buf
->len
< 4) { /* partial UTF-8 */
1857 io_fill_buf_comp(mrb
, fptr
);
1858 p
= &buf
->mem
[buf
->start
];
1859 len
= mrb_utf8len(p
, p
+buf
->len
);
1863 mrb_value str
= mrb_str_new(mrb
, buf
->mem
+buf
->start
, len
);
1864 io_buf_shift(buf
, len
);
1869 io_readchar(mrb_state
*mrb
, mrb_value io
)
1871 mrb_value result
= io_getc(mrb
, io
);
1872 if (mrb_nil_p(result
)) {
1879 io_getbyte(mrb_state
*mrb
, mrb_value io
)
1881 struct mrb_io
*fptr
= io_get_read_fptr(mrb
, io
);
1882 struct mrb_io_buf
*buf
= fptr
->buf
;
1884 io_fill_buf(mrb
, fptr
);
1885 if (fptr
->eof
) return mrb_nil_value();
1887 unsigned char c
= buf
->mem
[buf
->start
];
1888 io_buf_shift(buf
, 1);
1889 return mrb_int_value(mrb
, (mrb_int
)c
);
1893 io_readbyte(mrb_state
*mrb
, mrb_value io
)
1895 mrb_value result
= io_getbyte(mrb
, io
);
1896 if (mrb_nil_p(result
)) {
1903 io_flush(mrb_state
*mrb
, mrb_value io
)
1905 io_get_open_fptr(mrb
, io
);
1910 mrb_init_io(mrb_state
*mrb
)
1912 struct RClass
*io
= mrb_define_class_id(mrb
, MRB_SYM(IO
), mrb
->object_class
);
1913 MRB_SET_INSTANCE_TT(io
, MRB_TT_CDATA
);
1915 mrb_include_module(mrb
, io
, mrb_module_get_id(mrb
, MRB_SYM(Enumerable
))); /* 15.2.20.3 */
1916 mrb_define_class_method_id(mrb
, io
, MRB_SYM(_popen
), io_s_popen
, MRB_ARGS_ARG(1,2));
1917 mrb_define_class_method_id(mrb
, io
, MRB_SYM(_sysclose
), io_s_sysclose
, MRB_ARGS_REQ(1));
1918 mrb_define_class_method_id(mrb
, io
, MRB_SYM(for_fd
), io_s_for_fd
, MRB_ARGS_ARG(1,2));
1919 mrb_define_class_method_id(mrb
, io
, MRB_SYM(select
), io_s_select
, MRB_ARGS_ARG(1,3));
1920 mrb_define_class_method_id(mrb
, io
, MRB_SYM(sysopen
), io_s_sysopen
, MRB_ARGS_ARG(1,2));
1921 #if !defined(_WIN32) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
1922 mrb_define_class_method_id(mrb
, io
, MRB_SYM(_pipe
), io_s_pipe
, MRB_ARGS_NONE());
1925 mrb_define_method_id(mrb
, io
, MRB_SYM(initialize
), io_init
, MRB_ARGS_ARG(1,2));
1926 mrb_define_method_id(mrb
, io
, MRB_SYM(initialize_copy
), io_init_copy
, MRB_ARGS_REQ(1));
1927 mrb_define_method_id(mrb
, io
, MRB_SYM(isatty
), io_isatty
, MRB_ARGS_NONE());
1928 mrb_define_method_id(mrb
, io
, MRB_SYM_Q(eof
), io_eof
, MRB_ARGS_NONE()); /* 15.2.20.5.6 */
1929 mrb_define_method_id(mrb
, io
, MRB_SYM(getc
), io_getc
, MRB_ARGS_NONE()); /* 15.2.20.5.8 */
1930 mrb_define_method_id(mrb
, io
, MRB_SYM(gets
), io_gets
, MRB_ARGS_OPT(2)); /* 15.2.20.5.9 */
1931 mrb_define_method_id(mrb
, io
, MRB_SYM(read
), io_read
, MRB_ARGS_OPT(2)); /* 15.2.20.5.14 */
1932 mrb_define_method_id(mrb
, io
, MRB_SYM(readchar
), io_readchar
, MRB_ARGS_NONE()); /* 15.2.20.5.15 */
1933 mrb_define_method_id(mrb
, io
, MRB_SYM(readline
), io_readline
, MRB_ARGS_OPT(2)); /* 15.2.20.5.16 */
1934 mrb_define_method_id(mrb
, io
, MRB_SYM(readlines
), io_readlines
, MRB_ARGS_OPT(2)); /* 15.2.20.5.17 */
1935 mrb_define_method_id(mrb
, io
, MRB_SYM(sync
), io_sync
, MRB_ARGS_NONE()); /* 15.2.20.5.18 */
1936 mrb_define_method_id(mrb
, io
, MRB_SYM_E(sync
), io_set_sync
, MRB_ARGS_REQ(1)); /* 15.2.20.5.19 */
1937 mrb_define_method_id(mrb
, io
, MRB_SYM(sysread
), io_sysread
, MRB_ARGS_ARG(1,1));
1938 mrb_define_method_id(mrb
, io
, MRB_SYM(sysseek
), io_sysseek
, MRB_ARGS_ARG(1,1));
1939 mrb_define_method_id(mrb
, io
, MRB_SYM(syswrite
), io_syswrite
, MRB_ARGS_REQ(1));
1940 mrb_define_method_id(mrb
, io
, MRB_SYM(seek
), io_seek
, MRB_ARGS_ARG(1,1));
1941 mrb_define_method_id(mrb
, io
, MRB_SYM(close
), io_close
, MRB_ARGS_NONE()); /* 15.2.20.5.1 */
1942 mrb_define_method_id(mrb
, io
, MRB_SYM(close_write
), io_close_write
, MRB_ARGS_NONE());
1943 mrb_define_method_id(mrb
, io
, MRB_SYM_E(close_on_exec
), io_set_close_on_exec
, MRB_ARGS_REQ(1));
1944 mrb_define_method_id(mrb
, io
, MRB_SYM_Q(close_on_exec
), io_close_on_exec_p
, MRB_ARGS_NONE());
1945 mrb_define_method_id(mrb
, io
, MRB_SYM_Q(closed
), io_closed
, MRB_ARGS_NONE()); /* 15.2.20.5.2 */
1946 mrb_define_method_id(mrb
, io
, MRB_SYM(flush
), io_flush
, MRB_ARGS_NONE()); /* 15.2.20.5.7 */
1947 mrb_define_method_id(mrb
, io
, MRB_SYM(ungetc
), io_ungetc
, MRB_ARGS_REQ(1));
1948 mrb_define_method_id(mrb
, io
, MRB_SYM(pos
), io_pos
, MRB_ARGS_NONE());
1949 mrb_define_method_id(mrb
, io
, MRB_SYM(pid
), io_pid
, MRB_ARGS_NONE());
1950 mrb_define_method_id(mrb
, io
, MRB_SYM(fileno
), io_fileno
, MRB_ARGS_NONE());
1951 mrb_define_method_id(mrb
, io
, MRB_SYM(write
), io_write
, MRB_ARGS_ANY()); /* 15.2.20.5.20 */
1952 mrb_define_method_id(mrb
, io
, MRB_SYM(pread
), io_pread
, MRB_ARGS_ANY()); /* ruby 2.5 feature */
1953 mrb_define_method_id(mrb
, io
, MRB_SYM(pwrite
), io_pwrite
, MRB_ARGS_ANY()); /* ruby 2.5 feature */
1954 mrb_define_method_id(mrb
, io
, MRB_SYM(getbyte
), io_getbyte
, MRB_ARGS_NONE());
1955 mrb_define_method_id(mrb
, io
, MRB_SYM(readbyte
), io_readbyte
, MRB_ARGS_NONE());
1957 mrb_define_const_id(mrb
, io
, MRB_SYM(SEEK_SET
), mrb_fixnum_value(SEEK_SET
));
1958 mrb_define_const_id(mrb
, io
, MRB_SYM(SEEK_CUR
), mrb_fixnum_value(SEEK_CUR
));
1959 mrb_define_const_id(mrb
, io
, MRB_SYM(SEEK_END
), mrb_fixnum_value(SEEK_END
));