This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: FYI: fix OutputStreamWriter bug


I'm checking this in on the trunk.

This fixes a PR from the Red Hat bugzilla involving
OutputStreamWriter and java.nio charsets.  A test case is included.

Tom

2006-06-27  Tom Tromey  <tromey@redhat.com>

	* java/io/OutputStreamWriter.java (writeChars): Use a 'do' loop.
	Set 'out.count' earlier.
	(close): Call setFinished on converter.
	(flush): Always write work buffer.
	* java/io/PrintStream.java (writeChars): Do 'do' loop.
	(close): Call setFinished on converter.  Write a 'flush' array.
	* java/lang/natString.cc (getBytes): Call setFinished on
	converter.
	* gnu/gcj/convert/CharsetToBytesAdaptor.java (hasBytes): New
	field.
	(write): Set hasBytes.  Changed 'finished' logic.
	(havePendingBytes): Rewrote.
	(setFinished): New method.
	* gnu/gcj/convert/UnicodeToBytes.java (setFinished): New method.
	* testsuite/libjava.lang/RH194522.java: New file.
	* testsuite/libjava.lang/RH194522.out: New file.

Index: gnu/gcj/convert/UnicodeToBytes.java
===================================================================
--- gnu/gcj/convert/UnicodeToBytes.java	(revision 115024)
+++ gnu/gcj/convert/UnicodeToBytes.java	(working copy)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000, 2001, 2003, 2005  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2003, 2005, 2006  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -172,6 +172,15 @@
     return false;
   }
 
+  /**
+   * Users should call this method when the input is coming to an
+   * end.  This signals that the next write (which might be
+   * zero-length) ought to flush any internal state.
+   */
+  public void setFinished()
+  {
+  }
+
   /** Indicate that the converter is resuable.
    * This class keeps track of converters on a per-encoding basis.
    * When done with an encoder you may call this method to indicate
Index: gnu/gcj/convert/CharsetToBytesAdaptor.java
===================================================================
--- gnu/gcj/convert/CharsetToBytesAdaptor.java	(revision 115024)
+++ gnu/gcj/convert/CharsetToBytesAdaptor.java	(working copy)
@@ -39,6 +39,11 @@
   private boolean closedEncoder;
 
   /**
+   * True if there are bytes pending in the encoder.
+   */
+  private boolean hasBytes;
+
+  /**
    * True if we're finished.
    */
   private boolean finished;
@@ -112,20 +117,16 @@
     // Set the current position.
     outBuf.position(count);
 
-    // If we've already said that there is no more input available,
-    // then we simply try to flush again.
+    // Do the conversion.
+    CoderResult result = encoder.encode(inBuf, outBuf, closedEncoder);
+    hasBytes = result == CoderResult.OVERFLOW;
     if (closedEncoder)
       {
-	CoderResult result = encoder.flush(outBuf);
+	result = encoder.flush(outBuf);
 	if (result == CoderResult.UNDERFLOW)
 	  finished = true;
-       }
-    else
-      {
-	// Do the conversion.  If there are no characters to write,
-	// then we are finished.
-	closedEncoder = ! inBuf.hasRemaining();
-	encoder.encode(inBuf, outBuf, closedEncoder);
+	else
+	  hasBytes = true;
       }
 
     // Mark the new end of buf.
@@ -140,9 +141,14 @@
    */
   public boolean havePendingBytes()
   {
-    return ! finished;
+    return hasBytes;
   }
 
