mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* include/ruby/encoding.h (ECONV_NEWLINE_DECORATOR_READ_MASK,
ECONV_NEWLINE_DECORATOR_WRITE_MASK): new macro. * io.c (rb_io_extract_modeenc, pipe_open, prep_stdio, argf_next_argv): set TEXTMODE_NEWLINE_DECORATOR_ON_WRITE for textmode on creating IO if the flag is available. * io.c (make_writeconv): drop decorators for reading. * io.c (make_readconv): drop decorators for writing. * io.c (do_writeconv): existing writeconv is not the condition to raise ArgumentError. should check textmode or not. * test/ruby/test_io_m17n.rb (TestIO_M17N#test_{cr,lf,crlf}_decorator_on_stdout): test above changes. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33662 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4764756497
commit
add77a592b
3 changed files with 94 additions and 16 deletions
|
@ -305,6 +305,8 @@ void rb_econv_binmode(rb_econv_t *ec);
|
|||
|
||||
#define ECONV_DECORATOR_MASK 0x0000ff00
|
||||
#define ECONV_NEWLINE_DECORATOR_MASK 0x00003f00
|
||||
#define ECONV_NEWLINE_DECORATOR_READ_MASK 0x00000f00
|
||||
#define ECONV_NEWLINE_DECORATOR_WRITE_MASK 0x00003000
|
||||
|
||||
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR 0x00000100
|
||||
#define ECONV_CRLF_NEWLINE_DECORATOR 0x00001000
|
||||
|
|
51
io.c
51
io.c
|
@ -903,16 +903,8 @@ make_writeconv(rb_io_t *fptr)
|
|||
|
||||
fptr->writeconv_initialized = 1;
|
||||
|
||||
ecflags = fptr->encs.ecflags;
|
||||
ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
|
||||
ecopts = fptr->encs.ecopts;
|
||||
#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
|
||||
if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) &&
|
||||
(!(ecflags & ECONV_NEWLINE_DECORATOR_MASK) ||
|
||||
(ecflags & ECONV_UNIVERSAL_NEWLINE_DECORATOR))) {
|
||||
ecflags &= ~ECONV_UNIVERSAL_NEWLINE_DECORATOR;
|
||||
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
|
||||
/* no encoding conversion */
|
||||
|
@ -1050,6 +1042,8 @@ io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
|
|||
return len;
|
||||
}
|
||||
|
||||
# define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
|
||||
(fmode & FMODE_TEXTMODE) ? (c) : (a))
|
||||
static VALUE
|
||||
do_writeconv(VALUE str, rb_io_t *fptr)
|
||||
{
|
||||
|
@ -1059,12 +1053,14 @@ do_writeconv(VALUE str, rb_io_t *fptr)
|
|||
make_writeconv(fptr);
|
||||
|
||||
if (fptr->writeconv) {
|
||||
#define fmode (fptr->mode)
|
||||
if (!NIL_P(fptr->writeconv_asciicompat))
|
||||
common_encoding = fptr->writeconv_asciicompat;
|
||||
else if (!rb_enc_asciicompat(rb_enc_get(str))) {
|
||||
else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !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)));
|
||||
}
|
||||
#undef fmode
|
||||
}
|
||||
else {
|
||||
if (fptr->encs.enc2)
|
||||
|
@ -1806,7 +1802,7 @@ make_readconv(rb_io_t *fptr, int size)
|
|||
int ecflags;
|
||||
VALUE ecopts;
|
||||
const char *sname, *dname;
|
||||
ecflags = fptr->encs.ecflags;
|
||||
ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
|
||||
ecopts = fptr->encs.ecopts;
|
||||
if (fptr->encs.enc2) {
|
||||
sname = rb_enc_name(fptr->encs.enc2);
|
||||
|
@ -4214,8 +4210,6 @@ rb_io_binmode_p(VALUE io)
|
|||
static const char*
|
||||
rb_io_fmode_modestr(int fmode)
|
||||
{
|
||||
# define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
|
||||
(fmode & FMODE_TEXTMODE) ? (c) : (a))
|
||||
if (fmode & FMODE_APPEND) {
|
||||
if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
|
||||
return MODE_BTMODE("a+", "ab+", "at+");
|
||||
|
@ -4680,6 +4674,11 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
|
|||
ecflags = (fmode & FMODE_READABLE) ?
|
||||
MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
|
||||
0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
|
||||
#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
|
||||
ecflags |= (fmode & FMODE_WRITABLE) ?
|
||||
MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
|
||||
0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
|
||||
#endif
|
||||
ecopts = Qnil;
|
||||
}
|
||||
else {
|
||||
|
@ -4715,6 +4714,11 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
|
|||
ecflags = (fmode & FMODE_READABLE) ?
|
||||
MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
|
||||
0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
|
||||
#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
|
||||
ecflags |= (fmode & FMODE_WRITABLE) ?
|
||||
MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
|
||||
0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
|
||||
#endif
|
||||
ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
|
||||
|
||||
if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
|
||||
|
@ -5411,8 +5415,15 @@ pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode,
|
|||
if (convconfig) {
|
||||
fptr->encs = *convconfig;
|
||||
}
|
||||
else if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
|
||||
fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
|
||||
else {
|
||||
if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
|
||||
fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
|
||||
}
|
||||
#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
|
||||
if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
|
||||
fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
fptr->pid = pid;
|
||||
|
||||
|
@ -6581,6 +6592,9 @@ prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
|
|||
|
||||
GetOpenFile(io, fptr);
|
||||
fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
|
||||
#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
|
||||
fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
|
||||
#endif
|
||||
fptr->stdio_file = f;
|
||||
|
||||
return io;
|
||||
|
@ -7118,7 +7132,12 @@ argf_next_argv(VALUE argf)
|
|||
if (stdout_binmode) rb_io_binmode(rb_stdout);
|
||||
}
|
||||
fmode = FMODE_READABLE;
|
||||
if (!ARGF.binmode) fmode |= DEFAULT_TEXTMODE;
|
||||
if (!ARGF.binmode) {
|
||||
fmode |= DEFAULT_TEXTMODE;
|
||||
#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
|
||||
fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
|
||||
#endif
|
||||
}
|
||||
ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
|
||||
if (!NIL_P(write_io)) {
|
||||
rb_io_set_write_io(ARGF.current_file, write_io);
|
||||
|
|
|
@ -2117,4 +2117,61 @@ EOT
|
|||
end
|
||||
end
|
||||
end if /mswin|mingw/ =~ RUBY_PLATFORM
|
||||
|
||||
def test_cr_decorator_on_stdout
|
||||
with_pipe do |in_r, in_w|
|
||||
with_pipe do |out_r, out_w|
|
||||
pid = Process.spawn({}, EnvUtil.rubybin, in: in_r, out: out_w)
|
||||
in_r.close
|
||||
out_w.close
|
||||
in_w.write <<-EOS
|
||||
STDOUT.set_encoding('locale', nil, newline: :cr)
|
||||
STDOUT.puts "abc"
|
||||
STDOUT.flush
|
||||
EOS
|
||||
in_w.close
|
||||
Process.wait pid
|
||||
assert_equal "abc\r", out_r.binmode.read
|
||||
out_r.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_lf_decorator_on_stdout
|
||||
with_pipe do |in_r, in_w|
|
||||
with_pipe do |out_r, out_w|
|
||||
pid = Process.spawn({}, EnvUtil.rubybin, in: in_r, out: out_w)
|
||||
in_r.close
|
||||
out_w.close
|
||||
in_w.write <<-EOS
|
||||
STDOUT.set_encoding('locale', nil, newline: :lf)
|
||||
STDOUT.puts "abc"
|
||||
STDOUT.flush
|
||||
EOS
|
||||
in_w.close
|
||||
Process.wait pid
|
||||
assert_equal "abc\n", out_r.binmode.read
|
||||
out_r.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_crlf_decorator_on_stdout
|
||||
with_pipe do |in_r, in_w|
|
||||
with_pipe do |out_r, out_w|
|
||||
pid = Process.spawn({}, EnvUtil.rubybin, in: in_r, out: out_w)
|
||||
in_r.close
|
||||
out_w.close
|
||||
in_w.write <<-EOS
|
||||
STDOUT.set_encoding('locale', nil, newline: :crlf)
|
||||
STDOUT.puts "abc"
|
||||
STDOUT.flush
|
||||
EOS
|
||||
in_w.close
|
||||
Process.wait pid
|
||||
assert_equal "abc\r\n", out_r.binmode.read
|
||||
out_r.close
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue