diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | include/ruby/io.h | 2 | ||||
-rw-r--r-- | io.c | 73 |
3 files changed, 72 insertions, 8 deletions
@@ -1,3 +1,8 @@ +Sun Dec 23 01:18:06 2007 David Flanagan <david@davidflanagan.com> + + * io.c, io.h: temporary patch to partially implement + transcode-on-read and transcode-on-write + Sun Dec 23 00:48:05 2007 Shugo Maeda <shugo@ruby-lang.org> * test/net/imap/test_imap.rb: added tests for SSL. diff --git a/include/ruby/io.h b/include/ruby/io.h index 5111592935..1e605ea8ca 100644 --- a/include/ruby/io.h +++ b/include/ruby/io.h @@ -47,6 +47,7 @@ typedef struct rb_io_t { int rbuf_capa; VALUE tied_io_for_writing; rb_encoding *enc; + rb_encoding *enc2; } rb_io_t; #define HAVE_RB_IO_T 1 @@ -91,6 +92,7 @@ typedef struct rb_io_t { fp->rbuf_capa = 0;\ fp->tied_io_for_writing = 0;\ fp->enc = 0;\ + fp->enc2 = 0;\ } while (0) FILE *rb_io_stdio_file(rb_io_t *fptr); @@ -124,7 +124,7 @@ VALUE rb_default_rs; static VALUE argf; -static ID id_write, id_read, id_getc, id_flush; +static ID id_write, id_read, id_getc, id_flush, id_encode; extern char *ruby_inplace_mode; @@ -622,6 +622,26 @@ io_fwrite(VALUE str, rb_io_t *fptr) { long len, n, r, l, offset = 0; + /* + * If an external encoding was specified and it differs from + * the strings encoding then we must transcode before writing. + * We must also transcode if two encodings were specified + */ + if (fptr->enc && (fptr->enc2 || fptr->enc != rb_enc_get(str))) { + /* transcode str before output */ + /* the methods in transcode.c are static, so call indirectly */ + /* Can't use encode! because puts writes a frozen newline */ + if (fptr->enc2) { + str = rb_funcall(str, id_encode, 2, + rb_enc_from_encoding(fptr->enc), + rb_enc_from_encoding(fptr->enc2)); + } + else { + str = rb_funcall(str, id_encode, 1, + rb_enc_from_encoding(fptr->enc)); + } + } + len = RSTRING_LEN(str); if ((n = len) <= 0) return n; if (fptr->wbuf == NULL && !(fptr->mode & FMODE_SYNC)) { @@ -1279,7 +1299,17 @@ io_enc_str(VALUE str, rb_io_t *fptr) { OBJ_TAINT(str); if (fptr->enc) { - rb_enc_associate(str, fptr->enc); + if (fptr->enc2) { + /* two encodings, so transcode from enc2 to enc */ + /* the methods in transcode.c are static, so call indirectly */ + str = rb_funcall(str, id_encode, 2, + rb_enc_from_encoding(fptr->enc2), + rb_enc_from_encoding(fptr->enc)); + } + else { + /* just one encoding, so associate it with the string */ + rb_enc_associate(str, fptr->enc); + } } return str; } @@ -2878,11 +2908,11 @@ rb_io_binmode(VALUE io) static VALUE rb_io_binmode_m(VALUE io) { + rb_io_binmode(io); + #if defined(_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) || defined(__EMX__) VALUE write_io; - rb_io_binmode(io); - write_io = GetWriteIO(io); if (write_io != io) rb_io_binmode(write_io); @@ -3063,7 +3093,8 @@ void rb_io_mode_enc(rb_io_t *fptr, const char *mode) { const char *p0, *p1; - int idx; + char *enc2name; + int idx, idx2; p0 = strrchr(mode, ':'); if (p0) { @@ -3071,13 +3102,31 @@ rb_io_mode_enc(rb_io_t *fptr, const char *mode) if (idx >= 0) { fptr->enc = rb_enc_from_index(idx); } -#if 0 + else { + rb_warn("Unsupported encoding %s ignored", p0+1); + } p1 = strchr(mode, ':'); if (p1 < p0) { + enc2name = ALLOCA_N(char, p0-p1); + strncpy(enc2name, p1+1, p0-p1-1); + enc2name[p0-p1-1] = '\0'; + idx2=rb_enc_find_index(enc2name); + if (idx2 == idx) { + rb_warn("Ignoring internal encoding %s: it is identical to external encoding %s", + enc2name, p0+1); + } + else if (idx2 >= 0) { + fptr->enc2 = rb_enc_from_index(idx2); + } + else { + rb_warn("Unsupported encoding %s ignored", enc2name); + } } -#endif } - else if (!(fptr->mode & FMODE_BINMODE)) { + else if (fptr->mode & FMODE_BINMODE) { + fptr->enc = rb_ascii_encoding(); + } + else { fptr->enc = rb_default_external_encoding(); } } @@ -5703,6 +5752,11 @@ rb_io_external_encoding(VALUE io) return rb_enc_from_encoding(fptr->enc); } +static VALUE +argf_external_encoding(void) +{ + return rb_enc_default_external(); +} static VALUE argf_tell(void) @@ -6155,6 +6209,7 @@ Init_IO(void) id_read = rb_intern("read"); id_getc = rb_intern("getc"); id_flush = rb_intern("flush"); + id_encode = rb_intern("encode"); rb_define_global_function("syscall", rb_f_syscall, -1); @@ -6339,6 +6394,8 @@ Init_IO(void) rb_define_singleton_method(argf, "lineno", argf_lineno, 0); rb_define_singleton_method(argf, "lineno=", argf_set_lineno, 1); + rb_define_singleton_method(argf, "external_encoding", argf_external_encoding, 0); + rb_global_variable(¤t_file); rb_define_readonly_variable("$FILENAME", &filename); filename = rb_str_new2("-"); |