//
// $Id: Vector.h,v 1.40 2005/07/12 19:15:37 will_mason Exp $
//
// vi: set ft=objc:

/*
 * ObjectiveLib - a library of containers and algorithms for Objective-C
 *
 * Copyright (c) 2004
 * Will Mason
 *
 * Portions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Copyright (c) 1996,1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Copyright (c) 1997
 * Moscow Center for SPARC Technology
 *
 * Copyright (c) 1999 
 * Boris Fomitchev
 *
 * 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 2.1 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * You may contact the author at will_mason@users.sourceforge.net.
 */

#if !defined(VECTOR_OL_GUARD)
#define VECTOR_OL_GUARD

#import <ObjectiveLib/Iterator.h>
#if defined(OL_HAVE_INTTYPES_H)
#import <inttypes.h>
#endif

/**
 * @class OLVector Vector.h ObjectiveLib/Vector.h
 *
 * A growable array of objects. A vector is essentially an array of objects that
 * provides random access to its elements and is optimized for insertion and
 * removable at the end of the sequence. The capacity of the vector will grow as
 * needed, so memory management is entirely automatic. It also serves as a suitable
 * container for OLBackInsertIterator and OLInsertIterator.
 *
 * @sa OLArrayIterator, OLBoolVector
 *
 * @ingroup Containers
 */
@interface OLVector : NSObject
    <OLCopying, OLBackInserter, OLInserter, NSCoding>
{
@protected
    /**
     * The memory allocator in use
     */
    OLAllocator*    allocator;

    /**
     * The beginning of the sequence
     */
    id*             begin;

    /**
     * The end of the sequence
     */
    id*             end;

    /**
     * The end of storage capacity
     */
    id*             endOfCapacity;
}

/**
 * Create and return a new vector. The default memory allocator is used to allocate the
 * vector. If both the platform and allocator support autorelease, then the new vector
 * will be autoreleased before being returned.
 *
 * @return a new vector
 */
+ (id) vector;

/**
 * Create and return a new vector. The default memory allocator is used to allocate the
 * vector. If both the platform and allocator support autorelease, then the new vector
 * will be autoreleased before being returned. The vector is initialized with the
 * contents of the range <tt>[first, last)</tt>.
 *
 * @param first the first in the range of elements to insert
 * @param last one beyond the last in the range of elements to insert
 * @return a new vector
 */
+ (id) vectorFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Create and return a new vector. The default memory allocator is used to allocate the
 * vector. If both the platform and allocator support autorelease, then the new vector
 * will be autoreleased before being returned. The initial capacity will be no less
 * than @a capacity.
 *
 * @param capacity the minimum capacity of the new vector
 * @return a new vector
 */
+ (id) vectorWithCapacity: (unsigned)capacity;

/**
 * Create and return a new vector. The default memory allocator is used to allocate the
 * vector. If both the platform and allocator support autorelease, then the new vector
 * will be autoreleased before being returned. The new vector will have a size of
 * @a size, and each element will be set to @a value.
 *
 * @param size the size of the new vector
 * @param value the value with which to fill the new vector
 * @return a new vector
 */
+ (id) vectorWithSize: (unsigned)size filledWith: (id)value;

/**
 * Create and return a new vector. The default memory allocator is used to allocate the
 * vector. If both the platform and allocator support autorelease, then the new vector
 * will be autoreleased before being returned. The vector is initialized with the
 * contents of @a right.
 *
 * @param right the vector that should be copied into the new one
 * @return a new vector
 */
+ (id) vectorWithVector: (OLVector*)right;

/**
 * @name Initializers and Deallocators
 */
/* @{ */
/**
 * Initialize the vector. The default memory allocator is used, and the capacity
 * is initially zero.
 *
 * @return a reference to this vector
 */
- (id) init;

/**
 * Initialize the vector. The vector uses the default memory allocator and inserts
 * all elements referred to in the range <tt>[first, last)</tt>.
 *
 * @param first the first in the range of elements to insert
 * @param last one beyond the last in the range of elements to insert
 * @return a reference to this vector
 */
- (id) initFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Initialize the vector. The vector uses the given memory allocator and inserts
 * all elements referred to in the range <tt>[first, last)</tt>.
 *
 * @param first the first in the range of elements to insert
 * @param last one beyond the last in the range of elements to insert
 * @param alloc the memory allocator that the vector should use
 * @return a reference to this vector
 */
- (id) initFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last allocator: (OLAllocator*)alloc;

/**
 * Initialize the vector. The given memory allocator is used, and the initial capacity
 * is zero.
 *
 * @param alloc the memory allocator that the vector should use
 * @return a reference to this vector
 */
- (id) initWithAllocator: (OLAllocator*)alloc;

/**
 * Initialize the vector. The initial capacity is set to @a capacity, and the default
 * memory allocator is used.
 *
 * @param capacity the initial capacity of the vector
 * @return a reference to this vector
 */
- (id) initWithCapacity: (unsigned)capacity;

/**
 * Initialize the vector. This initializer creates a new vector
 * from an archive and returns it.
 *
 * @post The vector returned will be identical to the vector
 * saved to the archive using the #encodeWithCoder: message.
 *
 * @param decoder the coder which will decode the archived vector
 * @return a reference to this vector
 */
- (id) initWithCoder: (NSCoder*)decoder;

/**
 * Initialize the vector. The initial size of the vector will be @a size, and @a value
 * will be copied into the vector @a size times. The default memory allocator is used.
 *
 * @param size the number of elements to insert
 * @param value the object to be copied
 * @return a reference to this vector
 */
- (id) initWithSize: (unsigned)size filledWith: (id)value;

/**
 * Initialize the vector. The initial size of the vector will be @a size, and @a value
 * will be copied into the vector @a size times. The given memory allocator is used.
 *
 * @param size the number of elements to insert
 * @param value the object to be copied
 * @param alloc the memory allocator that the vector should use
 * @return a reference to this vector
 */
- (id) initWithSize: (unsigned)size filledWith: (id)value allocator: (OLAllocator*)alloc;

/**
 * Initialize the vector. The allocator of @a vector and all of its elements are copied
 * into the current vector.
 *
 * @param vector the vector to copy
 * @return a reference to this vector
 */
- (id) initWithVector: (OLVector*)vector;

/**
 * Finalize the vector and deallocate any allocated memory.
 */
- (void) dealloc;
/* @} */

/**
 * Assign objects to the vector. The current contents of the vector are removed,
 * and the vector is filled with @a count elements of @a value.
 *
 * @param count the number of elements to assign
 * @param value the object to be copied into the vector
 */
- (void) assign: (unsigned)count filledWith: (id)value;

/**
 * Assign @a object to the position at @a index. The object currently in possession
 * of the position at @a index is removed and replaced with @a object.
 *
 * @note The range of the vector is not checked prior to performing this operation.
 * Using values of @a index that do not lie within the vector's range will produce
 * undefined results.
 *
 * @param index the index to which to assign
 * @param object the object to put at @a index
 */
- (void) assignAt: (unsigned)index value: (id)object;

/**
 * Assign a range of objects to the vector. The current contents of the vector are
 * removed, and all elements in the range <tt>[first, last)</tt> are inserted
 * into the vector.
 *
 * @param first the first in the range of objects to assign
 * @param last one beyond the last in the range of objects to assign
 */
- (void) assignFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Return the object at @a index. A reference to the object is returned, though
 * the vector still owns the object in question.
 *
 * @note The range of the vector is not checked prior to performing this operation.
 * Using values of @a index that do not lie within the vector's range will produce
 * undefined results.
 *
 * @param index the index of the object to look up
 * @return a reference to the object at @a index
 */
- (id) at: (unsigned)index;

/**
 * Return the last object in the vector. A reference to the object is returned, though
 * the vector still owns the object in question.
 *
 * @note The results of this message are undefined if the vector is empty.
 *
 * @return the last object
 */
- (id) back;

/**
 * Return an iterator pointing to the beginning of the sequence. If the platform and
 * the allocator both support autorelease, then the iterator will be scheduled for
 * autorelease before being returned.
 *
 * @return an iterator pointing to the first element
 */
- (OLArrayIterator*) begin;

/**
 * Return the current capacity of the vector. The capacity represents the maximum number
 * of elements that the vector can hold before allocation of new memory will be required.
 *
 * @return the capacity
 */
- (unsigned) capacity;

/**
 * Remove all elements.
 */
- (void) clear;
- (id) copyWithAllocator: (OLAllocator*)alloc;
- (id) copyWithZone: (NSZone*)zone;

/**
 * Test whether the vector is empty.
 *
 * @return YES if the vector is empty, NO otherwise
 */
- (BOOL) empty;

/**
 * Encode the vector. The vector is saved to an archive using @a encoder. The vector
 * will be retrieved from the archive using the initializer #initWithCoder:.
 *
 * @param encoder the coder which will save the bit set to the archive
 */
- (void) encodeWithCoder: (NSCoder*)encoder;

/**
 * Return an iterator pointing to one position beyond the end of the sequence. If the platform and
 * the allocator both support autorelease, then the iterator will be scheduled for
 * autorelease before being returned.
 *
 * @return an iterator pointing to one position beyond the last element
 */
- (OLArrayIterator*) end;

/**
 * Remove the element designated by @a where. If the platform and
 * the allocator both support autorelease, then the iterator returned will be scheduled for
 * autorelease before being returned.
 *
 * @pre @a where must point to an element in this vector.
 *
 * @param where an iterator designating the element to remove
 * @return an iterator indicating the next element in the sequence remaining after @a where
 */
- (OLArrayIterator*) erase: (OLArrayIterator*)where;

/**
 * Remove a range of elements. All elements in the range <tt>[first, last)</tt> will
 * be removed from the vector. If the platform and allocator both support autorelease,
 * then the iterator returned will be scheduled for autorelease before being returned.
 *
 * @pre @a first and @a last must refer to elements in this vector.
 *
 * @param first the first in the range of elements to remove
 * @param last one position beyond the last in the range of elements to remove
 * @return an iterator indicating the next element in the sequence remaining after
 * removal of the range
 */
- (OLArrayIterator*) eraseFrom: (OLArrayIterator*)first to: (OLArrayIterator*)last;

/**
 * Return the first object in the vector. A reference to the object is returned, though
 * the vector still owns the object in question.
 *
 * @note The results of this message are undefined if the vector is empty.
 *
 * @return the first object
 */
- (id) front;

/**
 * Return the memory allocator being used.
 *
 * @return the memory allocator that this vector uses
 */
- (OLAllocator*) allocator;

/**
 * Insert a number of objects into the vector. @a num objects of @a value will be inserted
 * just before the position referred to by @a where. Thus, it is valid to use an iterator returned
 * by #end as an argument.
 *
 * @pre @a where must refer to a position in this vector
 *
 * @param where the position at which to insert the objects
 * @param num the number of objects to insert
 * @param value the object to be copied into the vector
 */
- (void) insertAt: (OLArrayIterator*)where count: (unsigned)num filledWith: (id)value;

/**
 * Insert a range of objects into the vector. All objects in the range <tt>[first, last)</tt>
 * are inserted just before the position referred to by @a where. Thus, it is valid to
 * use an iterator returned by #end as an argument.
 *
 * @param where the position at which to insert the objects
 * @param first the first in the range of objects to insert
 * @param last one position beyond the last in the range of objects to insert
 */
- (void) insertAt: (OLArrayIterator*)where from: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Insert an object into the vector. The @a object will be inserted just before the
 * position referred to by @a where. Thus, it is valid to use an iterator returned
 * by #end as an argument. If the platform and allocator both support autorelease,
 * then the iterator returned will be scheduled for autorelease before being returned.
 *
 * @pre @a where must refer to a position in this vector.
 *
 * @param where the position at which to insert @a object
 * @param object the object to insert
 * @return an iterator pointing to the newly inserted object
 */
- (OLArrayIterator*) insertAt: (OLArrayIterator*)where value: (id)object;

/**
 * Return whether this vector is equal to another one. Two vectors are considered equal
 * if they both contain the same number of objects that all return YES to the message
 * @c isEqual: and they are in the same order. They do not have to have the same memory
 * allocator in order to be considered equal.
 *
 * @param object the object to test
 * @return YES if @a object is equal to this vector
 */
- (BOOL) isEqual: (id)object;

/**
 * Return the maxiumum number of objects that can be stored in a vector. This limit is
 * theoretical, meaning that there is no guarantee that you can insert this many
 * objects into any given vector. The memory conditions of the run-time system play an
 * important role.
 *
 * @return the maximum number of objects for a vector
 */
- (unsigned) maxSize;

/**
 * Remove the last element in the vector.
 *
 * @note If there are no elements in the vector, then the behavior of this message
 * is undefined.
 */
- (void) popBack;

/**
 * Insert @a object at the end of the sequence.
 *
 * @param object the object to insert
 */
- (void) pushBack: (id)object;

/**
 * Return a reverse iterator pointing to the end of the sequence. Advancing the returned
 * iterator will move backwards through the sequence to the point indicated by the
 * iterator returned by #rend. If the platform and the allocator both support autorelease,
 * then the iterator will be scheduled for autorelease before being returned.
 *
 * @return a reverse iterator for the end of the sequence
 */
- (OLReverseRandomIterator*) rbegin;

/**
 * Return a reverse iterator pointing to the beginning of the sequence. This iterator
 * indicates one position beyond the last position that may be referenced by a
 * reverse iterator. If the platform and the allocator both support autorelease,
 * then the iterator will be scheduled for autorelease before being returned.
 *
 * @return a reverse iterator for the beginning of the sequence
 */
- (OLReverseRandomIterator*) rend;

/**
 * Reserve storage. If @a count is less than the current capacity of the vector, then
 * this message does nothing. If @a count is greater than the current capacity, then
 * <tt>count - capacity</tt> elements of storage will be added to the container. This
 * may invalidate iterators that are currently active. This operation will not affect
 * the size, or number of elements actually stored, only the capacity.
 *
 * @param count the total number of desired spaces in the vector
 */
- (void) reserve: (unsigned)count;

/**
 * Resize the vector to @a newsize. If @a newsize is smaller than the current #size, then
 * the sequence will be truncated. If @a newsize is larger than the current #size,
 * then @a value will be inserted at the end of the vector as many times as necessary
 * to fill the new size.
 *
 * @param newsize the new size of the vector
 * @param value the value with which to fill new elements, if necessary
 */
- (void) resize: (unsigned)newsize filledWith: (id)value;

/**
 * Return the number of elements in the vector.
 *
 * @return the number of elements
 */
- (unsigned) size;

/**
 * Swap this vector with another one. All elements in @a right will be placed into
 * this vector, and all elements in this vector will be placed in @a right. Unless the
 * allocators of the two vectors are different, the implementation of this message
 * results in a very fast swap.
 *
 * @param right the vector with which to swap this one
 */
- (void) swap: (OLVector*)right;

@end

/**
 * @struct OLBitIteratorBase Vector.h ObjectiveLib/Vector.h
 *
 * A data structure used by OLBitIterator. This structure holds the
 * data necessary to implement the class OLBitIterator.
 *
 * @note This structure is for internal use only and is not intended for
 * public consumption. However, if you find it useful, don't be shy.
 */
typedef struct
{
    /**
     * The word that holds the bit
     */
    uint32_t*   chunk;

    /**
     * The offset of the bit in its word
     */
    uint8_t     offset;
} OLBitIteratorBase;

/**
 * @class OLBitIterator Vector.h ObjectiveLib/Vector.h
 *
 * An iterator that can traverse an array of bits. This is a random
 * access iterator that is used to traverse elements in a boolean
 * vector.
 *
 * @sa OLBoolVector
 *
 * @ingroup Iterators
 */
@interface OLBitIterator : OLRandomAccessIterator
{
@protected
    /**
     * The base structure for bit iterators
     */
    OLBitIteratorBase   base;
}

