/***************************************************************************** # Copyright (C) 1994-2008 by David Gordon. # All rights reserved. # # This software is part of a beta-test version of the Consed/Autofinish # package. It should not be redistributed or # used for any commercial purpose, including commercially funded # sequencing, without written permission from the author and the # University of Washington. # # This software is provided ``AS IS'' and any express or implied # warranties, including, but not limited to, the implied warranties of # merchantability and fitness for a particular purpose, are disclaimed. # In no event shall the authors or the University of Washington be # liable for any direct, indirect, incidental, special, exemplary, or # consequential damages (including, but not limited to, procurement of # substitute goods or services; loss of use, data, or profits; or # business interruption) however caused and on any theory of liability, # whether in contract, strict liability, or tort (including negligence # or otherwise) arising in any way out of the use of this software, even # if advised of the possibility of such damage. # # Building Consed from source is error prone and not simple which is # why I provide executables. Due to time limitations I cannot # provide any assistance in building Consed. Even if you do not # modify the source, you may introduce errors due to using a # different version of the compiler, a different version of motif, # different versions of other libraries than I used, etc. For this # reason, if you discover Consed bugs, I can only offer help with # those bugs if you first reproduce those bugs with an executable # provided by me--not an executable you have built. # # Modifying Consed is also difficult. Although Consed is modular, # some modules are used by many other modules. Thus making a change # in one place can have unforeseen effects on many other features. # It may takes months for you to notice these other side-effects # which may not seen connected at all. It is not feasable for me to # provide help with modifying Consed sources because of the # potentially huge amount of time involved. # #*****************************************************************************/ #ifndef rwtvalorderedvector_included #define rwtvalorderedvector_included #include "mbt_exception.h" #include "rwdefs.h" #include "soEmptyString.h" const int nInitialRWTValOrderedVectorCapacity = 0; template class RWTValOrderedVector { public: int nCurrentLength_; int nMaxLength_; TP* pArray_; RWCString soName_; public: RWTValOrderedVector( size_t nCapacity = nInitialRWTValOrderedVectorCapacity, const RWCString& soName = soEmptyString ) : soName_( soName ) { pArray_ = new TP[ nCapacity ]; if ( !pArray_ ) { PANIC_OST( ost ) << "in RWTValOrderedVector ctor. failed to get memory for " << nCapacity << " objects" << ends; throw RWInternalError( ost.str() ); } nMaxLength_ = nCapacity; nCurrentLength_ = 0; } ~RWTValOrderedVector() { delete [] pArray_; } RWTValOrderedVector( const RWTValOrderedVector& aArray ); inline void append( const TP& val ) { if ( nCurrentLength_ + 1 > nMaxLength_ ) resize( (size_t) ( ( nMaxLength_ + 1 ) * nDefaultArrayResizeIncrement ) ); pArray_[ nCurrentLength_ ] = val; ++nCurrentLength_; } void appendArray( const RWTValOrderedVector& aArrayToAppend ); void clear() { nCurrentLength_ = 0; } void* data() { return (void*) pArray_; } int entries() const { return nCurrentLength_; } void increaseCurrentLength( const size_t nNewLength, const TP& valDefault ); void increaseButNotDecreaseMaxLength( const size_t nNewMaxLength ); void increaseMaxLengthIfNecessary( const size_t nExtraRoomNeeded ); int index( const TP& val ) const { for( int nPos = 0; nPos < nCurrentLength_; ++nPos ) { if ( pArray_[ nPos ] == val ) return( nPos ); } return( RW_NPOS ); } inline void insert( const TP& val ) { append( val ); } inline void insertAt( const size_t nIndex, const TP& val ) { if ( nIndex > nCurrentLength_ ) { PANIC_OST( ost ) << "RWTValOrderedVector::insertAt( " << nIndex << " is out of bounds since array has " << nCurrentLength_ << " elements. Name: " << soName_ << ends; throw RWInternalError( ost.str() ); } if ( nCurrentLength_ + 1 > nMaxLength_ ) resize( (size_t) ( ( nMaxLength_ + 1 ) * nDefaultArrayResizeIncrement ) ); for( register size_t n = nCurrentLength_; n > nIndex; --n ) { pArray_[n] = pArray_[n - 1]; } ++nCurrentLength_; pArray_[ nIndex ] = val; } bool isEmpty() const { if ( nCurrentLength_ == 0 ) return true; else return false; } TP last() const { if ( nCurrentLength_ == 0 ) { THROW_ERROR( "RWTValOrderedVector::last called for 0 length array " + soName_ ); } return( pArray_[ nCurrentLength_ - 1 ] ); } int length() const { return nCurrentLength_; } // I had to put the return at the end for the Solaris compiler's optimizer // Otherwise it gives an error at each instanciation: // "rwtvalorderedvector.h", line 110: Error: Different types for "?:" (Ntide* and void // where the (Ntide*) is replaced by whatever type is being instanciated inline TP& operator[]( const size_t nIndex ) { if ( nIndex >= nCurrentLength_ ) { PANIC_OST( ost ) << " RWTValOrderedVector::operator[] with nCurrentLength_ = " << nCurrentLength_ << " out of bounds with nIndex = " << nIndex << " name = " << soName_ << ends; throw RWInternalError( ost.str() ); } return( pArray_[ nIndex ] ); } inline TP operator[]( const size_t nIndex ) const { if ( nIndex < nCurrentLength_ ) return( pArray_[ nIndex ] ); else { PANIC_OST( ost ) << " RWTValOrderedVector::operator[] with nCurrentLength_ = " << nCurrentLength_ << " out of bounds with nIndex = " << nIndex << ends; throw RWInternalError( ost.str() ); } } RWTValOrderedVector& operator=( const RWTValOrderedVector& aArray ) { clear(); resize( aArray.nCurrentLength_ ); nCurrentLength_ = aArray.nCurrentLength_; for( int n = 0; n < nCurrentLength_; ++n ) pArray_[n] = aArray.pArray_[n]; return( *this ); } TP removeAt( size_t nIndex ) { if ( 0 <= nIndex && nIndex < nCurrentLength_ ) { TP val = pArray_[ nIndex ]; // notice that nothing happens to the object at // nCurrentLength_ - 1. It becomes beyond the end // of the array and is identical to the object just // to the left of it. for( int n = nIndex; n <= nCurrentLength_ - 2; ++n ) pArray_[n] = pArray_[n+1]; --nCurrentLength_; return( val ); } else { PANIC_OST( ost ) << "RWTValOrderedVector::removeAt( " << nIndex << " ) had subscript out of bounds since nCurrentLength_ = " << nCurrentLength_ << ends; throw RWInternalError( ost.str() ); } } TP removeLast() { if ( nCurrentLength_ == 0 ) { PANIC_OST( ost ) << "RWTValOrderedVector::removeLast() for an array with 0 elements" << ends; throw RWInternalError( ost.str() ); } --nCurrentLength_; return( pArray_[ nCurrentLength_ ] ); } inline void resize( const size_t nNewSize ) { // resize can make the object larger or smaller. But it // can't make it smaller than the nCurrentLength_ if ( nCurrentLength_ > nNewSize ) { return; } // notice that nNewSize can be smaller than nMaxLength_ TP* pTemp = new TP[ nNewSize ]; if ( !pTemp ) { PANIC_OST( ost ) << "RWTValOrderedVector::resize( " << nNewSize << " ) could not get enough memory" << ends; throw RWInternalError( ost.str() ); } for( int nIndex = 0; nIndex < nCurrentLength_; ++nIndex ) pTemp[ nIndex ] = pArray_[ nIndex ]; delete [] pArray_; pArray_ = pTemp; nMaxLength_ = nNewSize; } inline void reverseElementOrder() { // swap 1 <-> n, 2 <-> n-1... up to n/2. integer divide means // that in the event of odd number of entries, midpoint left alone int nLen = length(); int nLastSwapped = nLen / 2; int nSwapWith; TP tTemp; for( int nIndex = 0; nIndex < nLastSwapped; ++nIndex ) { tTemp = pArray_[nIndex]; nSwapWith = nLen - nIndex - 1; // which one nIndex gets swapped with pArray_[nIndex] = pArray_[ nSwapWith ]; pArray_[ nSwapWith ] = tTemp; } } // reverseElementOrder() void substring ( const RWTValOrderedVector& aArray, const int nStart, const int nLength ); void truncate( size_t nNewLength ) { if ( nCurrentLength_ <= nNewLength ) return; else { nCurrentLength_ = nNewLength; } } }; // Note: the HP compiler recreate .c file in ptrepository with each link // It also seems to run the compiler on these files without any defines. // Thus any #ifdef in the .c file will be false at the compilation that // occurs at link time. #ifdef INLINE_RWTVALORDEREDVECTOR #include "rwtvalorderedvector_inc.cpp" #endif #endif