|
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.
|