- (id) advance;
- (id) advanceBy: (int)count;

/**
 * Assign the value of @a object to the bit to which this iterator refers.
 * The bit at the current position will be replaced with a 1 if the message
 * @c boolValue returns YES, or 0 otherwise.
 *
 * @pre @a object must respond to the message @c boolValue.
 *
 * @param object the object to assign
 * @return a reference to this iterator
 */
- (id) assign: (id)object;
- (id) copyWithAllocator: (OLAllocator*)alloc;
- (id) copyWithZone: (NSZone*)zone;

/**
 * Dereference the iterator. Return an object that responds to the message
 * @c boolValue. The underlying objects are shared by all bit iterators, so
 * there is no significant memory allocation that occurs with the use of
 * bit iterators.
 *
 * @return a reference to an object that responds to @c boolValue
 */
- (id) dereference;
- (int) difference: (OLRandomAccessIterator*)other;
- (BOOL) isEqual: (id)object;
- (id) reverse;

@end

/**
 * @class OLBoolVector Vector.h ObjectiveLib/Vector.h
 *
 * A type of @ref OLVector "vector" that is optimized to store an
 * array of bits. The underlying array serves as the data structure
 * for a collection of YES or NO values. The interface is exactly the
 * same as the interface of OLVector, but the data structures used
 * are designed only to store bits.
 *
 * @sa OLBitIterator, OLVector
 *
 * @ingroup Containers
 */
@interface OLBoolVector : NSObject <OLCopying, NSCoding>
{
@protected
    /**
     * The beginning of the sequence
     */
    OLBitIteratorBase   begin;

    /**
     * The end of the sequence
     */
    OLBitIteratorBase   end;

    /**
     * The end of allocated storage
     */
    uint32_t*           endOfCapacity;

    /**
     * The memory allocator in use
     */
    OLAllocator*        allocator;
}

/**
 * Create and return a new vector. The default memory allocator is used to allocate the
 * vector. If both the platform and allocator support autorelease, then the new vector
 * will be autoreleased before being returned.
 *
 * @return a new vector
 */
+ (id) boolVector;

/**
 * Create and return a new vector. The default memory allocator is used to allocate the
 * vector. If both the platform and allocator support autorelease, then the new vector
 * will be autoreleased before being returned. The vector is initialized with the
 * contents of the range <tt>[first, last)</tt>.
 *
 * @pre The elements in the range <tt>[first, last)</tt> must all respond to the
 * message @c boolValue.
 *
 * @param first the first in the range of elements to insert
 * @param last one beyond the last in the range of elements to insert
 * @return a new vector
 */
+ (id) boolVectorFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Create and return a new vector. The default memory allocator is used to allocate the
 * vector. If both the platform and allocator support autorelease, then the new vector
 * will be autoreleased before being returned. The vector is initialized with the
 * contents of @a right.
 *
 * @param right the bool vector that should be copied into the new one
 * @return a new vector
 */
+ (id) boolVectorWithBoolVector: (OLBoolVector*)right;

/**
 * Create and return a new vector. The default memory allocator is used to allocate the
 * vector. If both the platform and allocator support autorelease, then the new vector
 * will be autoreleased before being returned. The initial capacity will be no less
 * than @a capacity.
 *
 * @param capacity the minimum capacity of the new vector
 * @return a new vector
 */
+ (id) boolVectorWithCapacity: (unsigned)capacity;

/**
 * Create and return a new vector. The default memory allocator is used to allocate the
 * vector. If both the platform and allocator support autorelease, then the new vector
 * will be autoreleased before being returned. The new vector will have a size of
 * @a size, and each element will be set to @a value.
 *
 * @param size the size of the new vector
 * @param value the value with which to fill the new vector
 * @return a new vector
 */
+ (id) boolVectorWithSize: (unsigned)size filledWithBool: (BOOL)value;

/**
 * @name Initializers and Deallocators
 */
