gt: 				return position>=end? -1: get(position++)&255;
context: /* XXL: The eXtensible and fleXible Library for data processing
  
  Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger
                          Head of the Database Research Group
                          Department of Mathematics and Computer Science
                          University of Marburg
                          Germany
  
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 3 of the License, or (at your option) any later version.
  
  This library 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
  Lesser General Public License for more details.
  
  You should have received a copy of the GNU Lesser General Public
  License along with this library;  If not, see <http://www.gnu.org/licenses/>. 
  
      http://code.google.com/p/xxl/
  
  */
  
  package xxl.core.io;
  
  import java.io.ByteArrayOutputStream;
  import java.io.DataInputStream;
  import java.io.DataOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.text.DecimalFormat;
  import java.util.zip.ZipEntry;
  import java.util.zip.ZipInputStream;
  import java.util.zip.ZipOutputStream;
  
  import xxl.core.functions.AbstractFunction;
  import xxl.core.functions.Function;
  import xxl.core.predicates.InputStreamEqualPredicate;
  import xxl.core.util.WrappingRuntimeException;
  
  /**
   * This class provides a block of serialized data. A block wraps a byte
   * array that stores the serialized data and adds methods for reading and
   * writing single bytes or the whole block. The block can additionally be
   * released when its serialized data is not longer needed.<p>
   *
   * Example usage (1).
   * <pre>
   *     // create a new block of five bytes
   *
   *     Block block = new Block(5);
   *
   *     // catch IOExceptions
   *
   *     try {
   *
   *         // open a data output stream on the block
   *
   *         DataOutputStream output = block.dataOutputStream();
   *
   *         // write the bytes 0 to 4 to the data output stream
   *
   *         for (int i = 0; i < 5; i++)
   *             output.write(i);
   *
   *         // invert every bit of the block
   *
   *         for (int i = 0; i < block.size; i++)
   *             block.set(i, (byte)block.get(i));
   *
   *         // open a data input stream on the block
   *
   *         DataInputStream input = block.dataInputStream();
   *
   *         // print the five bytes contained by the block
   *
   *         while (input.available()>0)
   *             System.out.println(input.read());
   *
   *     }
   *     catch (IOException ioe) {
   *         System.out.println("An I/O error occured.");
   *     }
   *
   *     // release the block
   *
   *     block.release();
   * </pre>
   *
   * @see DataInputStream
   * @see DataOutputStream
   * @see InputStream
   * @see IOException
   * @see OutputStream
   */
  public class Block implements Cloneable, SizeAware {
  
  	/**
  	 * Writes the length to the beginning of a Block using little endian byte ordering (4 bytes).
  	 * The function returns the block.
  	 */
  	public static Function SET_REAL_LENGTH = new AbstractFunction() {
  		public Object invoke (Object block, Object len) {
  			((Block) block).writeInteger(0,((Integer)len).intValue());
  			return null;
  		}
  	};
  
  	/** 
  	 * Gets the length from the beginning of a Block. Not every Block contains this information!
  	 */
  	public static Function GET_REAL_LENGTH = new AbstractFunction() {
  		public Object invoke (Object block) {
  			return new Integer(((Block) block).readInteger(0));
  		}
  	};
  
  	/**
  	 * The byte array stores the serialized data of the block. The block
  	 * starts at index <tt>offset</tt> of the array and contains
  	 * <tt>size</tt> bytes.
  	 */
  	public byte [] array;
  
  	/**
  	 * The <tt>int</tt> value <tt>offset</tt> determines the index of the
  	 * byte array where this block starts. Bytes at indices that are less
  	 * than <tt>offset</tt> did not belong to this block.
  	 */
  	public int offset;
  
  	/**
  	 * The <tt>int</tt> value <tt>size</tt> determines the number of bytes
  	 * this block is able to store.
  	 */
  	public int size;
  
  	/**
  	 * The flag <tt>released</tt> signals whether this block is released
  	 * or not. It is not possible to access a released block in order to
  	 * read or write bytes.
  	 */
  	protected boolean released = false;
  
  	/**
  	 * Constructs a new Block that wraps the specified array. The block
  	 * starts at the index of the byte array specified by <tt>offset</tt>
  	 * and contain <tt>size</tt> bytes.
  	 *
  	 * @param array the byte array that contains the serialized data of
  	 *        the block.
  	 * @param offset the index of the byte array where the block starts.
  	 * @param size the number of bytes the block contains.
  	 * @throws IllegalArgumentException when the byte array is not able to
  	 *         store this block. In other words, an exception is thrown
  	 *         when <code>(array.length&lt;offset+size)</code>.
  	 */
  	public Block (byte [] array, int offset, int size) throws IllegalArgumentException {
  		if (array.length<offset+size)
  			throw new IllegalArgumentException();
  		this.array = array;
  		this.offset = offset;
  		this.size = size;
  	}
  
  	/**
  	 * Constructs a new Block that wraps the specified array. The whole
  	 * byte array is used for storing the block. This constructor is
  	 * equivalent to the call of
  	 * <code>Block(array, 0, array.length)</code>.
  	 *
  	 * @param array the byte array that contains the serialized data of
  	 *        the block.
  	 */
  	public Block (byte [] array) {
  		this(array, 0, array.length);
  	}
  
  	/**
  	 * Constructs a new Block that contains a number of bytes specified by
  	 * <tt>blockSize</tt>. The block creates a new byte array in order to
  	 * store its serialized data. This constructor is equivalent to the
  	 * call of <code>Block(new byte[blockSize], 0, blockSize)</code>.
  	 *
  	 * @param blockSize the number of bytes the block contains.
  	 */
  	public Block (int blockSize) {
  		this(new byte[blockSize], 0, blockSize);
  	}
  
  	/**
  	 * Signals that the serialized data of this block is no longer needed
  	 * and releses the block. After releasing a block, it is not possible
  	 * to access it in order to read or write bytes.<br>
  	 * Note that this method is not idempotent. A call of this method on a
  	 * released block will cause an <tt>IllegalStateException</tt>.
  	 *
  	 * @throws IllegalStateException if this block is already released.
  	 */
  	public void release () throws IllegalStateException {
  		if (released)
  			throw new IllegalStateException("Block has already been released.");
  		released = true;
  	}
  
  	/**
  	 * Replaces the byte at the specified index of this block with the
  	 * specified byte and returns the set byte. When this block is
  	 * released or the specified index is out of its bounds, an exception
  	 * will be thrown.
  	 *
  	 * @param index the index of the byte that should be set.
  	 * @param b the new value of the byte at index <tt>index</tt>.
  	 * @return the set byte.
  	 * @throws IllegalStateException if this block is already released.
  	 * @throws IndexOutOfBoundsException if the specified index is out of
  	 *         this block's bounds. In other words, an exception is thrown
  	 *         when <code>(index<0 || index>=size)</code>.
  	 */
  	public byte set (int index, byte b) throws IllegalStateException, IndexOutOfBoundsException {
  		if (released)
  			throw new IllegalStateException("Block has already been released.");
  		if (index<0 || index>=size)
  			throw new IndexOutOfBoundsException("Index accessed: "+index);
  		return array[offset+index] = b;
  	}
  
  	/**
  	 * Returns the byte at the specified index of this block. When this
  	 * block is released or the specified index is out of its bounds, an
  	 * exception will be thrown.
  	 *
  	 * @param index position which is retrieved.
  	 * @return the byte at the specified index.
  	 * @throws IllegalStateException if this block is already released.
  	 * @throws IndexOutOfBoundsException if the specified index is out of
  	 *         this block's bounds. In other words, an exception is thrown
  	 *         when <code>(index<0 || index>=size)</code>.
  	 */
  	public byte get (int index) throws IllegalStateException, IndexOutOfBoundsException {
  		if (released)
  			throw new IllegalStateException("Block has already been released.");
  		if (index<0 || index>=size)
  			throw new IndexOutOfBoundsException();
  		return array[offset+index];
  	}
  
  	/**
  	 * Writes an integer inside the Block to a specified position (little endian).
  	 * @param position write offset
  	 * @param value value to be written
  	 */
  	public void writeInteger(int position, int value) {
  		ByteArrayConversions.convIntToByteArrayLE(value, array, position);
  	}
  
  	/**
  	 * Reads an integer from a specified position inside the Block (little endian).
  	 * @param position read offset
  	 * @return the integer value
  	 */
  	public int readInteger(int position) {
  		return ByteArrayConversions.convIntLE(array, position);
  	}
  
  	/**
  	 * Writes a long inside the Block to a specified position (little endian).
  	 * @param position write offset
  	 * @param value value to be written
  	 */
  	public void writeLong(int position, long value) {
  		ByteArrayConversions.convLongToByteArrayLE(value, array, position);
  	}
  
  	/**
  	 * Reads a long from a specified position inside the Block (little endian).
  	 * @param position read offset
  	 * @return the long value
  	 */
  	public long readLong(int position) {
  		return ByteArrayConversions.convLongLE(array, position);
  	}
  
  	/**
  	 * Returns a new output stream that depends on this block. The output
  	 * stream starts writing at index <tt>base</tt> (<i>inclusive</i>) and
  	 * stops at index <tt>end</tt> (<i>exclusive</i>) of this block. When
  	 * writing more than <tt>(end-base)</tt> bytes, the write method of
  	 * the output stream will cause an <tt>IOException</tt>.
  	 *
  	 * @param base the index of this block where the output stream starts
  	 *        writing (<i>inclusive</i>).
  	 * @param end the index of this block where the output stream stops
  	 *        writing (<i>exclusive</i>).
  	 * @return a new output stream, that depends on this block.
  	 */
  	public OutputStream outputStream(final int base, final int end) {
  		return new OutputStream() {
  			int position = base;
  
  			public final void write(int b) throws IOException {
  				if (released)
  					throw new IllegalStateException("Block has already been released.");
  				if (position >= end)
  					throw new IndexOutOfBoundsException("Index accessed: "+(position+1));
  				array[offset+position] = (byte)b;
  				position++;
  			}
  
  			public final void write(byte[] b) throws IOException {
  				write(b, 0, b.length);
  			}
  
  			public final void write(byte[] b, int off, int len) throws IOException {
  				if (released)
  					throw new IllegalStateException("Block has already been released.");
  				if (position<0 || position+len > end)
  					throw new IndexOutOfBoundsException("Index accessed: "+(position+len));
  				System.arraycopy(b, off, array, position, len);
  				position += len;
  			}
  		};
  	}
  
  	/**
  	 * Returns a new output stream that depends on this block. The output
  	 * stream starts writing at index <tt>base</tt> (<i>inclusive</i>) and
  	 * stops at the end of this block. When writing more than
  	 * <tt>(size-base)</tt> bytes, the write method of the output stream
  	 * will cause an <tt>IOException</tt>.
  	 *
  	 * @param base the index of this block where the output stream starts
  	 *        writing (<i>inclusive</i>).
  	 * @return a new output stream, that depends on this block.
  	 */
  	public OutputStream outputStream (final int base) {
  		return outputStream(base, size);
  	}
  
  	/**
  	 * Returns a new output stream that depends on this block. The output
  	 * stream writes the whole block. When writing more than <tt>size</tt>
  	 * bytes, the write method of the output stream will cause an
  	 * <tt>IOException</tt>.
  	 *
  	 * @return a new output stream, that depends on this block.
  	 */
  	public OutputStream outputStream () {
  		return outputStream(0);
  	}
  
  	/**
  	 * Returns a new data output stream that depends on this block. The
  	 * data output stream wraps an output stream created by calling
  	 * <code>outputStream(base, end)</code>. The underlying output stream
  	 * starts writing at index <tt>base</tt> (<i>inclusive</i>) and stops
  	 * at index <tt>end</tt> (<i>exclusive</i>) of this block. When
  	 * writing more than <tt>(end-base)</tt> bytes, the write method of
  	 * the underlying output stream will cause an <tt>IOException</tt>.
  	 *
  	 * @param base the index of this block where the data output stream
  	 *        starts writing (<i>inclusive</i>).
  	 * @param end the index of this block where the data output stream
  	 *        stops writing (<i>exclusive</i>).
  	 * @return a new data output stream, that depends on this block.
  	 */
  	public DataOutputStream dataOutputStream (int base, int end) {
  		return new DataOutputStream(outputStream(base, end));
  	}
  
  	/**
  	 * Returns a new data output stream that depends on this block. The
  	 * data output stream wraps an output stream created by calling
  	 * <code>outputStream(base)</code>. The underlying output stream
  	 * starts writing at index <tt>base</tt> (<i>inclusive</i>) and stops
  	 * at the end of this block. When writing more than
  	 * <tt>(size-base)</tt> bytes, the write method of the underlying
  	 * output stream will cause an <tt>IOException</tt>.
  	 *
  	 * @param base the index of this block where the data output stream
  	 *        starts writing (<i>inclusive</i>).
  	 * @return a new data output stream, that depends on this block.
  	 */
  	public DataOutputStream dataOutputStream (int base) {
  		return new DataOutputStream(outputStream(base));
  	}
  
  	/**
  	 * Returns a new data output stream that depends on this block. The
  	 * data output stream wraps an output stream created by calling
  	 * <code>outputStream()</code>. The underlying output stream writes
  	 * the whole block. When writing more than <tt>size</tt> bytes, the
  	 * write method of the underlying output stream will cause an
  	 * <tt>IOException</tt>.
  	 *
  	 * @return a new data output stream, that depends on this block.
  	 */
  	public DataOutputStream dataOutputStream () {
  		return new DataOutputStream(outputStream());
  	}
  
  	/**
  	 * Returns a new input stream that depends on this block. The input
  	 * stream starts reading at index <tt>base</tt> (<i>inclusive</i>) and
  	 * stops at index <tt>end</tt> (<i>exclusive</i>) of this block. When
  	 * reading more than <tt>(end-base)</tt> bytes, the read method of the
  	 * input stream will return <tt>-1</tt>.
  	 *
  	 * @param base the index of this block where the input stream starts
  	 *        reading (<i>inclusive</i>).
  	 * @param end the index of this block where the input stream stops
  	 *        reading (<i>exclusive</i>).
  	 * @return a new input stream, that depends on this block.
  	 */
  	public InputStream inputStream (final int base, final int end) {
  		return new InputStream () {
  			int position = base;
  
  			public final int read () {
  