// Copyright(c) 1996,1997 ObjectSpace, Inc.
// Portions Copyright(c) 1995, 1996 Hewlett-Packard Company.

package COM.objectspace.jgl;

import java.io.Serializable;

/**
 * An LongIterator is a random access iterator that allows you to iterate through
 * an array of longs.
 * <p>
 * @see COM.objectspace.jgl.RandomAccessIterator
 * @version 2.0.2
 * @author ObjectSpace, Inc.
 */

public final class LongIterator implements RandomAccessIterator, Serializable
  {
  LongArray myLongArray;
  long myArray[];
  int myIndex;

  /**
   * Return an iterator positioned at the first element of a particular array.
   * @param array The array whose first element I will be positioned at.
   */
  public static LongIterator begin( long array[] )
    {
    return new LongIterator( array, 0, new LongArray( array ) );
    }

  /**
   * Return an iterator positioned at the first element of a particular array.
   * @param array The array whose first element I will be positioned at.
   * @param longArray The container the iterator is associated with.
   */
  public static LongIterator begin( long array[], LongArray longArray )
    {
    return new LongIterator( array, 0, longArray );
    }

  /**
   * Return an iterator positioned immediately after the last element of a particular array.
   * @param array The array whose last element I will be positioned after.
   */
  public static LongIterator end( long array[] )
    {
    return new LongIterator( array, array.length, new LongArray( array ) );
    }

  /**
   * Return an iterator positioned immediately after the last element of a particular array.
   * @param array The array whose last element I will be positioned after.
   * @param longArray The container the iterator is associated with.
   */
  public static LongIterator end( long array[], LongArray longArray )
    {
    return new LongIterator( array, array.length, longArray );
    }

  /**
   * Construct myself to be an iterator with no associated data structure or position.
   */
  public LongIterator()
    {
    }

  /**
   * Construct myself to be a copy of an existing iterator.
   * @param iterator The iterator to copy.
   */
  public LongIterator( LongIterator iterator )
    {
    myLongArray = iterator.myLongArray;
    myArray = iterator.myArray;
    myIndex = iterator.myIndex;
    }

  /**
   * Construct myself to be an iterator positioned at the first element of a specified
   * array.
   * @param array The array whose first element I will be positioned at.
   */
  public LongIterator( long array[] )
    {
    this( array, 0, new LongArray( array ) );
    }

  /**
   * Construct myself to be an iterator positioned at the first element of a specified
   * array.
   * @param array The array whose first element I will be positioned at.
   * @param longArray The container the iterator is associated with.
   */
  public LongIterator( long array[], LongArray longArray )
    {
    this( array, 0, longArray );
    }

  /**
   * Construct myself to be positioned at a particular index of a specific array.
   * @param array My associated array.
   * @param index My associated index.
   */
  public LongIterator( long array[], int index )
    {
    this( array, index, new LongArray( array ) );
    }

  /**
   * Construct myself to be positioned at a particular index of a specific array.
   * @param array My associated array.
   * @param index My associated index.
   * @param longArray The container the iterator is associated with.
   */
  public LongIterator( long array[], int index, LongArray longArray )
    {
    myLongArray = longArray;
    myArray = array;
    myIndex = index;
    }

  /**
   * Return a clone of myself.
   */
  public Object clone()
    {
    return new LongIterator( this );
    }

  /**
   * Return my current index.
   */
  public int index()
    {
    return myIndex;
    }

  /**
   * Return true if a specified object is the same kind of iterator as me
   * and is positioned at the same element.
   * @param object Any object.
   */
  public boolean equals( Object object )
    {
    return object instanceof LongIterator && equals( (LongIterator) object );
    }

  /**
   * Return true if iterator is positioned at the same element as me.
   * @param iterator The iterator to compare myself against.
   */
  public boolean equals( LongIterator iterator )
    {
    return iterator.myIndex == myIndex && iterator.myArray == myArray;
    }

  /**
   * Return true if I'm before a specified iterator.
   * @param iterator The iterator to compare myself against.
   */
  public boolean less( RandomAccessIterator iterator )
    {
    return myIndex < ((LongIterator) iterator).myIndex;
    }

  /**
   * Return the object that is a specified distance from my current position.
   * @param offset The offset from my current position.
   */
  public Object get( int offset )
    {
    return new Long( myArray[ myIndex + offset ] );
    }

  /**
   * Write an object at a specified distance from my current position.
   * @param offset The offset from my current position.
   * @param object The object to write.
   */
  public void put( int offset, Object object )
    {
    myArray[ myIndex + offset ] = ((Long) object).longValue();
    }

  /**
   * Return true if I'm positioned at the first item of my input stream.
   */
  public boolean atBegin()
    {
    return myIndex == 0;
    }

  /**
   * Return true if I'm positioned after the last item in my input stream.
   */
  public boolean atEnd()
    {
    return myIndex == myArray.length;
    }

  /**
   * Return true if there are more elements in my input stream.
   */
  public boolean hasMoreElements()
    {
    return myIndex < myArray.length;
    }

  /**
   * Advance by one.
   */
  public void advance()
    {
    myIndex++;
    }

  /**
   * Advance by a specified amount.
   * @param n The amount to advance.
   */
  public void advance( int n )
    {
    myIndex += n;
    }

  /**
   * Retreat by one.
   */
  public void retreat()
    {
    myIndex--;
    }

  /**
   * Retreat by a specified amount.
   * @param n The amount to retreat.
   */
  public void retreat( int n )
    {
    myIndex -= n;
    }

  /**
   * Return the next element in my input stream.
   */
  public Object nextElement()
    {
    return new Long( myArray[ myIndex++ ] );
    }

  /**
   * Return the object at my current position.
   */
  public Object get()
    {
    return new Long( myArray[ myIndex ] );
    }

  /**
   * Set the object at my current position to a specified value.
   * @param object The object to be written at my current position.
   */
  public void put( Object object )
    {
    myArray[ myIndex ] = ((Long) object).longValue();
    }

  /**
   * Return the distance from myself to another iterator.
   * I should be before the specified iterator.
   * @param iterator The iterator to compare myself against.
   */
  public int distance( ForwardIterator iterator )
    {
    return ((LongIterator) iterator).myIndex - myIndex;
    }

  /**
   * Return null for my associated Container since none needs to exist.
   */
  public Container getContainer()
    {
    return myLongArray;
    }
  }
