package agg.util.colim;
import java.util.Enumeration;
/**
* A IntBuffer is a sequence that is very similar to a regular
* IntArray, except that it can expand to accommodate new elements.
* <p>
* The implementation store elements in a contiguous linear memory space
* so that index-based access is very quick. When an IntBuffer's originally
* allocated memory space is exceeded, its elements are copied into a new
* memory space that is large enough to accommodate everything.
* <p>
* If an insertion causes reallocation, all iterators and references are
* invalidated; otherwise, only the iterators and references after the
* insertion point are invalidated.
* <p>
* A remove invalidates all of the iterators and references after the point
* of the remove.
*/
public class IntBuffer implements Container {
static final int HASH_SIZE = 16;
final static int defaultValue = 0;
int storage[]; // My storage.
int length; // The number of objects I currently contain.
/**
* Construct myself to be an empty IntBuffer.
*/
public IntBuffer(){
clear();
}
/**
* Construct myself to contain a specified number of null elements.
* @param size The number of elements to contain.
* @exception java.lang.IllegalArgumentException If size is negative.
*/
public IntBuffer( int size ){
if ( size < 0 )
throw new IllegalArgumentException(
"Attempt to create an IntBuffer with a negative size" );
length = size;
storage = new int[ length ];
}
/**
* Construct myself to contain a specified number of elements set to
* a particular object.
* @param size The number of elements to contain.
* @param object The initial value of each element.
* @exception java.lang.IllegalArgumentException If size is negative.
*/
public IntBuffer( int size, int object ){
this( size );
for ( int i = 0; i < length; i++ )
storage[ i ] = object;
}
/**
* Construct myself to use a specified array as my initial storage.
* @param array t is used as initial storage.
*/
public IntBuffer( int array[] ){
this( array, true );
}
IntBuffer( int array[], boolean copyBuffer ){
synchronized( array ){
length = array.length;
if ( copyBuffer ){
storage = new int[ length ];
System.arraycopy( array, 0, storage, 0, length );
}
else
storage = array;
}
}
/**
* Construct myself to be a copy of an existing IntBuffer.
* @param array The IntBuffer to copy.
*/
public IntBuffer( IntBuffer array ){
this( array.storage );
}
/**
* Return a shallow copy of myself.
*/
public synchronized Object clone(){
return new IntBuffer( this );
}
/**
* Return true if I'm equal to another object.
* @param object The object to compare myself against.
*/
public boolean equals( Object object ){
return
object instanceof IntBuffer && equals( (IntBuffer)object )
|| object instanceof IntArray && equals( (IntArray)object );
}
/**
* Return true if I contain the same items in the same order as
* another IntBuffer.
* @param buffer The IntBuffer to compare myself against.
*/
public boolean equals( IntBuffer buffer ){
return equals( new IntArray( buffer.storage ) );
}
/**
* Return true if I contain the same items in the same order as
* a IntArray.
* @param array The IntArray to compare myself against.
*/
public synchronized boolean equals( IntArray array ){
return array.equals( storage );
}
/**
* Return true if I contain the same items in the same order as
* a native array of ints.
* @param array The array to compare myself against.
*/
public boolean equals( int array[] ){
return equals( new IntArray( array ) );
}
/**
* Return a string that describes me.
*/
@SuppressWarnings("rawtypes")
public synchronized String toString() {
StringBuffer buffer = new StringBuffer( "IntBuffer" );
buffer.append( "(" );
boolean first = true;
java.util.Enumeration iter = this.begin();
while ( iter.hasMoreElements() ){
if ( first ){
buffer.append( " " );
first = false;
}
else
buffer.append( ", " );
buffer.append( iter.nextElement() );
}
if ( first )
buffer.append( ")" );
else
buffer.append( " )" );
return buffer.toString();
}
/**
* Become a shallow copy of an existing IntBuffer.
* @param buffer The IntBuffer that I shall become a shallow copy of.
*/
public synchronized void copy( IntBuffer buffer ){
if ( this == buffer )
return;
synchronized( buffer ){
if ( buffer.length > storage.length ){
storage = buffer.get();
}
else{
System.arraycopy( buffer.storage, 0, storage, 0, buffer.length );
for ( int i = buffer.length; i < length; ++i )
storage[ i ] = defaultValue; // To avoid suprises later
}
length = buffer.length;
}
}
/**
* Copy my elements into the specified array.
* The number of items that are copied is equal to the smaller of my
* length and the size of the specified array.
* @param array The array that I shall copy my elements into.
*/
public synchronized void copyTo( int[] array ){
synchronized( array ){
System.arraycopy( storage, 0, array, 0, Math.min( length, array.length ) );
}
}
/**
* Retrieve the underlying primitive array.
*/
public synchronized int[] get(){
int data[] = new int[ length ];
copyTo( data );
return data;
}
/**
* Return my hash code for support of hashing containers
*/
public synchronized int hashCode(){
return orderedHash( begin(), length );
}
/**
* Return true if I contain no objects.
*/
public boolean isEmpty(){
return size() == 0;
}
/**
* Return my last element.
*/
public Object back(){
return at( size() - 1 );
}
/**
* Return my first element.
*/
public Object front(){
return at( 0 );
}
/**
* Return the number of entries that I contain.
*/
public int size(){
return length;
}
/**
* Return the number of elements that I contain without allocating more
* internal storage.
*/
public int capacity(){
return storage.length;
}
/**
* Return the maximum number of entries that I can contain.
*/
public int maxSize(){
return Integer.MAX_VALUE;
}
/**
* Return the element at the specified index.
* @param index The index.
* @exception java.lang.IndexOutOfBoundsException If the index is invalid.
*/
public Object at( int index ){
return new Integer( intAt( index ) );
}
/**
* Return the int at the specified index.
* @param index The index.
* @exception java.lang.IndexOutOfBoundsException If the index is invalid.
*/
public synchronized int intAt( int index ){
IntArray.checkIndex( index, length );
return storage[ index ];
}
/**
* Set the element at the specified index to a particular object.
* @param index The index.
* @param object The object.
* @exception java.lang.IndexOutOfBoundsException If the index is invalid.
*/
public synchronized void put( int index, Object object ){
put( index, asInt( object ) );
}
/**
* Set the int at the specified index to a particular value.
* @param index The index.
* @param object The value.
* @exception java.lang.IndexOutOfBoundsException If the index is invalid.
*/
public synchronized void put( int index, int object ){
IntArray.checkIndex( index, length );
storage[ index ] = object;
}
/**
* Remove all of my elements.
*/
public synchronized void clear(){
storage = new int[ IntArray.DEFAULT_SIZE ];
length = 0;
}
/**
* Remove the element at a particular index.
* @param index The index of the element to remove.
* @return The object removed.
* @exception java.lang.IndexOutOfBoundsException If the index is invalid.
*/
public synchronized Object remove( int index ){
IntArray.checkIndex( index, length );
Object retval = new Integer( storage[ index ] );
System.arraycopy( storage, index + 1, storage, index, length - index - 1 );
storage[ --length ] = defaultValue;
return retval;
}
/**
* Remove the elements within a range of indices.
* @param first The index of the first element to remove.
* @param last The index of the last element to remove.
* @return The number of elements removed.
* @exception java.lang.IndexOutOfBoundsException If either index is invalid.
*/
public synchronized int remove( int first, int last ){
if ( last < first )
return 0;
IntArray.checkRange( first, last, length );
int amount = last - first + 1;
System.arraycopy( storage, last + 1, storage, first, length - last - 1 );
for ( int i = length - amount; i < length; i++ )
storage[ i ] = defaultValue;
length -= amount;
return amount;
}
/**
* Remove and return my last element.
* @exception com.objectspace.jgl.RuntimeException If the IntBuffer is empty.
*/
public synchronized Object popBack(){
if ( length == 0 )
throw new RuntimeException( "IntBuffer is empty" );
Object r = new Integer( storage[ --length ] );
storage[ length ] = defaultValue;
return r;
}
/**
* Add an object after my last element. Returns null.
* This function is a synonym for pushBack().
* @param object The object to add.
*/
public synchronized Object add( Object object ){
add( asInt( object ) );
return null;
}
/**
* Add a int after my last element. Returns null.
* This function is a synonym for pushBack().
* @param object The object to add.
*/
public synchronized void add( int object ){
if ( length == storage.length )
{
int[] tmp = getNextStorage( 1 );
copyTo( tmp );
storage = tmp;
}
storage[ length++ ] = object;
}
/**
* Add an object after my last element.
* @param object to add.
*/
public void pushBack( Object object ){
add( asInt( object ) );
}
/**
* Add a int after my last element.
* @param object to add.
*/
public void pushBack( int object ){
add( object );
}
/**
* Insert an object at a particular position and return an iterator
* positioned at the new element.
* @param pos An iterator positioned at the element that the object will be inserted immediately before.
* @param object The object to insert.
*/
public IntIterator insert( IntIterator pos, Object object ){
return insert( pos, asInt( object ) );
}
/**
* Insert a value at a particular position and return an iterator
* positioned at the new element.
* @param pos An iterator positioned at the element that the object will be inserted immediately before.
* @param object The object to insert.
*/
public IntIterator insert( IntIterator pos, int object ){
insert( pos.index, object );
return new IntIterator( this, pos.index );
}
/**
* Insert an object at a particular index.
* @param index The index of the element that the object will be inserted immediately before.
* @param object The object to insert.
* @exception java.lang.IndexOutOfBoundsException If the index is invalid.
*/
public void insert( int index, Object object ){
insert( index, asInt( object ) );
}
/**
* Insert a value at a particular index.
* @param index The index of the element that the object will be inserted immediately before.
* @param object The value to insert.
* @exception java.lang.IndexOutOfBoundsException If the index is invalid.
*/
public synchronized void insert( int index, int object ){
IntArray.checkIndex( index, length + 1 );
if ( length != storage.length ) {
if ( index != length )
System.arraycopy( storage, index, storage, index + 1, length - index );
}
else{
int[] tmp = getNextStorage( 1 );
System.arraycopy( storage, 0, tmp, 0, index );
System.arraycopy( storage, index, tmp, index + 1, length - index );
storage = tmp;
}
storage[ index ] = object;
++length;
}
/**
* Insert multiple objects at a particular position.
* @param pos An iterator positioned at the element before which the
* elements will be inserted.
* @param n The number of objects to insert.
* @param object The object to insert.
*/
public void insert( IntIterator pos, int n, Object object ){
insert( pos, n, asInt( object ) );
}
/**
* Insert multiple values at a particular position.
* @param pos An iterator positioned at the element before which the
* elements will be inserted.
* @param n The number of values to insert.
* @param object The value to insert.
*/
public void insert( IntIterator pos, int n, int object ){
insert( pos.index, n, object );
}
/**
* Insert multiple objects at a particular index.
* @param index The index of the element immediately before the values will
* be inserted.
* @param object The object to insert.
* @exception java.lang.IndexOutOfBoundsException If the index is invalid.
* @exception java.lang.IllegalArgumentException If the number of values
* is negative.
*/
public void insert( int index, int n, Object object ){
insert( index, n, asInt( object ) );
}
/**
* Insert multiple objects at a particular index.
* @param index The index of the element immediately before the values will
* be inserted.
* @param object The value to insert.
* @exception java.lang.IndexOutOfBoundsException If the index is invalid.
* @exception java.lang.IllegalArgumentException If the number of values
* is negative.
*/
public synchronized void insert( int index, int n, int object ){
if ( n < 0 )
throw new IllegalArgumentException( "Attempt to insert a negative number of objects." );
if ( n == 0 )
return;
IntArray.checkIndex( index, length + 1 );
if ( storage.length - length >= n ){
System.arraycopy( storage, index, storage, index + n, length - index );
}
else{
int[] tmp = getNextStorage( n );
System.arraycopy( storage, 0, tmp, 0, index );
System.arraycopy( storage, index, tmp, index + n, length - index );
storage = tmp;
}
for ( int i = index; i < index + n; i++ )
storage[ i ] = object;
length += n;
}
/**
* Insert a sequence of objects at a particular location.
* @param pos The location of the element that the objects will be inserted immediately before.
* @param first An iterator positioned at the first element to insert.
* @param last An iterator positioned immediately after the last element to insert.
*/
public void insert( IntIterator pos, ForwardIterator first, ForwardIterator last ){
insert( pos.index, first, last );
}
/**
* Insert a sequence of objects at a particular index.
* @param index The index of the element that the objects will be inserted immediately before.
* @param first An iterator positioned at the first element to insert.
* @param last An iterator positioned immediately after the last element to insert.
*/
public synchronized void insert( int index, ForwardIterator first, ForwardIterator last ){
int n = first.distance( last );
if ( n == 0 )
return;
ForwardIterator firstx = (ForwardIterator)first.clone();
if ( storage.length - length >= n ){
System.arraycopy( storage, index, storage, index + n, length - index );
}
else{
int[] tmp = getNextStorage( n );
System.arraycopy( storage, 0, tmp, 0, index );
System.arraycopy( storage, index, tmp, index + n, length - index );
storage = tmp;
}
length += n;
for ( int i = index; i < index + n; i++ )
put( i, firstx.nextElement() );
}
/**
* Swap my contents with another IntBuffer.
* @param array The IntBuffer that I will swap my contents with.
*/
public synchronized void swap( IntBuffer array ){
synchronized( array ){
int oldLength = length;
int oldStorage[] = storage;
length = array.length;
storage = array.storage;
array.length = oldLength;
array.storage = oldStorage;
}
}
/**
* Return an Enumeration of my components.
*/
@SuppressWarnings("rawtypes")
public Enumeration elements(){
return new IntIterator( this, 0 );
}
/**
* Return an iterator positioned at my first item.
*/
public synchronized IntIterator begin(){
return new IntIterator( this, 0 );
}
/**
* Return an iterator positioned immediately after my last item.
*/
public synchronized IntIterator end(){
return new IntIterator( this, length );
}
/**
* If my storage space is currently larger than my total number of elements,
* reallocate the elements into a storage space that is exactly the right size.
*/
public synchronized void trimToSize(){
if ( length < storage.length )
storage = get();
}
/**
* Pre-allocate enough space to hold a specified number of elements.
* This operation does not change the value returned by size().
* @param n The amount of space to pre-allocate.
* @exception java.lang.IllegalArgumentException If the specified size is negative.
*/
public synchronized void ensureCapacity( int n ){
if ( n < 0 )
throw new IllegalArgumentException( "Attempt to reserve a negative size." );
if ( storage.length < n ){
int[] tmp = new int[ n ];
if ( length > 0 )
System.arraycopy( storage, 0, tmp, 0, length );
storage = tmp;
}
}
/**
* Remove and return my first element.
* @exception RuntimeException If the IntBuffer is empty.
*/
public synchronized Object popFront(){
if ( length == 0 )
throw new RuntimeException( "IntBuffer is empty" );
Object result = new Integer( storage[ 0 ] );
remove( 0 );
return result;
}
/**
* Insert an object in front of my first element.
* @param object The object to insert.
*/
public void pushFront( Object object ){
insert( 0, object );
}
/**
* Insert a value in front of my first element.
* @param object The object to insert.
*/
public void pushFront( int object ){
insert( 0, object );
}
/**
* Remove all elements that match a particular object and return the number of
* objects that were removed.
* @param object The object to remove.
*/
public int remove( Object object ){
return remove( object, length );
}
/**
* Remove at most a given number of elements that match a particular
* object and return the number of
* objects that were removed.
* @param object The object to remove.
* @param count The maximum number of objects to remove.
*/
public synchronized int remove( Object object, int count ){
int tmp = asInt( object );
int removed = 0;
while ( count > 0 ){
int i = indexOf( tmp );
if ( i < 0 )
break;
--count;
++removed;
remove( i );
}
return removed;
}
/**
* Replace all elements that match a particular object with a new value and return
* the number of objects that were replaced.
* @param oldValue The object to be replaced.
* @param newValue The value to substitute.
*/
public int replace( Object oldValue, Object newValue ){
return replace( asInt( oldValue ), asInt( newValue ) );
}
/**
* Replace all ints that match a particular object with a new value and return
* the number of objects that were replaced.
* @param oldValue The int to be replaced.
* @param newValue The value to substitute.
*/
public int replace( int oldValue, int newValue ){
return replace( 0, length - 1, oldValue, newValue );
}
/**
* Replace all elements within a range of indices that match a particular object
* with a new value and return the number of objects that were replaced.
* @param first The index of the first object to be considered.
* @param last The index just past the last object to be considered.
* @param oldValue The object to be replaced.
* @param newValue The value to substitute.
* @exception java.lang.IndexOutOfBoundsException If either index is invalid.
*/
public int replace( int first, int last, Object oldValue, Object newValue ){
return replace( first, last, asInt( oldValue ), asInt( newValue ) );
}
/**
* Replace all values within a range of indices that match a particular int
* with a new value and return the number of objects that were replaced.
* @param first The index of the first element to be considered.
* @param last The index just past the last element to be considered.
* @param oldValue The int to be replaced.
* @param newValue The value to substitute.
* @exception java.lang.IndexOutOfBoundsException If either index is invalid.
*/
public synchronized int replace( int first, int last, int oldValue, int newValue ){
IntArray.checkRange( first, last, length );
int n = 0;
while ( first < last ){
if ( storage[ first ] == oldValue ){
storage[ first ] = newValue;
++n;
}
++first;
}
return n;
}
/**
* Return the number of objects that match a particular value.
* @param object The object to count.
*/
public int count( Object object ){
return count( asInt( object ) );
}
/**
* Return the number of objects that equal a particular value.
* @param object The int to count.
*/
public int count( int object ){
return count( 0, length - 1, object );
}
/**
* Return the number of objects within a particular range of indices
* that match a particular value.
* @param first The index of the first object to consider.
* @param last The index of the last object to consider.
* @exception java.lang.IndexOutOfBoundsException If either index is
* invalid.
*/
public int count( int first, int last, Object object ){
return count( first, last, asInt( object ) );
}
/**
* Return the number of objects within a particular range of indices
* that match a particular int.
* @param first The index of the first object to consider.
* @param last The index of the last object to consider.
* @exception java.lang.IndexOutOfBoundsException If either index is
* invalid.
*/
public synchronized int count( int first, int last, int object ){
IntArray.checkRange( first, last, length );
int n = 0;
while ( first < last )
{
if ( storage[ first ] == object )
++n;
++first;
}
return n;
}
/**
* Return the index of the first object that matches a particular value, or
* -1 if the object is not found. Uses .equals() to find a match
* @param object The object to find.
* @exception java.lang.ClassCastException if objects are not Boolean
*/
public int indexOf( Object object ){
return indexOf( asInt( object ) );
}
/**
* Return the index of the first int that matches a particular value,
* or -1 if the value is not found.
* @param object The int to find.
*/
public int indexOf( int object ){
return indexOf( 0, length - 1, object );
}
/**
* Return the index of the first object within a range of indices that
* match a particular object, or -1 if the object is not found.
* @param first The index of the first object to consider.
* @param last The index of the last object to consider.
* @param object The object to find.
* @exception java.lang.IndexOutOfBoundsException If either index is
* invalid.
*/
public int indexOf( int first, int last, Object object ){
return indexOf( first, last, asInt( object ) );
}
/**
* Return the index of the first int within a range of indices that
* match a particular value, or -1 if the int is not found.
* @param first The index of the first value to consider.
* @param last The index of the last value to consider.
* @param object The value to find.
* @exception java.lang.IndexOutOfBoundsException If either index is
* invalid.
*/
public synchronized int indexOf( int first, int last, int object ){
if ( last < first )
return -1;
IntArray.checkRange( first, last, length );
for ( ; first < last; ++first )
if ( storage[ first ] == object )
return first;
return -1;
}
/**
* Sets the size of the IntBuffer. if the size shrinks, the extra elements (at
* the end of the array) are lost; if the size increases, the new elements
* are set to null.
* @param newSize The new size of the IntBuffer.
*/
public synchronized void setSize( int newSize ){
if ( newSize < 0 )
throw new IllegalArgumentException( "Attempt to become a negative size." );
if ( length > newSize )
remove( newSize, length - 1 );
else if ( length < newSize )
insert( length, newSize - length, defaultValue );
}
/**
* Return true if I contain a particular object using .equals()
* @param object The object in question.
*/
public boolean contains( Object object ){
return contains( asInt( object ) );
}
/**
* Return true if I contain a particular int.
*/
public boolean contains( int object ){
return indexOf( object ) != -1;
}
/**
* Ensure that there is enough space for at least n new objects.
*/
private int[] getNextStorage( int n ){
int newSize = Math.max( IntArray.getNextSize( length ), length + n );
int[] tmp = new int[ newSize ];
return tmp;
}
static int asInt( Object object ){
return ( (Number)object ).intValue();
}
final static int orderedHash( ForwardIterator iter, int length ) {
int h = 0;
int position = 0;
int skip = 1;
if ( length >= HASH_SIZE ){
skip = length / HASH_SIZE;
// insure that first will always exactly reach last
iter.advance( length % HASH_SIZE );
}
while ( iter.hasMoreElements() ){
if ( iter.get() != null )
h ^= iter.get().hashCode() / ( ( position % HASH_SIZE ) + 1 );
++position;
iter.advance( skip );
}
return h;
}
public static InputIterator find( InputIterator first, InputIterator last, Object object ){
InputIterator firstx = (InputIterator)first.clone();
while ( !firstx.equals( last ) && !( firstx.get().equals( object ) ) )
firstx.advance();
return firstx;
}
}