/* @{ */
/**
 * Initialize the vector. The default memory allocator is used, and the capacity
 * is initially zero.
 *
 * @return a reference to this vector
 */
- (id) init;

/**
 * Initialize the vector. The vector uses the default memory allocator and inserts
 * all elements referred to in the range <tt>[first, last)</tt>.
 *
 * @pre The elements in the range <tt>[first, last)</tt> must all respond to the
 * message @c boolValue.
 *
 * @param first the first in the range of elements to insert
 * @param last one beyond the last in the range of elements to insert
 * @return a reference to this vector
 */
- (id) initFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Initialize the vector. The vector uses the given memory allocator and inserts
 * all elements referred to in the range <tt>[first, last)</tt>.
 *
 * @pre The elements in the range <tt>[first, last)</tt> must all respond to the
 * message @c boolValue.
 *
 * @param first the first in the range of elements to insert
 * @param last one beyond the last in the range of elements to insert
 * @param alloc the memory allocator that the vector should use
 * @return a reference to this vector
 */
- (id) initFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last allocator: (OLAllocator*)alloc;

/**
 * Initialize the vector. The given memory allocator is used, and the initial capacity
 * is zero.
 *
 * @param alloc the memory allocator that the vector should use
 * @return a reference to this vector
 */
- (id) initWithAllocator: (OLAllocator*)alloc;

/**
 * Initialize the vector. The allocator of @a vector and all of its elements are copied
 * into the current vector.
 *
 * @param bvector the vector to copy
 * @return a reference to this vector
 */
- (id) initWithBoolVector: (OLBoolVector*)bvector;

/**
 * Initialize the vector. The initial capacity is set to no less than @a capacity,
 * and the default memory allocator is used.
 *
 * @param capacity the minimum initial capacity of the vector
 * @return a reference to this vector
 */
- (id) initWithCapacity: (unsigned)capacity;

/**
 * Initialize the vector. Creates a new vector from an archive and returns it.
 *
 * @post The vector returned will be identical to the vector saved to the archive
 * using the #encodeWithCoder: message.
 *
 * @param decoder the coder which will decode the archived vector
 * @return a reference to this vector
 */
- (id) initWithCoder: (NSCoder*)decoder;

/**
 * Initialize the vector. The initial size of the vector will be @a size, and @a value
 * will be copied into the vector @a size times. The default memory allocator is used.
 *
 * @param size the number of elements to insert
 * @param value the boolean value to insert
 * @return a reference to this vector
 */
- (id) initWithSize: (unsigned)size filledWithBool: (BOOL)value;

/**
 * Initialize the vector. The initial size of the vector will be @a size, and @a value
 * will be copied into the vector @a size times. The given memory allocator is used.
 *
 * @param size the number of elements to insert
 * @param value the boolean value to insert
 * @param alloc the memory allocator that the vector should use
 * @return a reference to this vector
 */
- (id) initWithSize: (unsigned)size filledWithBool: (BOOL)value allocator: (OLAllocator*)alloc;

/**
 * Finalize the vector and deallocate any allocated memory.
 */
- (void) dealloc;
/* @} */

/**
 * Assign a value to the vector. The current contents of the vector are removed,
 * and the vector is filled with @a count elements of @a value.
 *
 * @param count the number of elements to assign
 * @param value the boolean value to insert
 */
- (void) assign: (unsigned)count filledWith: (BOOL)value;

/**
 * Assign @a val to the position at @a index. The bit at position @a index
 * is replaced with @a val.
 *
 * @note The range of the vector is not checked prior to performing this operation.
 * Using values of @a index that do not lie within the vector's range will produce
 * undefined results.
 *
 * @param index the index to which to assign
 * @param val the boolean value to assign
 */
- (void) assignAt: (unsigned)index value: (BOOL)val;

/**
 * Assign a range of objects to the vector. The current contents of the vector are
 * removed, and all elements in the range <tt>[first, last)</tt> are inserted
 * into the vector.
 *
 * @pre The elements in the range <tt>[first, last)</tt> must all respond to the
 * message @c boolValue.
 *
 * @param first the first in the range of objects to assign
 * @param last one beyond the last in the range of objects to assign
 */