+  public void setFinished()
+  {
+    closedEncoder = true;
+  }
+
   // These aren't cached.
   public void done()
   {
Index: java/lang/natString.cc
===================================================================
--- java/lang/natString.cc	(revision 115024)
+++ java/lang/natString.cc	(working copy)
@@ -615,6 +615,8 @@
   while (todo > 0 || converter->havePendingBytes())
     {
       converter->setOutput(buffer, bufpos);
+      // We only really need to do a single write.
+      converter->setFinished();
       int converted = converter->write(this, offset, todo, NULL);
       bufpos = converter->count;
       if (converted == 0 && bufpos == converter->count)
Index: java/io/PrintStream.java
===================================================================
--- java/io/PrintStream.java	(revision 115024)
+++ java/io/PrintStream.java	(working copy)
@@ -1,5 +1,5 @@
 /* PrintStream.java -- OutputStream for printing output
-   Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005  Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -174,6 +174,8 @@
   {
     try
       {
+	converter.setFinished();
+	writeChars(new char[0], 0, 0);
 	flush();
 	out.close();
       }
@@ -251,7 +253,7 @@
   private void writeChars(char[] buf, int offset, int count)
     throws IOException
   {
-    while (count > 0 || converter.havePendingBytes())
+    do
       {
 	converter.setOutput(work_bytes, 0);
 	int converted = converter.write(buf, offset, count);
@@ -259,12 +261,13 @@
 	count -= converted;
 	out.write(work_bytes, 0, converter.count);
       }
+    while (count > 0 || converter.havePendingBytes());
   }
 
   private void writeChars(String str, int offset, int count)
     throws IOException
   {
-    while (count > 0 || converter.havePendingBytes())
+    do
       {
 	converter.setOutput(work_bytes, 0);
 	int converted = converter.write(str, offset, count, work);
@@ -272,6 +275,7 @@
 	count -= converted;
 	out.write(work_bytes, 0, converter.count);
       }
+    while (count > 0 || converter.havePendingBytes());
   }
 
   /**
Index: java/io/OutputStreamWriter.java
===================================================================
--- java/io/OutputStreamWriter.java	(revision 115024)
+++ java/io/OutputStreamWriter.java	(working copy)
@@ -1,5 +1,5 @@
 /* OutputStreamWriter.java -- Writer that converts chars to bytes
-   Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005  Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005, 2006  Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -168,6 +168,7 @@
       {
 	if (out != null)
 	  {
+	    converter.setFinished();
 	    flush();
 	    out.close();
 	    out = null;
@@ -200,11 +201,11 @@
 	if (out == null)
 	  throw new IOException("Stream closed");
 
-	if (wcount > 0)
-	  {
-	    writeChars(work, 0, wcount);
-	    wcount = 0;
-	  }
+	// Always write -- if we are close()ing then we want to make
+	// sure the converter is flushed.
+	writeChars(work, 0, wcount);
+	wcount = 0;
+
 	out.flush();
       }
   }
@@ -243,7 +244,7 @@
   private void writeChars(char[] buf, int offset, int count)
     throws IOException
   {
-    while (count > 0 || converter.havePendingBytes())
+    do
       {
 	// We must flush if out.count == out.buf.length.
 	// It is probably a good idea to flush if out.buf is almost full.
@@ -256,6 +257,9 @@
 	  }
 	converter.setOutput(out.buf, out.count);
 	int converted = converter.write(buf, offset, count);
+	// Must set this before we flush the output stream, because
+	// flushing will reset 'out.count'.
+	out.count = converter.count;
 	// Flush if we cannot make progress.
 	if (converted == 0 && out.count == converter.count)
 	  {
@@ -265,8 +269,8 @@
 	  }
 	offset += converted;
 	count -= converted;
-	out.count = converter.count;
       }
+    while (count > 0 || converter.havePendingBytes());
   }
 
   /**
Index: testsuite/libjava.lang/RH194522.out
===================================================================
Index: testsuite/libjava.lang/RH194522.java
===================================================================
--- testsuite/libjava.lang/RH194522.java	(revision 0)
+++ testsuite/libjava.lang/RH194522.java	(revision 0)
@@ -0,0 +1,18 @@
+// Test case for http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=194522
+
+import java.io.*;
+import java.nio.charset.Charset;
+
+public class RH194522
+{
+  public static void main(String[] args) throws Exception
+  {
+    Charset c = Charset.forName("UTF-8");
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    PrintWriter pw = new PrintWriter(new OutputStreamWriter(baos, c));
+    pw.println("hi");
+    pw.println("bob");
+    pw.flush();
+    pw.close();
+  }
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]