classpath-patches
[Top][All Lists]
Advanced

[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");
   }
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]