From: <cr...@us...> - 2008-11-05 13:26:07
|
Revision: 4670 http://jnode.svn.sourceforge.net/jnode/?rev=4670&view=rev Author: crawley Date: 2008-11-05 13:26:05 +0000 (Wed, 05 Nov 2008) Log Message: ----------- Fixes to allow ReaderInputStream to recover from encoder errors. Modified Paths: -------------- trunk/core/src/core/org/jnode/util/ReaderInputStream.java trunk/shell/src/test/org/jnode/test/shell/io/ReaderInputStreamTest.java Modified: trunk/core/src/core/org/jnode/util/ReaderInputStream.java =================================================================== --- trunk/core/src/core/org/jnode/util/ReaderInputStream.java 2008-11-04 21:26:57 UTC (rev 4669) +++ trunk/core/src/core/org/jnode/util/ReaderInputStream.java 2008-11-05 13:26:05 UTC (rev 4670) @@ -25,6 +25,7 @@ import java.io.Reader; import java.nio.ByteBuffer; import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; @@ -42,6 +43,7 @@ private ByteBuffer bytes = ByteBuffer.allocate(2048); private CharsetEncoder encoder; + private CoderResult cr; public ReaderInputStream(Reader reader) { this(reader, Charset.defaultCharset().name()); @@ -104,10 +106,12 @@ * @throws IOException */ private int fillBuffer(boolean wait) throws IOException { + // If there was a coder error left over from the last call, process + // it now. + resetAndThrowOnError(); bytes.clear(); // The loop is necessary because of the way that an encoder has to deal // with UTF-16 surrogate pairs. - CoderResult cr = null; int count; do { if (chars.remaining() == 0 || cr == CoderResult.UNDERFLOW) { @@ -126,25 +130,43 @@ if (reader.read(chars) == -1) { chars.flip(); cr = encoder.encode(chars, bytes, true); - if (cr.isError()) { - cr.throwException(); + count = bytes.position(); + if (count == 0) { + // Only report errors now if we didn't manage to encode anything + resetAndThrowOnError(); } - count = bytes.position(); bytes.flip(); return count > 0 ? count : -1; } chars.flip(); } cr = encoder.encode(chars, bytes, false); - if (cr.isError()) { - cr.throwException(); + count = bytes.position(); + if (count == 0) { + // Only report errors now if we didn't manage to encode anything + resetAndThrowOnError(); } - count = bytes.position(); } while (wait && count == 0); bytes.flip(); return count; } + private void resetAndThrowOnError() throws CharacterCodingException { + if (cr != null && cr.isError()) { + // Reset the encoder so that it will work next time we try to use it. + encoder.reset(); + // Skip over the problem characters + for (int i = 0; i < cr.length(); i++) { + chars.get(); + } + // Clear the coder result + CoderResult tmp = cr; + cr = null; + // ... and report the error using the appropriate exception. + tmp.throwException(); + } + } + public Reader getReader() { return reader; } Modified: trunk/shell/src/test/org/jnode/test/shell/io/ReaderInputStreamTest.java =================================================================== --- trunk/shell/src/test/org/jnode/test/shell/io/ReaderInputStreamTest.java 2008-11-04 21:26:57 UTC (rev 4669) +++ trunk/shell/src/test/org/jnode/test/shell/io/ReaderInputStreamTest.java 2008-11-05 13:26:05 UTC (rev 4670) @@ -125,6 +125,7 @@ Reader r = new StringReader(LINE); ReaderInputStream ris = new ReaderInputStream(r, "latin1"); byte[] buffer = new byte[257]; + assertEquals(256, ris.read(buffer)); try { ris.read(buffer); fail("No exception raised"); @@ -133,6 +134,25 @@ } } + public void testBadLatin1Recovery() throws Exception { + char[] chars = new char[11]; + for (int i = 0; i < 11; i++) { + chars[i] = i == 5 ? '\u0101' : (char) ('A' + i); + } + final String LINE = new String(chars); + Reader r = new StringReader(LINE); + ReaderInputStream ris = new ReaderInputStream(r, "latin1"); + byte[] buffer = new byte[5]; + assertEquals(5, ris.read(buffer)); + try { + ris.read(); + fail("No exception raised"); + } catch (UnmappableCharacterException ex) { + // expected + } + assertEquals(5, ris.read(buffer)); + } + public void testUnicode() throws Exception { char[] chars = new char[1024]; for (int i = 0; i < 1024; i++) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |