From: <cr...@us...> - 2008-09-04 14:09:44
|
Revision: 4540 http://jnode.svn.sourceforge.net/jnode/?rev=4540&view=rev Author: crawley Date: 2008-09-04 14:09:40 +0000 (Thu, 04 Sep 2008) Log Message: ----------- Bug fixes for WriterOutputStream + unit tests Modified Paths: -------------- trunk/shell/src/shell/org/jnode/shell/io/WriterOutputStream.java Added Paths: ----------- trunk/shell/src/test/org/jnode/test/shell/io/WriterOutputStreamTest.java Modified: trunk/shell/src/shell/org/jnode/shell/io/WriterOutputStream.java =================================================================== --- trunk/shell/src/shell/org/jnode/shell/io/WriterOutputStream.java 2008-09-03 23:43:55 UTC (rev 4539) +++ trunk/shell/src/shell/org/jnode/shell/io/WriterOutputStream.java 2008-09-04 14:09:40 UTC (rev 4540) @@ -7,12 +7,13 @@ import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; +import java.nio.charset.CoderResult; public class WriterOutputStream extends OutputStream { // TODO deal with decoder errors. private ByteBuffer bytes = ByteBuffer.allocate(2048); - private CharBuffer chars = CharBuffer.allocate(1024); + private CharBuffer chars = CharBuffer.allocate(2048); private Writer writer; private CharsetDecoder decoder; @@ -20,24 +21,53 @@ public WriterOutputStream(Writer writer, String encoding) { this.writer = writer; this.decoder = Charset.forName(encoding).newDecoder(); + bytes.clear(); + chars.clear(); } @Override public void write(int b) throws IOException { bytes.put((byte) b); if (bytes.remaining() == 0) { - decoder.decode(bytes, chars, false); - flush(); + flush(false); } } @Override public void flush() throws IOException { - if (chars.position() > 0) { - int len = chars.position(); - int pos = chars.arrayOffset(); - writer.write(chars.array(), pos, len); + flush(false); + } + + @Override + public void close() throws IOException { + flush(true); + writer.close(); + } + + private int flush(boolean all) throws IOException { + if (bytes.position() > 0) { + bytes.flip(); chars.clear(); + CoderResult cr = decoder.decode(bytes, chars, all); + int count = chars.position(); + if (count > 0) { + int pos = chars.arrayOffset(); + writer.write(chars.array(), pos, count); + } + if (cr.isError() || (all && cr == CoderResult.UNDERFLOW)) { + cr.throwException(); + } + if (bytes.remaining() > 0) { + byte[] tmp = new byte[bytes.remaining()]; + bytes.get(tmp); + bytes.clear(); + bytes.put(tmp); + } else { + bytes.clear(); + } + return count; + } else { + return 0; } } @@ -47,13 +77,13 @@ throw new IndexOutOfBoundsException(); } while (len > 0) { - int pos = bytes.position(); - bytes.put(b, off, len); - int count = bytes.position() - pos; - off += count; - len -= count; - decoder.decode(bytes, chars, false); - flush(); + int toWrite = Math.min(len, bytes.remaining()); + bytes.put(b, off, toWrite); + off += toWrite; + len -= toWrite; + if (bytes.remaining() == 0) { + flush(false); + } } } Added: trunk/shell/src/test/org/jnode/test/shell/io/WriterOutputStreamTest.java =================================================================== --- trunk/shell/src/test/org/jnode/test/shell/io/WriterOutputStreamTest.java (rev 0) +++ trunk/shell/src/test/org/jnode/test/shell/io/WriterOutputStreamTest.java 2008-09-04 14:09:40 UTC (rev 4540) @@ -0,0 +1,153 @@ +/* + * $Id: ThreadCommandInvoker.java 3374 2007-08-02 18:15:27Z lsantha $ + * + * JNode.org + * Copyright (C) 2007 JNode.org + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package org.jnode.test.shell.io; + +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.nio.charset.MalformedInputException; +import java.nio.charset.UnmappableCharacterException; + +import junit.framework.TestCase; + +import org.jnode.shell.io.ReaderInputStream; +import org.jnode.shell.io.WriterOutputStream; + +public class WriterOutputStreamTest extends TestCase { + + public void testEmpty() throws Exception { + String LINE = ""; + StringWriter sw = new StringWriter(); + WriterOutputStream wos = new WriterOutputStream(sw, "UTF-8"); + byte[] buffer = LINE.getBytes(); + wos.write(buffer); + wos.flush(); + assertEquals(LINE, sw.getBuffer().toString()); + } + + public void testLine() throws Exception { + String LINE = "The quick brown fox jumped over the lazy doc"; + StringWriter sw = new StringWriter(); + WriterOutputStream wos = new WriterOutputStream(sw, "UTF-8"); + byte[] buffer = LINE.getBytes(); + wos.write(buffer); + wos.flush(); + assertEquals(LINE, sw.getBuffer().toString()); + } + + public void testByteAtATime() throws Exception { + String LINE = "The quick brown fox jumped over the lazy doc"; + StringWriter sw = new StringWriter(); + WriterOutputStream wos = new WriterOutputStream(sw, "UTF-8"); + byte[] buffer = LINE.getBytes(); + for (byte b : buffer) { + wos.write(b); + } + wos.flush(); + assertEquals(LINE, sw.getBuffer().toString()); + } + + public void testByteAtATimeWithFlushes() throws Exception { + String LINE = "The quick brown fox jumped over the lazy doc"; + StringWriter sw = new StringWriter(); + WriterOutputStream wos = new WriterOutputStream(sw, "UTF-8"); + byte[] buffer = LINE.getBytes(); + for (int i = 0; i < buffer.length; i++) { + wos.write(buffer[i]); + wos.flush(); + assertEquals(LINE.charAt(i), sw.getBuffer().charAt(i)); + } + assertEquals(LINE, sw.getBuffer().toString()); + } + + public void testUnicode() throws Exception { + char[] chars = new char[8192]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) i; + } + byte[] buffer = new String(chars).getBytes(); + StringWriter sw = new StringWriter(); + WriterOutputStream wos = new WriterOutputStream(sw, "UTF-8"); + wos.write(buffer); + wos.flush(); + StringBuffer sb = sw.getBuffer(); + assertEquals(chars.length, sb.length()); + for (int i = 0; i < chars.length; i++) { + assertEquals(chars[i], sb.charAt(i)); + } + } + + public void testBadUnicode() throws Exception { + byte[] BAD = new byte[] {(byte) 0x80}; + StringWriter sw = new StringWriter(); + WriterOutputStream wos = new WriterOutputStream(sw, "UTF-8"); + try { + wos.write(BAD); + wos.flush(); + fail("no exception thrown"); + } catch (MalformedInputException ex) { + // expected + } + } + + public void testBadUnicode2() throws Exception { + byte[] BAD = new byte[] {(byte) 'h', (byte) 'i', (byte) 0x80}; + StringWriter sw = new StringWriter(); + WriterOutputStream wos = new WriterOutputStream(sw, "UTF-8"); + try { + wos.write(BAD); + wos.flush(); + fail("no exception thrown"); + } catch (MalformedInputException ex) { + // expected + assertEquals("hi", sw.getBuffer().toString()); + } + } + + public void testBadUnicode3() throws Exception { + byte[] BAD = new byte[] {(byte) 'h', (byte) 'i', (byte) 0xc2, (byte) 0x00}; + StringWriter sw = new StringWriter(); + WriterOutputStream wos = new WriterOutputStream(sw, "UTF-8"); + try { + wos.write(BAD); + wos.flush(); + fail("no exception thrown"); + } catch (MalformedInputException ex) { + // expected + assertEquals("hi", sw.getBuffer().toString()); + } + } + + public void testBadUnicode4() throws Exception { + byte[] BAD = new byte[] {(byte) 'h', (byte) 'i', (byte) 0xc2}; + StringWriter sw = new StringWriter(); + WriterOutputStream wos = new WriterOutputStream(sw, "UTF-8"); + wos.write(BAD); + wos.flush(); + try { + wos.close(); + fail("no exception thrown"); + } catch (MalformedInputException ex) { + // expected + assertEquals("hi", sw.getBuffer().toString()); + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |