mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* win32/win32.c, include/ruby/win32.h (rb_w32_fd_is_text): new function.
* win32/win32.c (init_stdhandle): set default mode of stdin as binmode. * io.c (set_binary_mode_with_seek_cur): new function to replace SET_BINARY_MODE_WITH_SEEK_CUR macro. now returns previous mode of the fd and take care of LF in rbuf. * io.c (do_writeconv): set text mode when needed. * io.c (io_read): need to change the mode of the IO to binmode temporally when the length for IO#read, because IO#read with length must behave so. * test/ruby/test_io_m17n.rb (TestIO_M17N#est_{read_with_length, read_with_length_binmode,get[cs]_and_read_with_binmode, read_with_binmode_and_get[cs],read_write_with_binmode}): tests for above changes. all patches are written by Hiroshi Shirosaki. [ruby-core:41496] [Feature #5714] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34043 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4474c83a9d
commit
0c6103cf50
5 changed files with 194 additions and 17 deletions
24
ChangeLog
24
ChangeLog
|
@ -1,3 +1,27 @@
|
|||
Wed Dec 14 19:22:33 2011 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* win32/win32.c, include/ruby/win32.h (rb_w32_fd_is_text): new function.
|
||||
|
||||
* win32/win32.c (init_stdhandle): set default mode of stdin as binmode.
|
||||
|
||||
* io.c (set_binary_mode_with_seek_cur): new function to replace
|
||||
SET_BINARY_MODE_WITH_SEEK_CUR macro. now returns previous mode of the
|
||||
fd and take care of LF in rbuf.
|
||||
|
||||
* io.c (do_writeconv): set text mode when needed.
|
||||
|
||||
* io.c (io_read): need to change the mode of the IO to binmode
|
||||
temporally when the length for IO#read, because IO#read with length
|
||||
must behave so.
|
||||
|
||||
* test/ruby/test_io_m17n.rb (TestIO_M17N#est_{read_with_length,
|
||||
read_with_length_binmode,get[cs]_and_read_with_binmode,
|
||||
read_with_binmode_and_get[cs],read_write_with_binmode}): tests for
|
||||
above changes.
|
||||
|
||||
all patches are written by Hiroshi Shirosaki. [ruby-core:41496]
|
||||
[Feature #5714]
|
||||
|
||||
Wed Dec 14 15:28:31 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* transcode.c (str_encode): about the extension of :fallback
|
||||
|
|
|
@ -304,6 +304,7 @@ extern int rb_w32_stati64(const char *, struct stati64 *);
|
|||
extern int rb_w32_ustati64(const char *, struct stati64 *);
|
||||
extern int rb_w32_access(const char *, int);
|
||||
extern int rb_w32_uaccess(const char *, int);
|
||||
extern char rb_w32_fd_is_text(int);
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
extern int rb_w32_fstati64(int, struct stati64 *);
|
||||
|
|
86
io.c
86
io.c
|
@ -374,6 +374,8 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd)
|
|||
# endif
|
||||
#endif
|
||||
|
||||
static int io_fflush(rb_io_t *);
|
||||
|
||||
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
|
||||
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
|
||||
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
|
||||
|
@ -413,22 +415,59 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd)
|
|||
* but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
|
||||
* conversion for working properly with mode change.
|
||||
*/
|
||||
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) do {\
|
||||
if ((fptr)->rbuf.len > 0 && !((fptr)->mode & FMODE_DUPLEX)) {\
|
||||
off_t r;\
|
||||
errno = 0;\
|
||||
r = io_seek((fptr), -(fptr)->rbuf.len, SEEK_CUR);\
|
||||
if (r < 0 && errno) {\
|
||||
if (errno == ESPIPE)\
|
||||
(fptr)->mode |= FMODE_DUPLEX;\
|
||||
}\
|
||||
else {\
|
||||
(fptr)->rbuf.off = 0;\
|
||||
(fptr)->rbuf.len = 0;\
|
||||
}\
|
||||
}\
|
||||
setmode((fptr)->fd, O_BINARY);\
|
||||
} while(0)
|
||||
/*
|
||||
* Return previous translation mode.
|
||||
*/
|
||||
inline static int set_binary_mode_with_seek_cur(rb_io_t *fptr) {
|
||||
off_t r, pos;
|
||||
ssize_t read_size;
|
||||
long i;
|
||||
long newlines = 0;
|
||||
char *p;
|
||||
|
||||
if (!rb_w32_fd_is_text((fptr)->fd)) return O_BINARY;
|
||||
|
||||
if ((fptr)->rbuf.len == 0 || (fptr)->mode & FMODE_DUPLEX) {
|
||||
setmode((fptr)->fd, O_BINARY);
|
||||
return O_TEXT;
|
||||
}
|
||||
|
||||
if (io_fflush(fptr) < 0) {
|
||||
rb_sys_fail(0);
|
||||
}
|
||||
errno = 0;
|
||||
pos = lseek((fptr)->fd, 0, SEEK_CUR);
|
||||
if (pos < 0 && errno) {
|
||||
if (errno == ESPIPE)
|
||||
(fptr)->mode |= FMODE_DUPLEX;
|
||||
setmode((fptr)->fd, O_BINARY);
|
||||
return O_TEXT;
|
||||
}
|
||||
/* add extra offset for '\r' */
|
||||
p = (fptr)->rbuf.ptr+(fptr)->rbuf.off;
|
||||
for (i = 0; i < (fptr)->rbuf.len; i++) {
|
||||
if (*p == '\n') newlines++;
|
||||
p++;
|
||||
}
|
||||
while (newlines >= 0) {
|
||||
r = lseek((fptr)->fd, pos - (fptr)->rbuf.len - newlines, SEEK_SET);
|
||||
if (newlines == 0) break;
|
||||
if (read_size = _read((fptr)->fd, (fptr)->rbuf.ptr, (fptr)->rbuf.len + newlines)) {
|
||||
if (read_size == (fptr)->rbuf.len) {
|
||||
lseek((fptr)->fd, r, SEEK_SET);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
newlines--;
|
||||
}
|
||||
}
|
||||
}
|
||||
(fptr)->rbuf.off = 0;
|
||||
(fptr)->rbuf.len = 0;
|
||||
setmode((fptr)->fd, O_BINARY);
|
||||
return O_TEXT;
|
||||
}
|
||||
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
|
||||
|
||||
#else
|
||||
/* Unix */
|
||||
|
@ -494,7 +533,6 @@ rb_io_check_closed(rb_io_t *fptr)
|
|||
}
|
||||
}
|
||||
|
||||
static int io_fflush(rb_io_t *);
|
||||
|
||||
VALUE
|
||||
rb_io_get_io(VALUE io)
|
||||
|
@ -1142,6 +1180,9 @@ do_writeconv(VALUE str, rb_io_t *fptr)
|
|||
!(fptr->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
|
||||
setmode(fptr->fd, O_BINARY);
|
||||
}
|
||||
else {
|
||||
setmode(fptr->fd, O_TEXT);
|
||||
}
|
||||
if (!rb_enc_asciicompat(rb_enc_get(str))) {
|
||||
rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
|
||||
rb_enc_name(rb_enc_get(str)));
|
||||
|
@ -2462,6 +2503,9 @@ io_read(int argc, VALUE *argv, VALUE io)
|
|||
rb_io_t *fptr;
|
||||
long n, len;
|
||||
VALUE length, str;
|
||||
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
|
||||
int previous_mode;
|
||||
#endif
|
||||
|
||||
rb_scan_args(argc, argv, "02", &length, &str);
|
||||
|
||||
|
@ -2482,7 +2526,15 @@ io_read(int argc, VALUE *argv, VALUE io)
|
|||
if (len == 0) return str;
|
||||
|
||||
READ_CHECK(fptr);
|
||||
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
|
||||
previous_mode = set_binary_mode_with_seek_cur(fptr);
|
||||
#endif
|
||||
n = io_fread(str, 0, fptr);
|
||||
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
|
||||
if (previous_mode == O_TEXT) {
|
||||
setmode(fptr->fd, O_TEXT);
|
||||
}
|
||||
#endif
|
||||
if (n == 0) {
|
||||
if (fptr->fd < 0) return Qnil;
|
||||
rb_str_resize(str, 0);
|
||||
|
|
|
@ -2222,4 +2222,96 @@ EOT
|
|||
end
|
||||
end
|
||||
end if /mswin|mingw/ =~ RUBY_PLATFORM
|
||||
|
||||
def test_read_with_length
|
||||
with_tmpdir {
|
||||
str = "a\nb"
|
||||
generate_file("tmp", str)
|
||||
open("tmp", "r") do |f|
|
||||
assert_equal(str, f.read(3))
|
||||
end
|
||||
}
|
||||
end if /mswin|mingw/ =~ RUBY_PLATFORM
|
||||
|
||||
def test_read_with_length_binmode
|
||||
with_tmpdir {
|
||||
str = "a\r\nb\r\nc\r\n\r\n"
|
||||
generate_file("tmp", str)
|
||||
open("tmp", "r") do |f|
|
||||
# read with length should be binary mode
|
||||
assert_equal("a\r\n", f.read(3)) # binary
|
||||
assert_equal("b\nc\n\n", f.read) # text
|
||||
end
|
||||
}
|
||||
end if /mswin|mingw/ =~ RUBY_PLATFORM
|
||||
|
||||
def test_gets_and_read_with_binmode
|
||||
with_tmpdir {
|
||||
str = "a\r\nb\r\nc\r\n\n\r\n"
|
||||
generate_file("tmp", str)
|
||||
open("tmp", "r") do |f|
|
||||
assert_equal("a\n", f.gets) # text
|
||||
assert_equal("b\r\n", f.read(3)) # binary
|
||||
assert_equal("c\r\n", f.read(3)) # binary
|
||||
assert_equal("\n\n", f.read) # text
|
||||
end
|
||||
}
|
||||
end if /mswin|mingw/ =~ RUBY_PLATFORM
|
||||
|
||||
def test_getc_and_read_with_binmode
|
||||
with_tmpdir {
|
||||
str = "a\r\nb\r\nc\n\n\r\n\r\n"
|
||||
generate_file("tmp", str)
|
||||
open("tmp", "r") do |f|
|
||||
assert_equal("a", f.getc) # text
|
||||
assert_equal("\n", f.getc) # text
|
||||
assert_equal("b\r\n", f.read(3)) # binary
|
||||
assert_equal("c\n\n\n\n", f.read) # text
|
||||
end
|
||||
}
|
||||
end if /mswin|mingw/ =~ RUBY_PLATFORM
|
||||
|
||||
def test_read_with_binmode_and_gets
|
||||
with_tmpdir {
|
||||
str = "a\r\nb\r\nc\r\n\r\n"
|
||||
open("tmp", "wb") { |f| f.write str }
|
||||
open("tmp", "r") do |f|
|
||||
assert_equal("a", f.getc) # text
|
||||
assert_equal("\n", f.getc) # text
|
||||
assert_equal("b\r\n", f.read(3)) # binary
|
||||
assert_equal("c\n", f.gets) # text
|
||||
assert_equal("\n", f.gets) # text
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_read_with_binmode_and_getc
|
||||
with_tmpdir {
|
||||
str = "a\r\nb\r\nc\r\n\r\n"
|
||||
open("tmp", "wb") { |f| f.write str }
|
||||
open("tmp", "r") do |f|
|
||||
assert_equal("a", f.getc) # text
|
||||
assert_equal("\n", f.getc) # text
|
||||
assert_equal("b\r\n", f.read(3)) # binary
|
||||
assert_equal("c", f.getc) # text
|
||||
assert_equal("\n", f.getc) # text
|
||||
assert_equal("\n", f.getc) # text
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_read_write_with_binmode
|
||||
with_tmpdir {
|
||||
str = "a\r\n"
|
||||
generate_file("tmp", str)
|
||||
open("tmp", "r+") do |f|
|
||||
assert_equal("a\r\n", f.read(3)) # binary
|
||||
f.write("b\n\n"); # text
|
||||
f.rewind
|
||||
assert_equal("a\nb\n\n", f.read) # text
|
||||
f.rewind
|
||||
assert_equal("a\r\nb\r\n\r\n", f.binmode.read) # binary
|
||||
end
|
||||
}
|
||||
end if /mswin|mingw/ =~ RUBY_PLATFORM
|
||||
end
|
||||
|
|
|
@ -2259,6 +2259,9 @@ init_stdhandle(void)
|
|||
if (fileno(stdin) < 0) {
|
||||
stdin->_file = open_null(0);
|
||||
}
|
||||
else {
|
||||
setmode(fileno(stdin), O_BINARY);
|
||||
}
|
||||
if (fileno(stdout) < 0) {
|
||||
stdout->_file = open_null(1);
|
||||
}
|
||||
|
@ -6137,3 +6140,8 @@ rb_w32_inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
|
|||
}
|
||||
return numaddr;
|
||||
}
|
||||
|
||||
char
|
||||
rb_w32_fd_is_text(int fd) {
|
||||
return _osfile(fd) & FTEXT;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue