/* java.util.zip.StreamManipulator
   Copyright (C) 2001 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 java.util.zip;

/**
 * This class allows us to retrieve a specified amount of bits from
 * the input buffer, as well as copy big byte blocks.
 *
 * It uses an int buffer to store up to 31 bits for direct
 * manipulation.  This guarantees that we can get at least 16 bits,
 * but we only need at most 15, so this is all safe.
 *
 * There are some optimizations in this class, for example, you must
 * never peek more then 8 bits more than needed, and you must first 
 * peek bits before you may drop them.  This is not a general purpose
 * class but optimized for the behaviour of the Inflater.
 *
 * @author John Leuner, Jochen Hoenicke
 */

class StreamManipulator
{
  private byte[] window;
  private int window_start = 0;
  private int window_end = 0;

  private int buffer = 0;
  private int bits_in_buffer = 0;

  /**
   * Get the next n bits but don't increase input pointer.  n must be
   * less or equal 16 and if you if this call succeeds, you must drop
   * at least n-8 bits in the next call.
   * 
   * @return the value of the bits, or -1 if not enough bits available.  */
  public final int peekBits(int n)
  {
    if (bits_in_buffer < n)
      {
	if (window_start == window_end)
	  return -1;
	buffer |= (window[window_start++] & 0xff
		   | (window[window_start++] & 0xff) << 8) << bits_in_buffer;
	bits_in_buffer += 16;
      }
    return buffer & ((1 << n) - 1);
  }

  /* Drops the next n bits from the input.  You should have called peekBits
   * with a bigger or equal n before, to make sure that enough bits are in
   * the bit buffer.
   */
  public final void dropBits(int n)
  {
    buffer >>>= n;
    bits_in_buffer -= n;
  }

  /**
   * Gets the next n bits and increases input pointer.  This is equivalent
   * to peekBits followed by dropBits, except for correct error handling.
   * @return the value of the bits, or -1 if not enough bits available. 
   */
  public final int getBits(int n)
  {
    int bits = peekBits(n);
    if (bits >= 0)
      dropBits(n);
    return bits;
  }
  /**
   * Gets the number of bits available in the bit buffer.  This must be
   * only called when a previous peekBits() returned -1.
   * @return the number of bits available.
   */
  public final int getAvailableBits()
  {
    return bits_in_buffer;
  }

  /**
   * Gets the number of bytes available.  
   * @return the number of bytes available.
   */
  public final int getAvailableBytes()
  {
    return window_end - window_start + (bits_in_buffer >> 3);
  }

  /**
   * Skips to the next byte boundary.
   */
  public void skipToByteBoundary()
  {
    buffer >>= (bits_in_buffer & 7);
    bits_in_buffer &= ~7;
  }

  public final boolean needsInput() {
    return window_start == window_end;
  }


  /* Copies length bytes from input buffer to output buffer starting
   * at output[offset].  You have to make sure, that the buffer is
   * byte aligned.  If not enough bytes are available, copies fewer
   * bytes.
   * @param length the length to copy, 0 is allowed.
   * @return the number of bytes copied, 0 if no byte is available.  
   */
  public int copyBytes(byte[] output, int offset, int length)
  {
    if (length < 0)
      throw new IllegalArgumentException("length negative");
    if ((bits_in_buffer & 7) != 0)  
      /* bits_in_buffer may only be 0 or 8 */
      throw new IllegalStateException("Bit buffer is not aligned!");

    int count = 0;
    while (bits_in_buffer > 0 && length > 0)
      {
	output[offset++] = (byte) buffer;
	buffer >>>= 8;
	bits_in_buffer -= 8;
	length--;
	count++;
      }
    if (length == 0)
      return count;

    int avail = window_end - window_start;
    if (length > avail)
      length = avail;
    System.arraycopy(window, window_start, output, offset, length);
    window_start += length;

    if (((window_start - window_end) & 1) != 0)
      {
	/* We always want an even number of bytes in input, see peekBits */
	buffer = (window[window_start++] & 0xff);
	bits_in_buffer = 8;
      }
    return count + length;
  }

  public StreamManipulator()
  {
  }

  public void reset()
  {
    window_start = window_end = buffer = bits_in_buffer = 0;
  }

  public void setInput(byte[] buf, int off, int len)
  {
    if (window_start < window_end)
      throw new IllegalStateException
	("Old input was not completely processed");

    int end = off + len;

    /* We want to throw an ArrayIndexOutOfBoundsException early.  The
     * check is very tricky: it also handles integer wrap around.  
     */
    if (0 > off || off > end || end > buf.length)
      throw new ArrayIndexOutOfBoundsException();
    
    if ((len & 1) != 0)
      {
	/* We always want an even number of bytes in input, see peekBits */
	buffer |= (buf[off++] & 0xff) << bits_in_buffer;
	bits_in_buffer += 8;
      }
    
    window = buf;
    window_start = off;
    window_end = end;
  }
}

