3131 typedef long ftime_t ;
3232 typedef long fsuseconds_t ;
3333 typedef int fmode_t ;
34+ typedef int mrb_io_read_write_size ;
3435
3536 #ifndef O_TMPFILE
3637 #define O_TMPFILE O_TEMPORARY
4344 typedef time_t ftime_t ;
4445 typedef suseconds_t fsuseconds_t ;
4546 typedef mode_t fmode_t ;
47+ typedef ssize_t mrb_io_read_write_size ;
4648#endif
4749
4850#ifdef _MSC_VER
@@ -845,15 +847,35 @@ mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass)
845847 return mrb_fixnum_value (fd );
846848}
847849
850+ static mrb_value mrb_io_sysread_common (mrb_state * mrb ,
851+ mrb_io_read_write_size (* readfunc )(int , void * , fsize_t , off_t ),
852+ mrb_value io , mrb_value buf , mrb_int maxlen , off_t offset );
853+
854+ static mrb_io_read_write_size
855+ mrb_sysread_dummy (int fd , void * buf , fsize_t nbytes , off_t offset )
856+ {
857+ return (mrb_io_read_write_size )read (fd , buf , nbytes );
858+ }
859+
848860mrb_value
849861mrb_io_sysread (mrb_state * mrb , mrb_value io )
850862{
851- struct mrb_io * fptr ;
852863 mrb_value buf = mrb_nil_value ();
853864 mrb_int maxlen ;
854- int ret ;
855865
856866 mrb_get_args (mrb , "i|S" , & maxlen , & buf );
867+
868+ return mrb_io_sysread_common (mrb , mrb_sysread_dummy , io , buf , maxlen , 0 );
869+ }
870+
871+ static mrb_value
872+ mrb_io_sysread_common (mrb_state * mrb ,
873+ mrb_io_read_write_size (* readfunc )(int , void * , fsize_t , off_t ),
874+ mrb_value io , mrb_value buf , mrb_int maxlen , off_t offset )
875+ {
876+ struct mrb_io * fptr ;
877+ int ret ;
878+
857879 if (maxlen < 0 ) {
858880 mrb_raise (mrb , E_ARGUMENT_ERROR , "negative expanding string size" );
859881 }
@@ -875,7 +897,7 @@ mrb_io_sysread(mrb_state *mrb, mrb_value io)
875897 if (!fptr -> readable ) {
876898 mrb_raise (mrb , E_IO_ERROR , "not opened for reading" );
877899 }
878- ret = read (fptr -> fd , RSTRING_PTR (buf ), (fsize_t )maxlen );
900+ ret = readfunc (fptr -> fd , RSTRING_PTR (buf ), (fsize_t )maxlen , offset );
879901 switch (ret ) {
880902 case 0 : /* EOF */
881903 if (maxlen == 0 ) {
@@ -925,27 +947,44 @@ mrb_io_sysseek(mrb_state *mrb, mrb_value io)
925947 }
926948}
927949
950+ static mrb_value mrb_io_syswrite_common (mrb_state * mrb ,
951+ mrb_io_read_write_size (* writefunc )(int , const void * , fsize_t , off_t ),
952+ mrb_value io , mrb_value buf , off_t offset );
953+
954+ static mrb_io_read_write_size
955+ mrb_syswrite_dummy (int fd , const void * buf , fsize_t nbytes , off_t offset )
956+ {
957+ return (mrb_io_read_write_size )write (fd , buf , nbytes );
958+ }
959+
928960mrb_value
929961mrb_io_syswrite (mrb_state * mrb , mrb_value io )
962+ {
963+ mrb_value buf ;
964+
965+ mrb_get_args (mrb , "S" , & buf );
966+
967+ return mrb_io_syswrite_common (mrb , mrb_syswrite_dummy , io , buf , 0 );
968+ }
969+
970+ static mrb_value mrb_io_syswrite_common (mrb_state * mrb ,
971+ mrb_io_read_write_size (* writefunc )(int , const void * , fsize_t , off_t ),
972+ mrb_value io , mrb_value buf , off_t offset )
930973{
931974 struct mrb_io * fptr ;
932- mrb_value str , buf ;
933975 int fd , length ;
934976
935977 fptr = io_get_open_fptr (mrb , io );
936978 if (! fptr -> writable ) {
937979 mrb_raise (mrb , E_IO_ERROR , "not opened for writing" );
938980 }
939981
940- mrb_get_args (mrb , "S" , & str );
941- buf = str ;
942-
943982 if (fptr -> fd2 == -1 ) {
944983 fd = fptr -> fd ;
945984 } else {
946985 fd = fptr -> fd2 ;
947986 }
948- length = write (fd , RSTRING_PTR (buf ), (fsize_t )RSTRING_LEN (buf ));
987+ length = writefunc (fd , RSTRING_PTR (buf ), (fsize_t )RSTRING_LEN (buf ), offset );
949988 if (length == -1 ) {
950989 mrb_sys_fail (mrb , 0 );
951990 }
@@ -1328,6 +1367,62 @@ mrb_io_sync(mrb_state *mrb, mrb_value self)
13281367 return mrb_bool_value (fptr -> sync );
13291368}
13301369
1370+ #ifndef MRB_WITH_IO_PREAD_PWRITE
1371+ # define mrb_io_pread mrb_notimplement_m
1372+ # define mrb_io_pwrite mrb_notimplement_m
1373+ #else
1374+ static off_t
1375+ value2off (mrb_state * mrb , mrb_value offv )
1376+ {
1377+ switch (mrb_type (offv )) {
1378+ #ifndef MRB_WITHOUT_FLOAT
1379+ case MRB_TT_FLOAT :
1380+ {
1381+ mrb_float tmp = mrb_float (offv );
1382+ if (tmp < INT64_MIN || tmp > INT64_MAX ) {
1383+ /* fall through to use convert by `mrb_int()` (and raise error if out of range) */
1384+ } else {
1385+ return (off_t )tmp ;
1386+ }
1387+ }
1388+ /* fall through */
1389+ #endif /* MRB_WITHOUT_FLOAT */
1390+ default :
1391+ return (off_t )mrb_int (mrb , offv );
1392+ }
1393+ }
1394+
1395+ /*
1396+ * call-seq:
1397+ * pread(maxlen, offset, outbuf = "") -> outbuf
1398+ */
1399+ static mrb_value
1400+ mrb_io_pread (mrb_state * mrb , mrb_value io )
1401+ {
1402+ mrb_value buf = mrb_nil_value ();
1403+ mrb_value off ;
1404+ mrb_int maxlen ;
1405+
1406+ mrb_get_args (mrb , "io|S!" , & maxlen , & off , & buf );
1407+
1408+ return mrb_io_sysread_common (mrb , pread , io , buf , maxlen , value2off (mrb , off ));
1409+ }
1410+
1411+ /*
1412+ * call-seq:
1413+ * pwrite(buffer, offset) -> wrote_bytes
1414+ */
1415+ static mrb_value
1416+ mrb_io_pwrite (mrb_state * mrb , mrb_value io )
1417+ {
1418+ mrb_value buf , off ;
1419+
1420+ mrb_get_args (mrb , "So" , & buf , & off );
1421+
1422+ return mrb_io_syswrite_common (mrb , pwrite , io , buf , value2off (mrb , off ));
1423+ }
1424+ #endif /* MRB_WITH_IO_PREAD_PWRITE */
1425+
13311426static mrb_value
13321427io_bufread (mrb_state * mrb , mrb_value self )
13331428{
@@ -1383,6 +1478,8 @@ mrb_init_io(mrb_state *mrb)
13831478 mrb_define_method (mrb , io , "closed?" , mrb_io_closed , MRB_ARGS_NONE ()); /* 15.2.20.5.2 */
13841479 mrb_define_method (mrb , io , "pid" , mrb_io_pid , MRB_ARGS_NONE ()); /* 15.2.20.5.2 */
13851480 mrb_define_method (mrb , io , "fileno" , mrb_io_fileno_m , MRB_ARGS_NONE ());
1481+ mrb_define_method (mrb , io , "pread" , mrb_io_pread , MRB_ARGS_ANY ()); /* ruby 2.5 feature */
1482+ mrb_define_method (mrb , io , "pwrite" , mrb_io_pwrite , MRB_ARGS_ANY ()); /* ruby 2.5 feature */
13861483
13871484 mrb_define_class_method (mrb , io , "_bufread" , io_bufread , MRB_ARGS_REQ (2 ));
13881485}
0 commit comments