/* ChunkedInputStream.java --
   Copyright (C) 2004, 2006 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.net.protocol.http;

import java.io.IOException;
import java.io.InputStream;
import java.net.ProtocolException;


//
// Note that we rely on the implemtation of skip() in the super class
// (InputStream) calling our read methods to account for chunk headers
// while skipping.
//


/**
 * Input stream wrapper for the "chunked" transfer-coding.
 *
 * @author Chris Burdess (dog@gnu.org)
 */
public class ChunkedInputStream
  extends InputStream
{

  private static final byte CR = 0x0d;
  private static final byte LF = 0x0a;

  Headers headers;

  /** The underlying stream. */
  private InputStream in;

  /** Size of the chunk we're reading.  */
  int size;
  /** Number of bytes we've read in this chunk.  */
  int count;
  /**
   * True when we should read meta-information, false when we should
   * read data.
   */
  boolean meta;
  /** True when we've hit EOF.  */
  boolean eof;

  /**
   * Constructor.
   * @param in the response socket input stream
   * @param headers the headers to receive additional header lines
   */
  public ChunkedInputStream(InputStream in, Headers headers)
  {
    this.in = in;
    this.headers = headers;
    size = -1;
    count = 0;
    meta = true;
  }

  public int read()
    throws IOException
  {
    byte[] buf = new byte[1];
    int len = read(buf, 0, 1);
    if (len == -1)
      {
        return -1;
      }
    return 0xff & buf[0];
  }

  public synchronized int read(byte[] buffer, int offset, int length)
    throws IOException
  {
    if (eof)
      {
        return -1;
      }
    if (meta)
      {
        // Read chunk header
        int c, last = 0;
        boolean seenSemi = false;
        StringBuilder buf = new StringBuilder();
        do
          {
            c = in.read();
            if (c == 0x3b) // ;
              {
                seenSemi = true;
              }
            else if (c == 0x0a && last == 0x0d) // CRLF
              {
                try
                  {
                    size = Integer.parseInt(buf.toString(), 16);
                  }
                catch (NumberFormatException nfe)
                  {
                    IOException ioe = new IOException("Bad chunk header");
                    ioe.initCause(nfe);
                    // Unrecoverable.  Don't try to read more.
                    in.close();
                    throw ioe;
                  }
                break;
              }
            else if (!seenSemi && c >= 0x30)
              {
                buf.append ((char) c);
              }
            last = c;
          }
        while(c != -1);
        count = 0;
        meta = false;
      }
    if (size == 0)
      {
        // Read trailer
        headers.parse(in);
        eof = true;
        return -1;
      }
    else
      {
	int canRead = Math.min(size - count, length);
	int len = in.read(buffer, offset, canRead);
	if (len == -1)
	  {
	    // This is an error condition but it isn't clear what we
	    // should do with it.
	    eof = true;
	    return -1;
	  }
        count += len;
        if (count == size)
          {
            // Read CRLF
            int c1 = in.read();
            int c2 = in.read();
            if (c1 == -1 || c2 == -1)
              {
                // EOF before CRLF: bad, but ignore
                eof = true;
                return -1;
              }
            if (c1 != 0x0d || c2 != 0x0a)
              {
                throw new ProtocolException("expecting CRLF: " + c1 + "," + c2);
              }
            meta = true;
          }
        return len;
      }
  }

  /**
   * This method returns the number of bytes that can be read from
   * this stream before a read might block.  Even if the underlying
   * InputStream has data available past the end of the current chunk,
   * we have no way of knowing how large the next chunk header will
   * be. So we cannot report available data past the current chunk.
   *
   * @return The number of bytes that can be read before a read might
   * block
   *
   * @exception IOException If an error occurs
   */
  public int available() throws IOException
  {
    if (meta)
      return 0;
    
    return Math.min(in.available(), size - count);
  }

  /**
   * This method closes the ChunkedInputStream by closing the underlying
   * InputStream.
   * 
   * @exception IOException If an error occurs
   */
  public void close() throws IOException
  {
    in.close();
  }
  
}

