[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]