gt: 		if (avail <= 0)
context: // ========================================================================
  // $Id: LineInput.java,v 1.17 2005/10/05 11:32:40 gregwilkins Exp $
  // Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
  // ------------------------------------------------------------------------
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at 
  // http://www.apache.org/licenses/LICENSE-2.0
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  // ========================================================================
  
  package org.browsermob.proxy.jetty.util;
  
  import org.apache.commons.logging.Log;
  import org.browsermob.proxy.jetty.log.LogFactory;
  
  import java.io.*;
  
  // TODO: Auto-generated Javadoc
  /* ------------------------------------------------------------ */
  /**
   * Fast LineInput InputStream. This buffered InputStream provides methods for
   * reading lines of bytes. The lines can be converted to String or character
   * arrays either using the default encoding or a user supplied encoding.
   * 
   * Buffering and data copying are highly optimized, making this an ideal class
   * for protocols that mix character encoding lines with arbitrary byte data (eg
   * HTTP).
   * 
   * The buffer size is also the maximum line length in bytes and/or characters.
   * If the byte length of a line is less than the max, but the character length
   * is greater, than then trailing characters are lost.
   * 
   * Line termination is forgiving and accepts CR, LF, CRLF or EOF. Line input
   * uses the mark/reset mechanism, so any marks set prior to a readLine call are
   * lost.
   * 
   * @version $Id: LineInput.java,v 1.17 2005/10/05 11:32:40 gregwilkins Exp $
   * @author Greg Wilkins (gregw)
   */
  public class LineInput extends FilterInputStream {
  
  	/** The log. */
  	private static Log log = LogFactory.getLog(LineInput.class);
  
  	/* ------------------------------------------------------------ */
  	/** The _buf. */
  	private byte _buf[];
  
  	/** The _byte buffer. */
  	private ByteBuffer _byteBuffer;
  
  	/** The _reader. */
  	private InputStreamReader _reader;
  
  	/** The _mark. */
  	private int _mark = -1; // reset marker
  
  	/** The _pos. */
  	private int _pos; // Start marker
  
  	/** The _avail. */
  	private int _avail; // Available back marker, may be byte limited
  
  	/** The _contents. */
  	private int _contents; // Absolute back marker of buffer
  
  	/** The _byte limit. */
  	private int _byteLimit = -1;
  
  	/** The _new byte limit. */
  	private boolean _newByteLimit;
  
  	/** The _line buffer. */
  	private LineBuffer _lineBuffer;
  
  	/** The _encoding. */
  	private String _encoding;
  
  	/** The _eof. */
  	private boolean _eof = false;
  
  	/** The _last cr. */
  	private boolean _lastCr = false;
  
  	/** The _seen cr lf. */
  	private boolean _seenCrLf = false;
  
  	/** The Constant LF. */
  	private final static int LF = 10;
  
  	/** The Constant CR. */
  	private final static int CR = 13;
  
  	/* ------------------------------------------------------------ */
  	/**
  	 * Constructor. Default buffer and maximum line size is 2048.
  	 * 
  	 * @param in
  	 *            The underlying input stream.
  	 */
  	public LineInput(InputStream in) {
  		this(in, 0);
  	}
  
  	/* ------------------------------------------------------------ */
  	/**
  	 * Constructor.
  	 * 
  	 * @param in
  	 *            The underlying input stream.
  	 * @param bufferSize
  	 *            The buffer size and maximum line length.
  	 */
  	public LineInput(InputStream in, int bufferSize) {
  		super(in);
  		_mark = -1;
  		if (bufferSize == 0)
  			bufferSize = 8192;
  		_buf = ByteArrayPool.getByteArray(bufferSize);
  		_byteBuffer = new ByteBuffer(_buf);
  		_lineBuffer = new LineBuffer(bufferSize);
  
  		try {
  			_reader = new InputStreamReader(_byteBuffer, "UTF-8");
  		} catch (UnsupportedEncodingException e) {
  			_reader = new InputStreamReader(_byteBuffer);
  		}
  	}
  
  	/* ------------------------------------------------------------ */
  	/**
  	 * Constructor.
  	 * 
  	 * @param in
  	 *            The underlying input stream.
  	 * @param bufferSize
  	 *            The buffer size and maximum line length.
  	 * @param encoding
  	 *            the character encoding to use for readLine methods.
  	 * @throws UnsupportedEncodingException
  	 *             the unsupported encoding exception
  	 */
  	public LineInput(InputStream in, int bufferSize, String encoding)
  			throws UnsupportedEncodingException {
  		super(in);
  		_mark = -1;
  		if (bufferSize == 0)
  			bufferSize = 2048;
  		_buf = ByteArrayPool.getByteArray(bufferSize);
  		_byteBuffer = new ByteBuffer(_buf);
  		_lineBuffer = new LineBuffer(bufferSize);
  		_reader = new InputStreamReader(_byteBuffer, encoding);
  		_encoding = encoding;
  	}
  
  	/* ------------------------------------------------------------ */
  	/**
  	 * Gets the input stream.
  	 * 
  	 * @return the input stream
  	 */
  	public InputStream getInputStream() {
  		return in;
  	}
  
  	/* ------------------------------------------------------------ */
  	/**
  	 * Set the byte limit. If set, only this number of bytes are read before
  	 * EOF.
  	 * 
  	 * @param bytes
  	 *            Limit number of bytes, or -1 for no limit.
  	 */
  	public void setByteLimit(int bytes) {
  		_byteLimit = bytes;
  
  		if (bytes >= 0) {
  			_newByteLimit = true;
  			_byteLimit -= _contents - _pos;
  			if (_byteLimit < 0) {
  				_avail += _byteLimit;
  				_byteLimit = 0;
  			}
  		} else {
  			_newByteLimit = false;
  			_avail = _contents;
  			_eof = false;
  		}
  	}
  
  	/* ------------------------------------------------------------ */
  	/**
  	 * Get the byte limit.
  	 * 
  	 * @return Number of bytes until EOF is returned or -1 for no limit.
  	 */
  	public int getByteLimit() {
  		if (_byteLimit < 0)
  			return _byteLimit;
  
  		return _byteLimit + _avail - _pos;
  	}
  
  	/* ------------------------------------------------------------ */
  	/**
  	 * Read a line ended by CR, LF or CRLF. The default or supplied encoding is
  	 * used to convert bytes to characters.
  	 * 
  	 * @return The line as a String or null for EOF.
  	 * @throws IOException
  	 *             Signals that an I/O exception has occurred.
  	 */
  	public synchronized String readLine() throws IOException {
  		int len = fillLine(_buf.length);
  
  		if (len < 0)
  			return null;
  
  		String s = null;
  		if (_encoding == null)
  			s = new String(_buf, _mark, len);
  		else {
  			try {
  				s = new String(_buf, _mark, len, _encoding);
  			} catch (UnsupportedEncodingException e) {
  				log.warn(LogSupport.EXCEPTION, e);
  			}
  		}
  		_mark = -1;
  
  		return s;
  	}
  
  	/* ------------------------------------------------------------ */
  	/**
  	 * Read a line ended by CR, LF or CRLF. The default or supplied encoding is
  	 * used to convert bytes to characters.
  	 * 
  	 * @param c
  	 *            Character buffer to place the line into.
  	 * @param off
  	 *            Offset into the buffer.
  	 * @param len
  	 *            Maximum length of line.
  	 * @return The length of the line or -1 for EOF.
  	 * @throws IOException
  	 *             Signals that an I/O exception has occurred.
  	 */
  	public int readLine(char[] c, int off, int len) throws IOException {
  		int blen = fillLine(len);
  
  		if (blen < 0)
  			return -1;
  		if (blen == 0)
  			return 0;
  
  		_byteBuffer.setStream(_mark, blen);
  
  		int read = 0;
  		while (read < len && _reader.ready()) {
  			int r = _reader.read(c, off + read, len - read);
  			if (r <= 0)
  				break;
  			read += r;
  		}
  
  		_mark = -1;
  
  		return read;
  	}
  
  	/* ------------------------------------------------------------ */
  	/**
  	 * Read a line ended by CR, LF or CRLF.
  	 * 
  	 * @param b
  	 *            Byte array to place the line into.
  	 * @param off
  	 *            Offset into the buffer.
  	 * @param len
  	 *            Maximum length of line.
  	 * @return The length of the line or -1 for EOF.
  	 * @throws IOException
  	 *             Signals that an I/O exception has occurred.
  	 */
  	public int readLine(byte[] b, int off, int len) throws IOException {
  		len = fillLine(len);
  
  		if (len < 0)
  			return -1;
  		if (len == 0)
  			return 0;
  
  		System.arraycopy(_buf, _mark, b, off, len);
  		_mark = -1;
  
  		return len;
  	}
  
  	/* ------------------------------------------------------------ */
  	/**
  	 * Read a Line ended by CR, LF or CRLF. Read a line into a shared LineBuffer
  	 * instance. The LineBuffer is resused between calls and should not be held
  	 * by the caller. The default or supplied encoding is used to convert bytes
  	 * to characters.
  	 * 
  	 * @return LineBuffer instance or null for EOF.
  	 * @throws IOException
  	 *             Signals that an I/O exception has occurred.
  	 */
  	public LineBuffer readLineBuffer() throws IOException {
  		return readLineBuffer(_buf.length);
  	}
  
  	/* ------------------------------------------------------------ */
  	/**
  	 * Read a Line ended by CR, LF or CRLF. Read a line into a shared LineBuffer
  	 * instance. The LineBuffer is resused between calls and should not be held
  	 * by the caller. The default or supplied encoding is used to convert bytes
  	 * to characters.
  	 * 
  	 * @param len
  	 *            Maximum length of a line, or 0 for default
  	 * @return LineBuffer instance or null for EOF.
  	 * @throws IOException
  	 *             Signals that an I/O exception has occurred.
  	 */
  	public LineBuffer readLineBuffer(int len) throws IOException {
  		len = fillLine(len > 0 ? len : _buf.length);
  
  		if (len < 0)
  			return null;
  
  		if (len == 0) {
  			_lineBuffer.size = 0;
  			return _lineBuffer;
  		}
  
  		_byteBuffer.setStream(_mark, len);
  
  		_lineBuffer.size = 0;
  		int read = 0;
  		while (read < len && _reader.ready()) {
  			int r = _reader.read(_lineBuffer.buffer, read, len - read);
  			if (r <= 0)
  				break;
  			read += r;
  		}
  		_lineBuffer.size = read;
  		_mark = -1;
  
  		return _lineBuffer;
  	}
  
  	/* ------------------------------------------------------------ */
  	/*
  	 * (non-Javadoc)
  	 * 
  	 * @see java.io.FilterInputStream#read()
  	 */
  	public synchronized int read() throws IOException {
  		int b;
  		if (_pos >= _avail)
  			fill();
  		if (_pos >= _avail)
  			b = -1;
  		else
  			b = _buf[_pos++] & 255;
  
  		return b;
  	}
  
  	/* ------------------------------------------------------------ */
  	/*
  	 * (non-Javadoc)
  	 * 
  	 * @see java.io.FilterInputStream#read(byte[], int, int)
  	 */
  	public synchronized int read(byte b[], int off, int len) throws IOException {
  		int avail = _avail - _pos;
  		if (avail <= 0) {
  			fill();
  			avail = _avail - _pos;
  		}
  
  		if (avail <= 0)
  			len = -1;
  		else {
  			len = (avail < len) ? avail : len;
  			System.arraycopy(_buf, _pos, b, off, len);
  			_pos += len;
  		}
  
  		return len;
  	}
  
  	/* ------------------------------------------------------------ */
  	/*
  	 * (non-Javadoc)
  	 * 
  	 * @see java.io.FilterInputStream#skip(long)
  	 */
  	public long skip(long n) throws IOException {
  		int avail = _avail - _pos;
  		if (avail <= 0) {
  			fill();
  			avail = _avail - _pos;
  		}
  
  