|
Hi Code is unchanged but fixed block comments. cu Robert Michael Koch wrote: On Fri, Feb 18, 2005 at 03:43:33AM +0100, Robert Schuster wrote:Hi. I think I have fixed the remaining bits in the ChannelReader. This patch adds support for the two missing constructors in java.io.InputStreamReader and implements both variants of java.nio.newChannel correctly (not being stubs anymore).2005-02-18 Robert Schuster <[EMAIL PROTECTED]> * java/nio/channels/Channels: Added FIXMEs about stub method implementation. (newReader): Implemented. * java/io/InputStreamReader: (InputStreamReader(InputStream, Charset)): Implemented. (InputStreamReader(InputStream, CharsetDecoder)): Implemented. * gnu/java/nio/ChannelReader: New class. If no one objects I want to have this in for 0.14Can you please use "//" for inline comments and not "/* ... */". This is afaik much easier to read. Michael _______________________________________________ Classpath-patches mailing list [email protected] http://lists.gnu.org/mailman/listinfo/classpath-patches |
Index: java/io/InputStreamReader.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/io/InputStreamReader.java,v
retrieving revision 1.18
diff -u -r1.18 InputStreamReader.java
--- java/io/InputStreamReader.java 16 Feb 2005 11:18:37 -0000 1.18
+++ java/io/InputStreamReader.java 18 Feb 2005 02:32:14 -0000
@@ -38,8 +38,11 @@
package java.io;
+import java.nio.channels.Channels;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+
import gnu.java.io.EncodingManager;
-import gnu.java.io.decode.Decoder;
/**
* This class reads characters from a byte input stream. The characters
@@ -92,7 +95,7 @@
* This is the byte-character decoder class that does the reading and
* translation of bytes from the underlying stream.
*/
- private Decoder in;
+ private Reader in;
/**
* This method initializes a new instance of <code>InputStreamReader</code>
@@ -130,6 +133,29 @@
}
/**
+ * Creates an InputStreamReader that uses a decoder of the given
+ * charset to decode the bytes in the InputStream into
+ * characters.
+ */
+ public InputStreamReader(InputStream in, Charset charset) {
+ /* FIXME: InputStream is wrapped in Channel which is read by a
+ * Reader-implementation for channels. However to fix this we
+ * need to completely move to NIO-style character
+ * encoding/decoding.
+ */
+ this.in = Channels.newReader(Channels.newChannel(in), charset.newDecoder(), -1);
+ }
+
+ /**
+ * Creates an InputStreamReader that uses the given charset decoder
+ * to decode the bytes in the InputStream into characters.
+ */
+ public InputStreamReader(InputStream in, CharsetDecoder decoder) {
+ // FIXME: see [EMAIL PROTECTED] InputStreamReader(InputStream, Charset)
+ this.in = Channels.newReader(Channels.newChannel(in), decoder, -1);
+ }
+
+ /**
* This method closes this stream, as well as the underlying
* <code>InputStream</code>.
*
Index: java/nio/channels/Channels.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/nio/channels/Channels.java,v
retrieving revision 1.10
diff -u -r1.10 Channels.java
--- java/nio/channels/Channels.java 12 Jan 2005 10:08:13 -0000 1.10
+++ java/nio/channels/Channels.java 18 Feb 2005 02:32:15 -0000
@@ -38,6 +38,7 @@
package java.nio.channels;
+import gnu.java.nio.ChannelReader;
import gnu.java.nio.InputStreamChannel;
import gnu.java.nio.OutputStreamChannel;
@@ -102,7 +103,7 @@
public static Reader newReader(ReadableByteChannel ch, CharsetDecoder dec,
int minBufferCap)
{
- throw new Error("not implemented");
+ return new ChannelReader(ch, dec, minBufferCap);
}
/**
@@ -124,6 +125,7 @@
public static Writer newWriter(WritableByteChannel ch, CharsetEncoder enc,
int minBufferCap)
{
+ // FIXME: implement java.nio.channels.Channel.newWriter(WritableByteChannel, CharsetEncoder, int)
throw new Error("not implemented");
}
Index: gnu/java/nio/ChannelReader.java
===================================================================
RCS file: gnu/java/nio/ChannelReader.java
diff -N gnu/java/nio/ChannelReader.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gnu/java/nio/ChannelReader.java 18 Feb 2005 02:32:15 -0000
@@ -0,0 +1,239 @@
+/* ChannelReader.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.java.nio;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ * A Reader implementation that works using a ReadableByteChannel and a
+ * CharsetDecoder.
+ *
+ * <p>
+ * This is a bridge between NIO <->IO character decoding.
+ * </p>
+ *
+ * @author Robert Schuster
+ */
+public class ChannelReader extends Reader
+{
+
+ private static final int DEFAULT_BUFFER_CAP = 8192;
+
+ private ReadableByteChannel channel;
+
+ private CharsetDecoder decoder;
+
+ private ByteBuffer byteBuffer;
+
+ private CharBuffer charBuffer;
+
+ public ChannelReader(ReadableByteChannel channel, CharsetDecoder decoder,
+ int minBufferCap)
+ {
+ this.channel = channel;
+ this.decoder = decoder;
+
+ // JDK reports errors, so we do the same.
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ decoder.reset();
+
+ int size = (minBufferCap == -1) ? DEFAULT_BUFFER_CAP : minBufferCap;
+
+ /*
+ * Allocates the buffers and prepares them for reading, because that is the
+ * first operation being done on them.
+ */
+ byteBuffer = ByteBuffer.allocate(size);
+ byteBuffer.flip();
+ charBuffer = CharBuffer.allocate((int) (size * decoder.averageCharsPerByte()));
+ }
+
+ public int read(char[] buf, int offset, int count) throws IOException
+ {
+ /*
+ * I declared channel being null meaning that the reader is closed.
+ */
+ if (!channel.isOpen())
+ throw new IOException("Reader was already closed.");
+
+ /*
+ * I declared decoder being null meaning that there is no more data to read
+ * and convert.
+ */
+ if (decoder == null)
+ return -1;
+
+ /*
+ * Stores the amount of character being read. It -1 so that if no conversion
+ * occured the caller will see this as an 'end of file'.
+ */
+ int sum = -1;
+
+ /*
+ * Copies any characters which may be left from the last invocation into the
+ * destination array.
+ */
+ if (charBuffer.remaining() > 0)
+ {
+ sum = Math.min(count, charBuffer.remaining());
+ charBuffer.get(buf, offset, sum);
+
+ /*
+ * Updates the control variables according to the latest copy operation.
+ */
+ offset += sum;
+ count -= sum;
+ }
+
+ /*
+ * Copies the character which have not been put in the destination array to
+ * the beginning. If data is actually copied count will be 0. If no data is
+ * copied count is >0 and we can now convert some more characters.
+ */
+ charBuffer.compact();
+
+ int converted = 0;
+ boolean last = false;
+
+ while (count != 0)
+ {
+ /*
+ * Tries to convert some bytes (Which will intentionally fail in the
+ * first place because we have not read any bytes yet.)
+ */
+ CoderResult result = decoder.decode(byteBuffer, charBuffer, last);
+ if(result.isMalformed() || result.isUnmappable()) {
+ /* JDK throws exception when bytes are malformed for sure.
+ * FIXME: Unsure what happens when a character is simply
+ * unmappable.
+ */
+ result.throwException();
+ }
+
+ /*
+ * Marks that we should end this loop regardless whether the caller
+ * wants more chars or not, when this was the last conversion.
+ */
+ if (last)
+ {
+ decoder = null;
+ }
+ else if (result.isUnderflow())
+ {
+ // We need more bytes to do the conversion.
+
+ /*
+ * Copies the not yet converted bytes to the beginning making it
+ * being able to receive more bytes.
+ */
+ byteBuffer.compact();
+
+ // Reads in another bunch of bytes for being converted.
+ if (channel.read(byteBuffer) == -1)
+ {
+ /*
+ * If there is no more data available in the channel we mark
+ * that state for the final character conversion run which is
+ * done in the next loop iteration.
+ */
+ last = true;
+ }
+
+ // Prepares the byteBuffer for the next character conversion run.
+ byteBuffer.flip();
+ }
+
+ // Prepares the charBuffer for being drained.
+ charBuffer.flip();
+
+ converted = Math.min(count, charBuffer.remaining());
+ charBuffer.get(buf, offset, converted);
+
+ /*
+ * Copies characters which have not yet being copied into the char-Array
+ * to the beginning making it possible to read them later (If data is
+ * really copied here, then the caller has received enough characters so
+ * far.).
+ */
+ charBuffer.compact();
+
+ /*
+ * Updates the control variables according to the latest copy operation.
+ */
+ offset += converted;
+ count -= converted;
+
+ // Updates the amount of transferred characters
+ sum += converted;
+
+ if (decoder == null)
+ {
+ break;
+ }
+
+ /*
+ * Now that more characters have been transfered we let the loop decide
+ * what to do next.
+ */
+ }
+
+ // Makes the charBuffer ready for reading on the next invocation.
+ charBuffer.flip();
+
+ return sum;
+ }
+
+ public void close() throws IOException
+ {
+ channel.close();
+
+ // Makes sure all intermediate data is released by the decoder.
+ if (decoder != null)
+ decoder.reset();
+ }
+
+}
Index: java/io/InputStreamReader.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/io/InputStreamReader.java,v
retrieving revision 1.18
diff -u -r1.18 InputStreamReader.java
--- java/io/InputStreamReader.java 16 Feb 2005 11:18:37 -0000 1.18
+++ java/io/InputStreamReader.java 21 Feb 2005 18:02:59 -0000
@@ -38,8 +38,11 @@
package java.io;
+import java.nio.channels.Channels;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+
import gnu.java.io.EncodingManager;
-import gnu.java.io.decode.Decoder;
/**
* This class reads characters from a byte input stream. The characters
@@ -92,7 +95,7 @@
* This is the byte-character decoder class that does the reading and
* translation of bytes from the underlying stream.
*/
- private Decoder in;
+ private Reader in;
/**
* This method initializes a new instance of <code>InputStreamReader</code>
@@ -130,6 +133,29 @@
}
/**
+ * Creates an InputStreamReader that uses a decoder of the given
+ * charset to decode the bytes in the InputStream into
+ * characters.
+ */
+ public InputStreamReader(InputStream in, Charset charset) {
+ /* FIXME: InputStream is wrapped in Channel which is read by a
+ * Reader-implementation for channels. However to fix this we
+ * need to completely move to NIO-style character
+ * encoding/decoding.
+ */
+ this.in = Channels.newReader(Channels.newChannel(in), charset.newDecoder(), -1);
+ }
+
+ /**
+ * Creates an InputStreamReader that uses the given charset decoder
+ * to decode the bytes in the InputStream into characters.
+ */
+ public InputStreamReader(InputStream in, CharsetDecoder decoder) {
+ // FIXME: see [EMAIL PROTECTED] InputStreamReader(InputStream, Charset)
+ this.in = Channels.newReader(Channels.newChannel(in), decoder, -1);
+ }
+
+ /**
* This method closes this stream, as well as the underlying
* <code>InputStream</code>.
*
Index: java/nio/channels/Channels.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/nio/channels/Channels.java,v
retrieving revision 1.10
diff -u -r1.10 Channels.java
--- java/nio/channels/Channels.java 12 Jan 2005 10:08:13 -0000 1.10
+++ java/nio/channels/Channels.java 21 Feb 2005 18:02:59 -0000
@@ -38,6 +38,7 @@
package java.nio.channels;
+import gnu.java.nio.ChannelReader;
import gnu.java.nio.InputStreamChannel;
import gnu.java.nio.OutputStreamChannel;
@@ -102,7 +103,7 @@
public static Reader newReader(ReadableByteChannel ch, CharsetDecoder dec,
int minBufferCap)
{
- throw new Error("not implemented");
+ return new ChannelReader(ch, dec, minBufferCap);
}
/**
@@ -124,6 +125,7 @@
public static Writer newWriter(WritableByteChannel ch, CharsetEncoder enc,
int minBufferCap)
{
+ // FIXME: implement java.nio.channels.Channel.newWriter(WritableByteChannel, CharsetEncoder, int)
throw new Error("not implemented");
}
Index: gnu/java/nio/ChannelReader.java
===================================================================
RCS file: gnu/java/nio/ChannelReader.java
diff -N gnu/java/nio/ChannelReader.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gnu/java/nio/ChannelReader.java 21 Feb 2005 18:03:00 -0000
@@ -0,0 +1,239 @@
+/* ChannelReader.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.java.nio;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ * A Reader implementation that works using a ReadableByteChannel and a
+ * CharsetDecoder.
+ *
+ * <p>
+ * This is a bridge between NIO <->IO character decoding.
+ * </p>
+ *
+ * @author Robert Schuster
+ */
+public class ChannelReader extends Reader
+{
+
+ private static final int DEFAULT_BUFFER_CAP = 8192;
+
+ private ReadableByteChannel channel;
+
+ private CharsetDecoder decoder;
+
+ private ByteBuffer byteBuffer;
+
+ private CharBuffer charBuffer;
+
+ public ChannelReader(ReadableByteChannel channel, CharsetDecoder decoder,
+ int minBufferCap)
+ {
+ this.channel = channel;
+ this.decoder = decoder;
+
+ // JDK reports errors, so we do the same.
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ decoder.reset();
+
+ int size = (minBufferCap == -1) ? DEFAULT_BUFFER_CAP : minBufferCap;
+
+ /*
+ * Allocates the buffers and prepares them for reading, because that is the
+ * first operation being done on them.
+ */
+ byteBuffer = ByteBuffer.allocate(size);
+ byteBuffer.flip();
+ charBuffer = CharBuffer.allocate((int) (size * decoder.averageCharsPerByte()));
+ }
+
+ public int read(char[] buf, int offset, int count) throws IOException
+ {
+ /*
+ * I declared channel being null meaning that the reader is closed.
+ */
+ if (!channel.isOpen())
+ throw new IOException("Reader was already closed.");
+
+ /*
+ * I declared decoder being null meaning that there is no more data to read
+ * and convert.
+ */
+ if (decoder == null)
+ return -1;
+
+ /*
+ * Stores the amount of character being read. It -1 so that if no conversion
+ * occured the caller will see this as an 'end of file'.
+ */
+ int sum = -1;
+
+ /*
+ * Copies any characters which may be left from the last invocation into the
+ * destination array.
+ */
+ if (charBuffer.remaining() > 0)
+ {
+ sum = Math.min(count, charBuffer.remaining());
+ charBuffer.get(buf, offset, sum);
+
+ /*
+ * Updates the control variables according to the latest copy operation.
+ */
+ offset += sum;
+ count -= sum;
+ }
+
+ /*
+ * Copies the character which have not been put in the destination array to
+ * the beginning. If data is actually copied count will be 0. If no data is
+ * copied count is >0 and we can now convert some more characters.
+ */
+ charBuffer.compact();
+
+ int converted = 0;
+ boolean last = false;
+
+ while (count != 0)
+ {
+ /*
+ * Tries to convert some bytes (Which will intentionally fail in the
+ * first place because we have not read any bytes yet.)
+ */
+ CoderResult result = decoder.decode(byteBuffer, charBuffer, last);
+ if(result.isMalformed() || result.isUnmappable()) {
+ /* JDK throws exception when bytes are malformed for sure.
+ * FIXME: Unsure what happens when a character is simply
+ * unmappable.
+ */
+ result.throwException();
+ }
+
+ /*
+ * Marks that we should end this loop regardless whether the caller
+ * wants more chars or not, when this was the last conversion.
+ */
+ if (last)
+ {
+ decoder = null;
+ }
+ else if (result.isUnderflow())
+ {
+ // We need more bytes to do the conversion.
+
+ /*
+ * Copies the not yet converted bytes to the beginning making it
+ * being able to receive more bytes.
+ */
+ byteBuffer.compact();
+
+ // Reads in another bunch of bytes for being converted.
+ if (channel.read(byteBuffer) == -1)
+ {
+ /*
+ * If there is no more data available in the channel we mark
+ * that state for the final character conversion run which is
+ * done in the next loop iteration.
+ */
+ last = true;
+ }
+
+ // Prepares the byteBuffer for the next character conversion run.
+ byteBuffer.flip();
+ }
+
+ // Prepares the charBuffer for being drained.
+ charBuffer.flip();
+
+ converted = Math.min(count, charBuffer.remaining());
+ charBuffer.get(buf, offset, converted);
+
+ /*
+ * Copies characters which have not yet being copied into the char-Array
+ * to the beginning making it possible to read them later (If data is
+ * really copied here, then the caller has received enough characters so
+ * far.).
+ */
+ charBuffer.compact();
+
+ /*
+ * Updates the control variables according to the latest copy operation.
+ */
+ offset += converted;
+ count -= converted;
+
+ // Updates the amount of transferred characters
+ sum += converted;
+
+ if (decoder == null)
+ {
+ break;
+ }
+
+ /*
+ * Now that more characters have been transfered we let the loop decide
+ * what to do next.
+ */
+ }
+
+ // Makes the charBuffer ready for reading on the next invocation.
+ charBuffer.flip();
+
+ return sum;
+ }
+
+ public void close() throws IOException
+ {
+ channel.close();
+
+ // Makes sure all intermediate data is released by the decoder.
+ if (decoder != null)
+ decoder.reset();
+ }
+
+}
_______________________________________________ Classpath-patches mailing list [email protected] http://lists.gnu.org/mailman/listinfo/classpath-patches