- (void) assignFrom: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Return the bit at @a index. YES or NO will be returned depending on whether the
 * bit at @a index is set.
 *
 * @note The range of the vector is not checked prior to performing this operation.
 * Using values of @a index that do not lie within the vector's range will produce
 * undefined results.
 *
 * @param index the index of the object to look up
 * @return YES if the bit is set, NO otherwise
 */
- (BOOL) at: (unsigned)index;

/**
 * Return the last value in the vector.
 *
 * @note The results of this message are undefined if the vector is empty.
 *
 * @return the last object
 */
- (BOOL) back;

/**
 * Return an iterator pointing to the beginning of the sequence. If the platform and
 * the allocator both support autorelease, then the iterator will be scheduled for
 * autorelease before being returned.
 *
 * @return an iterator pointing to the first element
 */
- (OLBitIterator*) begin;

/**
 * Return the current capacity of the vector. The capacity represents the maximum number
 * of elements that the vector can hold before allocation of new memory will be required.
 *
 * @return the capacity
 */
- (unsigned) capacity;

/**
 * Remove all elements.
 */
- (void) clear;
- (id) copyWithAllocator: (OLAllocator*)alloc;
- (id) copyWithZone: (NSZone*)zone;

/**
 * Test whether the vector is empty.
 *
 * @return YES if the vector is empty, NO otherwise
 */
- (BOOL) empty;

/**
 * Encode the vector. The vector is saved to an archive using @a encoder. The vector
 * will be retrieved from the archive using the initializer #initWithCoder:.
 *
 * @param encoder the coder which will save the vector to the archive
 */
- (void) encodeWithCoder: (NSCoder*)encoder;

/**
 * Return an iterator pointing to one position beyond the end of the sequence. If the platform and
 * the allocator both support autorelease, then the iterator will be scheduled for
 * autorelease before being returned.
 *
 * @return an iterator pointing to one position beyond the last element
 */
- (OLBitIterator*) end;

/**
 * Remove the element designated by @a where. If the platform and
 * the allocator both support autorelease, then the iterator returned will be scheduled for
 * autorelease before being returned.
 *
 * @pre @a where must point to an element in this vector.
 *
 * @param where an iterator designating the element to remove
 * @return an iterator indicating the next element in the sequence remaining after @a where
 */
- (OLBitIterator*) erase: (OLBitIterator*)where;

/**
 * Remove a range of elements. All elements in the range <tt>[first, last)</tt> will
 * be removed from the vector. If the platform and allocator both support autorelease,
 * then the iterator returned will be scheduled for autorelease before being returned.
 *
 * @pre @a first and @a last must refer to elements in this vector.
 *
 * @param first the first in the range of elements to remove
 * @param last one position beyond the last in the range of elements to remove
 * @return an iterator indicating the next element in the sequence remaining after
 * removal of the range
 */
- (OLBitIterator*) eraseFrom: (OLBitIterator*)first to: (OLBitIterator*)last;

/**
 * Return the first object in the vector. A reference to the object is returned, though
 * the vector still owns the object in question.
 *
 * @note The results of this message are undefined if the vector is empty.
 *
 * @return the first object
 */
- (BOOL) front;

/**
 * Return the memory allocator being used.
 *
 * @return the memory allocator that this vector uses
 */
- (OLAllocator*) allocator;

/**
 * Insert a number of values into the vector. @a num values of @a value will be inserted
 * just before the position referred to by @a where. Thus, it is valid to use an iterator returned
 * by #end as an argument.
 *
 * @pre @a where must refer to a position in this vector
 *
 * @param where the position at which to insert the objects
 * @param num the number of objects to insert
 * @param value the object to be copied into the vector
 */
- (void) insertAt: (OLBitIterator*)where count: (unsigned)num filledWith: (BOOL)value;

