/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301 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
  {
    synchronized (lock)
      {
        // 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
  {
    synchronized (lock)
      {
        channel.close();

        // Makes sure all intermediate data is released by the decoder.
        if (decoder != null)
          decoder.reset();
      }
  }

}
