//----------------------------------------------------------------------
//  SPECIFICATION FILE (IntFlexVec.h)
//  This module exports an integer vector class that allows:
//    1. Run-time specification and changing of vector lower and upper bounds
//    2. Trapping of invalid subscripts
//    3. Aggregate vector assignment
//    4. Aggregate vector initialization (for parameter passage by
//       value, function value return, initialization in a declaration)
//    5. Growing and shrinking.
//    6. No unitialized elements.
//  This is patterned after arrays in CLU.
//----------------------------------------------------------------------

#ifndef vector_h
#define vector_h 1

#include <iostream.h>
#include <limits.h>
#include "bool.h"

typedef int ItemType;

class IntFlexVec {
  // ABSTRACTLY: a low bound and a sequence of ItemType values, starting from
  // the low bound.  We use the notation <e1,...,en> for such a sequence;
  // it has size n. The "legal indexes" of such an abstract value
  // are lb .. size+lb-1.  The "high bound" of self is thus
  // the low bound + the size - 1.  The first element of the sequence is e1
  // and the "last" is en.
  
public:
  IntFlexVec( int lowerBound = 0, int numElements = 0 );
    // MODIFIES: self
    // POST: self is an empty sequence, with low bound lowerBound.
    // Note: If numElements >= 0, then numElements are expected to be added
    // using AddHigh, otherwise abs(numElements) are expected to be added
    // using AddLow.
    // Note: numElements is a hint that may help speed execution.

  IntFlexVec( int lowerBound, int numElements, ItemType elt );
    // PRE: numElements > 0 && lowerBound + numElements <= INT_MAX
    // MODIFIES: self
    // POST: self is an sequence of size numElements, with each of them elt
    // && the low bound is lowerBound.
  
  IntFlexVec( const IntFlexVec& anotherVec );  // a "copy-constructor"
    // MODIFIES: self
    // POST: self has the same abstract value as anotherVec.

  ~IntFlexVec();      // Destructor
    // MODIFIES: self
    // POST: the abstract value is undefined.

  IntFlexVec & operator = ( const IntFlexVec & vec2 );
    // POST: FCTVAL == the object self
    // && self has the same sequence and low bound as vec2
  
  int Low ( ) const;
    // POST: FCTVAL == the low bound of self

  int High ( ) const;
    // POST: FCTVAL == the high bound of self

  int Size ( );
    // POST: FCTVAL == self's sequence size

  Boolean Empty ( );
    // POST: FCTVAL == (self's sequence is empty)

  void Set_Low ( int lb );
    // MODIFIES: self
    // POST: the low bound of self is made lb && the sequence is unchanged.

  ItemType operator[] ( int i ) const;
    // MODIFIES: cerr
    // POST: IF i is a legal index
    //       THEN FCTVAL == the (lb+i-1)th element of the sequence
    //                       (with 1-based indexing)
    //       ELSE an error message is printed and the program halted.

  void Store ( int i, ItemType elt );
    // MODIFIES: cerr
    // POST: IF i is a legal index
    //       THEN the (lb+i-1)th element of the sequence is made to be elt
    //                       (with 1-based indexing)
    //       ELSE an error message is printed and the program halted.

  ItemType Bottom ( ) const;
    // MODIFIES: cerr
    // POST: IF self's sequence is not empty
    //       THEN FCTVAL == the first element of the sequence
    //       ELSE an error message is printed and the program halted.

  ItemType Top ( ) const;
    // MODIFIES: cerr
    // POST: IF self's sequence is not empty
    //       THEN FCTVAL == the last element of the sequence
    //       ELSE an error message is printed and the program halted.

  void AddHigh ( ItemType elt );
    // PRE: the high bound + 1 <= INT_MAX
    // MODIFIES: self
    // POST: the sequence of self is the same as self<entry>
    // except that elt is added as the last element.

  void AddLow ( ItemType elt );
    // PRE: the low bound - 1 >= INT_MIN
    // MODIFIES: self
    // POST: the sequence of self is the same as self<entry>
    // except that elt is added as the first element
    // && the low bound of self is the low bound of self<entry> - 1.

  ItemType RemHigh ( ItemType elt );
    // MODIFIES: self, cerr
    // POST: IF self is not empty
    //       THEN the sequence of self is the same as self<entry>
    //            except that the last element is removed
    //            && FCTVAL is the first element of self<entry>
    //       ELSE an error message is printed and the program halted.

  ItemType RemLow ( ItemType elt );
    // MODIFIES: self, cerr
    // POST: IF self is not empty
    //       THEN the sequence of self is the same as self<entry>
    //            except that the first element is removed
    //            && the low bound of self is the low bound of self<entry> + 1
    //            && FCTVAL is the first element of self<entry>
    //       ELSE an error message is printed and the program halted.

  Boolean operator == ( const IntFlexVec & anotherVec) const;
    // POST: FCTVAL == (self and anotherVec have the same abstract value)

#include "IntFlexVec.pri"
};
#endif
