ruby-changes:7175
From: akr <ko1@a...>
Date: Mon, 18 Aug 2008 23:29:03 +0900 (JST)
Subject: [ruby-changes:7175] Ruby:r18694 (trunk): * io.c (io_ungetbyte): renamed from io_ungetc.
akr 2008-08-18 23:28:45 +0900 (Mon, 18 Aug 2008) New Revision: 18694 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=18694 Log: * io.c (io_ungetbyte): renamed from io_ungetc. (rb_io_ungetbyte): new method. (rb_io_ungetc): push back into character buffer if enc2 is set. Modified files: trunk/ChangeLog trunk/io.c trunk/test/ruby/test_io_m17n.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 18693) +++ ChangeLog (revision 18694) @@ -1,3 +1,9 @@ +Mon Aug 18 23:27:07 2008 Tanaka Akira <akr@f...> + + * io.c (io_ungetbyte): renamed from io_ungetc. + (rb_io_ungetbyte): new method. + (rb_io_ungetc): push back into character buffer if enc2 is set. + Mon Aug 18 22:41:46 2008 Tanaka Akira <akr@f...> * io.c (id_encode): removed. Index: io.c =================================================================== --- io.c (revision 18693) +++ io.c (revision 18694) @@ -326,14 +326,10 @@ static rb_encoding *io_input_encoding(rb_io_t *fptr); static void -io_ungetc(VALUE str, rb_io_t *fptr) +io_ungetbyte(VALUE str, rb_io_t *fptr) { int len = RSTRING_LEN(str); - if (rb_enc_dummy_p(io_input_encoding(fptr))) { - rb_raise(rb_eNotImpError, "ungetc against dummy encoding is not currently supported"); - } - if (fptr->rbuf == NULL) { fptr->rbuf_off = 0; fptr->rbuf_len = 0; @@ -344,7 +340,7 @@ fptr->rbuf = ALLOC_N(char, fptr->rbuf_capa); } if (fptr->rbuf_capa < len + fptr->rbuf_len) { - rb_raise(rb_eIOError, "ungetc failed"); + rb_raise(rb_eIOError, "ungetbyte failed"); } if (fptr->rbuf_off < len) { MEMMOVE(fptr->rbuf+fptr->rbuf_capa-fptr->rbuf_len, @@ -2715,6 +2711,42 @@ /* * call-seq: + * ios.ungetbyte(string) => nil + * ios.ungetbyte(integer) => nil + * + * Pushes back bytes (passed as a parameter) onto <em>ios</em>, + * such that a subsequent buffered read will return it. Only one byte + * may be pushed back before a subsequent read operation (that is, + * you will be able to read only the last of several bytes that have been pushed + * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>). + * + * f = File.new("testfile") #=> #<File:testfile> + * b = f.getbyte #=> 0x38 + * f.ungetbyte(b) #=> nil + * f.getbyte #=> 0x38 + */ + +VALUE +rb_io_ungetbyte(VALUE io, VALUE b) +{ + rb_io_t *fptr; + + GetOpenFile(io, fptr); + rb_io_check_readable(fptr); + if (NIL_P(b)) return Qnil; + if (FIXNUM_P(b)) { + char cc = FIX2INT(b); + b = rb_str_new(&cc, 1); + } + else { + SafeStringValue(b); + } + io_ungetbyte(b, fptr); + return Qnil; +} + +/* + * call-seq: * ios.ungetc(string) => nil * * Pushes back one character (passed as a parameter) onto <em>ios</em>, @@ -2733,6 +2765,7 @@ rb_io_ungetc(VALUE io, VALUE c) { rb_io_t *fptr; + long len; GetOpenFile(io, fptr); rb_io_check_readable(fptr); @@ -2747,7 +2780,24 @@ else { SafeStringValue(c); } - io_ungetc(c, fptr); + if (fptr->enc2) { + make_readconv(fptr); + len = RSTRING_LEN(c); + if (fptr->crbuf_capa - fptr->crbuf_len < len) + rb_raise(rb_eIOError, "ungetc failed"); + if (fptr->crbuf_off < len) { + MEMMOVE(fptr->crbuf+fptr->crbuf_capa-fptr->crbuf_len, + fptr->crbuf+fptr->crbuf_off, + char, fptr->crbuf_len); + fptr->crbuf_off = fptr->crbuf_capa-fptr->crbuf_len; + } + fptr->crbuf_off -= len; + fptr->crbuf_len += len; + MEMMOVE(fptr->crbuf+fptr->crbuf_off, RSTRING_PTR(c), char, len); + } + else { + io_ungetbyte(c, fptr); + } return Qnil; } @@ -8019,6 +8069,7 @@ rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0); rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0); rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0); + rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1); rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1); rb_define_method(rb_cIO, "<<", rb_io_addstr, 1); rb_define_method(rb_cIO, "flush", rb_io_flush, 0); Index: test/ruby/test_io_m17n.rb =================================================================== --- test/ruby/test_io_m17n.rb (revision 18693) +++ test/ruby/test_io_m17n.rb (revision 18694) @@ -239,17 +239,33 @@ with_tmpdir { src = "before \e$B\x23\x30\x23\x31\e(B after".force_encoding("iso-2022-jp") generate_file('tmp', src) - assert_raise(NotImplementedError) do - s = open("tmp", "r:iso-2022-jp:euc-jp") {|f| - f.ungetc("0".force_encoding("euc-jp")) - f.read - } - assert_equal(Encoding.find("euc-jp"), s.encoding) - assert_str_equal(("0" + src).encode("euc-jp"), s) - end + s = open("tmp", "r:iso-2022-jp:euc-jp") {|f| + f.ungetc("0".force_encoding("euc-jp")) + f.read + } + assert_equal(Encoding.find("euc-jp"), s.encoding) + assert_str_equal("0" + src.encode("euc-jp"), s) } end + def test_ungetc_stateful_conversion2 + with_tmpdir { + src = "before \e$B\x23\x30\x23\x31\e(B after".force_encoding("iso-2022-jp") + former = "before \e$B\x23\x30\e(B".force_encoding("iso-2022-jp") + rs = "\e$B\x23\x30\e(B".force_encoding("iso-2022-jp") + latter = "\e$B\x23\x31\e(B after".force_encoding("iso-2022-jp") + generate_file('tmp', src) + s = open("tmp", "r:iso-2022-jp:euc-jp") {|f| + assert_equal(former.encode("euc-jp", "iso-2022-jp"), + f.gets(rs.encode("euc-jp", "iso-2022-jp"))) + f.ungetc("0") + f.read + } + assert_equal(Encoding.find("euc-jp"), s.encoding) + assert_str_equal("0" + latter.encode("euc-jp"), s) + } + end + def test_open_ascii with_tmpdir { src = "abc\n" -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/