[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [cp-patches] RFC: ChannelReader #2
From: |
Robert Schuster |
Subject: |
Re: [cp-patches] RFC: ChannelReader #2 |
Date: |
Mon, 31 Jan 2005 23:35:44 +0100 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.5) Gecko/20050107 |
Hi.
However Channels had only a stub implementation for
newReader(ReadableByteChannel, CharsetDecoder). I changed that by
writing the adapter: gnu.java.nio.ChannelReader .
Which isn't included in the patch :( It's not just me then.
Arg. Yes this is because I forgot to 'cvs add' the file :(
One thing that occurred to me from looking at the patch (without the
class, I couldn't compile). If you remove the decoder instance
(replacing it with Reader), how do the other constructors and the rest
of the class still operate?
gnu.java.io.decode.Decoder is a subclass of reader.
Ok here is the same patch but now with the ChannelReader class
included. I plan to clean up this thing in the next days (probably at
weekend).
@Michael: This patch does not make existing things slower.
cu
Robert
|
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 31 Jan 2005 22:22:44 -0000
@@ -0,0 +1,240 @@
+/* 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
+ * </p>
+ *
+ * @author Robert Schuster
+ */
+public class ChannelReader extends Reader
+{
+
+ private static final int DEFAULT_BUFFER_CAP = 512;
+
+ 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;
+
+ // TODO: find out how 'it' behaves
+ decoder.onMalformedInput(CodingErrorAction.IGNORE);
+ decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ 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 == null)
+ 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);
+
+ /*
+ * 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 == CoderResult.UNDERFLOW)
+ {
+ // 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;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.io.Reader#close()
+ */
+
+ public void close() throws IOException
+ {
+ // Makes sure all intermediate data is released by the decoder.
+ if (decoder != null)
+ decoder.reset();
+
+ if (channel != null)
+ {
+ channel.close();
+ channel = null;
+ }
+ }
+
+}
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 31 Jan 2005 22:22:46 -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,9 @@
public static Reader newReader(ReadableByteChannel ch, CharsetDecoder dec,
int minBufferCap)
{
- throw new Error("not implemented");
+ // TODO: find out how 'it' reacts on wrong arguments
+
+ return new ChannelReader(ch, dec, minBufferCap);
}
/**
@@ -124,6 +127,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");
}