/**
 * Insert a range of values into the vector. All objects in the range <tt>[first, last)</tt>
 * are inserted just before the position referred to by @a where. Thus, it is valid to
 * use an iterator returned by #end as an argument.
 *
 * @pre The elements in the range <tt>[first, last)</tt> must all respond to the
 * message @c boolValue.
 *
 * @param where the position at which to insert the objects
 * @param first the first in the range of objects to insert
 * @param last one position beyond the last in the range of objects to insert
 */
- (void) insertAt: (OLBitIterator*)where from: (OLForwardIterator*)first to: (OLForwardIterator*)last;

/**
 * Insert a value into the vector. @a val will be inserted just before the
 * position referred to by @a where. Thus, it is valid to use an iterator returned
 * by #end as an argument. If the platform and allocator both support autorelease,
 * then the iterator returned will be scheduled for autorelease before being returned.
 *
 * @pre @a where must refer to a position in this vector.
 *
 * @param where the position at which to insert @a object
 * @param val the value to insert
 * @return an iterator pointing to the newly inserted object
 */
- (OLBitIterator*) insertAt: (OLBitIterator*)where value: (BOOL)val;

/**
 * Return whether this vector is equal to another one. Two vectors are considered equal
 * if they both contain the same number of elements and each element is equal to the
 * corresponding element in the other vector. They do not have to have the same memory
 * allocator in order to be considered equal.
 *
 * @param object the object to test
 * @return YES if @a object is equal to this vector
 */
- (BOOL) isEqual: (id)object;

/**
 * Return the maxiumum number of elements that can be stored in a vector. This limit is
 * theoretical, meaning that there is no guarantee that you can insert this many
 * elements into any given vector. The memory conditions of the run-time system play an
 * important role.
 *
 * @return the maximum number of elements for a vector
 */
- (unsigned) maxSize;

/**
 * Remove the last element in the vector.
 *
 * @note If there are no elements in the vector, then the behavior of this message
 * is undefined.
 */
- (void) popBack;

/**
 * Insert @a value at the end of the sequence.
 *
 * @param value the value to insert
 */
- (void) pushBack: (BOOL)value;

/**
 * Return a reverse iterator pointing to the end of the sequence. Advancing the returned
 * iterator will move backwards through the sequence to the point indicated by the
 * iterator returned by #rend. If the platform and the allocator both support autorelease,
 * then the iterator will be scheduled for autorelease before being returned.
 *
 * @return a reverse iterator for the end of the sequence
 */
- (OLReverseRandomIterator*) rbegin;

/**
 * Return a reverse iterator pointing to the beginning of the sequence. This iterator
 * indicates one position beyond the last position that may be referenced by a
 * reverse iterator. If the platform and the allocator both support autorelease,
 * then the iterator will be scheduled for autorelease before being returned.
 *
 * @return a reverse iterator for the beginning of the sequence
 */
- (OLReverseRandomIterator*) rend;

/**
 * Reserve storage. If @a count is less than the current capacity of the vector, then
 * this message does nothing. If @a count is greater than the current capacity, then at least
 * <tt>count - capacity</tt> elements of storage will be added to the container. This
 * may invalidate iterators that are currently active. This operation will not affect
 * the size, or number of elements actually stored, only the capacity.
 *
 * @param count the total number of desired spaces in the vector
 */
- (void) reserve: (unsigned)count;

/**
 * Resize the vector to @a newsize. If @a newsize is smaller than the current #size, then
 * the sequence will be truncated. If @a newsize is larger than the current #size,
 * then @a value will be inserted at the end of the vector as many times as necessary
 * to fill the new size.
 *
 * @param newsize the new size of the vector
 * @param value the value with which to fill new elements, if necessary
 */
- (void) resize: (unsigned)newsize filledWith: (BOOL)value;

/**
 * Return the number of elements in the vector.
 *
 * @return the number of elements
 */
- (unsigned) size;

/**
 * Swap this vector with another one. All elements in @a right will be placed into
 * this vector, and all elements in this vector will be placed in @a right. Unless the
 * allocators of the two vectors are different, the implementation of this message
 * results in a very fast swap.
 *
 * @param right the vector with which to swap this one
 */
- (void) swap: (OLBoolVector*)right;

@end

#endif
