MercuryVector.h

Go to the documentation of this file.
00001 #ifndef MERCURYVECTOR_H
00002 #define MERCURYVECTOR_H
00003 
00004 #include "global.h"
00005 #include <malloc.h>
00006 #include <string.h>
00007 
00008 //very stripped down and fast vector
00009 template<typename T>
00010 class MVector
00011 {
00012     public:
00013         MVector()
00014             :m_reserved(0), m_size(0), m_data(0)
00015         {  }
00016         ~MVector()
00017         {
00018             clear();
00019         }
00020         MVector(const MVector<T>& v)
00021             :m_reserved(v.m_reserved), m_size(v.m_size)
00022         {
00023             m_data = (T*)malloc(sizeof(T)*m_reserved);
00024             for (unsigned int i = 0; i < m_size; ++i)
00025             {
00026                 new( &m_data[i] ) T (v.m_data[i]);
00027                 #if defined( _DEBUG_MEMORY )
00028                 MercuryAFree( &m_data[i] );
00029                 #endif
00030             }
00031         }
00032         void push_back(const T& element);
00033         inline unsigned int size() const { return m_size; }
00034         inline bool empty() const { return m_size == 0; }
00035         void resize(unsigned int newSize);
00036         void reserve(unsigned int newSize);
00037         inline T& operator[](unsigned int x) { return m_data[x]; }
00038         inline const T& operator[](unsigned int x) const { return m_data[x]; }
00039         inline T& at( unsigned int x ) { return m_data[x]; }
00040         inline const T& at( unsigned int x ) const { return m_data[x]; }
00041         const MVector<T>& operator=(const MVector<T>& v);
00042         void clear();
00043         void remove( int iPlace );
00044         void insert( int iPlace, const T & data );
00045     private:
00046         unsigned int m_reserved; //available space
00047         unsigned int m_size; //number of valid (constructed) objects
00048         T * m_data;
00049 };
00050 
00051 #include "MercuryUtil.h"
00052 
00053 template<typename T>
00054 void MVector<T>::push_back(const T& element)
00055 {
00056     if (m_size >= m_reserved)
00057     {
00058         if (m_reserved <= 0)
00059         {
00060             SAFE_FREE( m_data );
00061             m_data = (T*)malloc(sizeof(T));
00062             m_reserved = 1;
00063         }
00064         else
00065         {
00066             int tsize = nextPow2(m_reserved);
00067             int size = m_size;
00068             reserve(tsize);
00069             m_size = size;
00070         }
00071     }
00072 
00073     new( &m_data[m_size] ) T ( element );
00074     #if defined( _DEBUG_MEMORY )
00075     MercuryAFree( &m_data[m_size] );
00076     #endif
00077 
00078     ++m_size;
00079 }
00080 
00081 template<typename T>
00082 void MVector<T>::resize(unsigned int newSize)
00083 {
00084     if (newSize == 0)
00085     {
00086         clear();
00087         return;
00088     }
00089     //Fully reserve space and initalize constructors
00090     //Make larger and reserve space
00091     if (newSize == m_size)
00092     {
00093         return;
00094     }
00095     else if(newSize > m_size)
00096     {
00097         if (newSize > m_reserved)
00098         {
00099             m_reserved = newSize;
00100             m_data = (T*)realloc(m_data, sizeof(T)*m_reserved);
00101         }
00102 
00103         for (unsigned int i = m_size; i < newSize; ++i)
00104         {
00105             new (&m_data[i]) (T);
00106             #if defined( _DEBUG_MEMORY )
00107             MercuryAFree( &m_data[i] );
00108             #endif
00109 
00110         }
00111     }
00112     else
00113     {
00114         //get smaller
00115         m_reserved = newSize;
00116 
00117         //destroy data that will be lost
00118         for (unsigned int i = m_reserved; i < m_size; ++i)
00119             (&m_data[i])->~T();
00120 
00121         m_data = (T*)realloc(m_data, sizeof(T)*m_reserved);
00122     }
00123     m_size = newSize;
00124 }
00125 
00126 template<typename T>
00127 void MVector<T>::reserve(unsigned int newSize)
00128 {
00129     if (newSize == 0)
00130     {
00131         clear();
00132         return;
00133     }
00134     if (newSize == m_reserved)
00135     {
00136         return;
00137     }
00138     else if (newSize > m_reserved)
00139     {
00140         m_reserved = newSize;
00141         m_data = (T*)realloc(m_data, sizeof(T)*m_reserved);
00142     }
00143     else
00144     {
00145         m_reserved = newSize;
00146 
00147         //destroy data that will be lost
00148         for (unsigned int i = m_reserved; i < m_size; ++i)
00149             (&m_data[i])->~T();
00150 
00151         m_data = (T*)realloc(m_data, sizeof(T)*m_reserved);
00152         m_size = newSize;
00153     }
00154 }
00155 
00156 template<typename T>
00157 void MVector<T>::remove( int iPlace )
00158 {
00159     m_size--;
00160     (&m_data[iPlace])->~T();
00161     memcpy( &m_data[iPlace], &m_data[iPlace+1], sizeof(T) * ( m_size - iPlace ) );
00162 }
00163 
00164 #include <stdio.h>
00165 template<typename T>
00166 void MVector<T>::insert( int iPlace, const T & data )
00167 {
00168     int i;
00169     resize( m_size + 1 );
00170 
00171     (&m_data[m_size-1])->~T();
00172     for( i = m_size - 1; i > iPlace; i-- )
00173         memcpy( &m_data[i], &m_data[i-1], sizeof (T) );
00174 
00175     new ( &m_data[iPlace] ) T( data );
00176     #if defined( _DEBUG_MEMORY )
00177     MercuryAFree( &m_data[iPlace] );
00178     #endif
00179 
00180 }
00181 
00182 template<typename T>
00183 void MVector<T>::clear()
00184 {
00185     for (unsigned int i = 0; i < m_size; ++i)
00186         (&m_data[i])->~T();
00187 
00188     SAFE_FREE(m_data);
00189     m_size = m_reserved = 0;
00190 }
00191 template<typename T>
00192 const MVector<T>& MVector<T>::operator=(const MVector<T>& v)
00193 {
00194     clear();
00195     m_reserved = v.m_reserved;
00196     m_size = v.m_size;
00197     m_data = (T*)malloc(sizeof(T)*m_reserved);
00198     for (unsigned int i = 0; i < m_size; ++i)
00199     {
00200         new( &m_data[i]) T( v.m_data[i] );
00201 #if defined( _DEBUG_MEMORY )
00202         MercuryAFree( &m_data[i] );
00203 #endif
00204     }
00205     return *this;
00206 }
00207 
00208 
00209 template<typename T>
00210 class MDequeNode
00211 {
00212 public:
00213     MDequeNode(): Next(0),Prev(0) { }
00214     MDequeNode( const T & tIn ): Data(tIn), Next(0), Prev(0) { }
00215     T            Data;
00216     MDequeNode<T> * Next;
00217     MDequeNode<T> * Prev;
00218 };
00219 
00221 template<typename T>
00222 class MDequeIterator
00223 {
00224 public:
00225     MDequeIterator() : ThisNode( 0 ) { }
00226     ~MDequeIterator() { ThisNode = 0; }
00227 
00229     inline T & Data() { return ThisNode->Data; }
00231     inline T * operator -> () { return &ThisNode->Data; }
00233     inline T & operator * ()  { return ThisNode->Data; }
00234 
00236     inline MDequeIterator<T> & operator ++ () { if( ThisNode ) ThisNode = ThisNode->Next; return *this; }
00238     inline MDequeIterator<T> & operator -- () { if( ThisNode ) ThisNode = ThisNode->Prev; return *this; }
00239 
00240     //i++ save current iterator, incrememnt, then return the old iterator
00241     inline MDequeIterator<T> operator ++ ( int dummy ) { MDequeNode< T > * pS = ThisNode; ThisNode = ThisNode->Next; return MDequeIterator( pS ); }
00242     //i-- save current iterator, decrement, then return the old iterator
00243     inline MDequeIterator<T> operator -- ( int dummy ) { MDequeNode< T > * pS = ThisNode; ThisNode = ThisNode->Prev; return MDequeIterator( pS); }
00244 
00245     inline bool operator == ( const MDequeIterator & rhs ) { return (ThisNode == rhs.ThisNode ); }
00246     inline bool operator != ( const MDequeIterator & rhs ) { return (ThisNode != rhs.ThisNode ); }
00247 
00248     //Should be private but I Can't get friend functions to work right in this situation
00249     MDequeIterator( MDequeNode<T> * pBootNode ) { ThisNode = pBootNode; }
00250     MDequeNode<T> * ThisNode;
00251 };
00252 
00253 
00254 template<typename T>
00255 //Mercury Deque (similar to list, and deque)
00256 class MDeque
00257 {
00258 public:
00259     MDeque() : iSize(0), Head(0), Tail(0){ }
00260     ~MDeque() { while( Head ) { Temp = Head; Head=Head->Next; delete Temp; } }
00261 
00262     MDeque( const MDeque & rhs ) : iSize(0), Head(0), Tail(0)
00263     {
00264         MDequeIterator< T > t = rhs.begin();
00265         while( t != rhs.end() )
00266         {
00267             push_back( *t );
00268             ++t;
00269         }
00270     }
00271 
00272     MDeque & operator = ( const MDeque & rhs )
00273     {
00274         MDequeIterator< T > t = rhs.begin();
00275         while( t != rhs.end() )
00276         {
00277             push_back( *t );
00278             ++t;
00279         }
00280         return *this;
00281     }
00282     
00284     inline void swap( MDequeIterator<T> & p1, MDequeIterator<T> & p2 ) {
00285 
00286         if( p1.ThisNode->Next == p2.ThisNode )
00287         {
00288             p2.ThisNode->Prev = p1.ThisNode->Prev;
00289             p1.ThisNode->Prev = p2.ThisNode;
00290             p1.ThisNode->Next = p2.ThisNode->Next;
00291             p2.ThisNode->Next = p1.ThisNode;
00292             if( p2.ThisNode->Prev )
00293                 p2.ThisNode->Prev->Next = p2.ThisNode;
00294             else 
00295                 Head = p2.ThisNode;
00296             if( p1.ThisNode->Next )
00297                 p1.ThisNode->Next->Prev = p1.ThisNode;
00298             else
00299                 Tail = p1.ThisNode;
00300         }
00301         else if( p2.ThisNode->Next == p1.ThisNode )
00302         {
00303             p1.ThisNode->Prev = p2.ThisNode->Prev;
00304             p2.ThisNode->Prev = p1.ThisNode;
00305             p2.ThisNode->Next = p1.ThisNode->Next;
00306             p1.ThisNode->Next = p2.ThisNode;
00307 
00308             if( p1.ThisNode->Prev )
00309                 p1.ThisNode->Prev->Next = p1.ThisNode;
00310             else 
00311                 Head = p1.ThisNode;
00312             if( p2.ThisNode->Next )
00313                 p2.ThisNode->Next->Prev = p2.ThisNode;
00314             else
00315                 Tail = p2.ThisNode;
00316         }
00317         else {
00318             Temp = p1.ThisNode->Prev;
00319             p1.ThisNode->Prev = p2.ThisNode->Prev;
00320             p2.ThisNode->Prev = Temp;
00321 
00322             Temp = p1.ThisNode->Next;
00323             p1.ThisNode->Next = p2.ThisNode->Next;
00324             p2.ThisNode->Next = Temp;
00325 
00326             if( p1.ThisNode->Prev )
00327                 p1.ThisNode->Prev->Next = p1.ThisNode;
00328             else 
00329                 Head = p1.ThisNode;
00330             if( p1.ThisNode->Next )
00331                 p1.ThisNode->Next->Prev = p1.ThisNode;
00332             else
00333                 Tail = p1.ThisNode;
00334 
00335 
00336 
00337             if( p2.ThisNode->Prev )
00338                 p2.ThisNode->Prev->Next = p2.ThisNode;
00339             else
00340                 Head = p2.ThisNode;
00341             if( p2.ThisNode->Next )
00342                 p2.ThisNode->Next->Prev = p2.ThisNode;
00343             else
00344                 Tail = p2.ThisNode;
00345 
00346         }
00347     }
00348 
00350     inline void push_front( const T & pData ) { iSize++; Temp = Head; Head = new MDequeNode<T>( pData ); Head->Next = Temp; if( Temp ) Temp->Prev = Head; if( !Tail ) Tail = Head; }
00352     inline void push_back( const T & pData ) { iSize++; Temp = Tail; Tail = new MDequeNode<T>( pData ); Tail->Prev = Temp; if( Temp ) Temp->Next = Tail; if( !Head ) Head = Tail; }
00354     inline void pop_front() { Temp = Head->Next; delete Head; iSize--; Head = Temp; if ( !Temp ) Tail = 0; }
00356     inline void pop_back() { Temp = Tail->Prev; delete Tail; iSize--; Tail = Temp; if ( !Temp ) Head = 0; }
00358     inline T & front() const { return Head->Data; }
00360     inline T & back() const { return Tail->Data; }
00362     inline unsigned int size() const { return iSize; } 
00364     inline bool empty() const { return iSize==0; }
00365 
00367     inline MDequeIterator<T> begin() { return MDequeIterator<T>(Head); }
00369     inline MDequeIterator<T> & end() { return Nil; }
00370 
00372     inline const MDequeIterator<T> begin() const { return MDequeIterator<T>(Head); }
00374     inline const MDequeIterator<T> & end() const { return Nil; }
00375 
00377     inline MDequeIterator<T> find( const T & fCmp )
00378     {
00379         Temp = Head;
00380         while( Temp )
00381             if( Temp->Data == fCmp )
00382                 return MDequeIterator<T>( Temp );
00383             else
00384                 Temp = Temp->Next;
00385         return MDequeIterator<T>( Tail );
00386     }
00387 
00389     inline void erase( MDequeIterator<T> & p ) { 
00390         if( !p.ThisNode || iSize <= 0 )
00391             ASSERT_M( false, "DELETING NULL!!!" );
00392         iSize--;
00393         if( p.ThisNode == Tail )
00394         {
00395             //Special case (last element)
00396             if( p.ThisNode == Head )
00397             {
00398                 delete Tail;
00399                 Tail = 0;
00400                 Head = 0;
00401                 return;
00402             }
00403             Temp = Tail;
00404             Tail = Tail->Prev;
00405             Tail->Next = 0;
00406             delete Temp;
00407             return;
00408         }
00409         else if( p.ThisNode == Head )
00410         {
00411             Temp = Head;
00412             Head = Head->Next;
00413             Head->Prev = 0;
00414             delete Temp;
00415             return;
00416         } else {
00417             Temp = p.ThisNode;
00418             p.ThisNode->Prev->Next = p.ThisNode->Next;
00419             p.ThisNode->Next->Prev = p.ThisNode->Prev;
00420             delete Temp;
00421         }
00422     }
00423 private:
00424     unsigned int iSize;
00425     MDequeIterator <T> Nil;
00426     MDequeNode <T> * Temp;
00427     MDequeNode <T> * Head;
00428     MDequeNode <T> * Tail;
00429 };
00430 
00432 int GetAPrime( int ith );
00433 
00435 template<typename T>
00436 class MHash
00437 {
00438 public:
00439     MHash( ) : m_iSize( GetAPrime( m_iPrimest = 1 ) ) 
00440     { 
00441         m_pTable = new MHashNode<T> * [m_iSize]; 
00442         memset( m_pTable, 0, m_iSize * sizeof( MHashNode<T>* ) );
00443         m_iCount = 0;
00444     }
00445 
00446     MHash( const MHash & rhs ) 
00447     {
00448         m_iPrimest = rhs.m_iPrimest;
00449         m_iCount = rhs.m_iCount;
00450         m_pTable = new MHashNode<T> * [rhs.m_iSize];
00451         m_iSize = rhs.m_iSize;
00452         
00453         memset( m_pTable, 0, m_iSize * sizeof( MHashNode<T>* ) );
00454 
00455         for( unsigned i = 0; i < m_iSize; ++i )
00456         {
00457             MHashNode <T> * TMP = rhs.m_pTable[i];
00458             while (TMP)
00459             {
00460                 m_pTable[i] = new MHashNode<T>( m_pTable[i], TMP->Index, TMP->Data );
00461                 TMP = TMP->Next;
00462             }
00463         }
00464     }
00465 
00466     MHash & operator = ( const MHash & rhs ) 
00467     {
00468         m_iPrimest = rhs.m_iPrimest;
00469         m_iCount = rhs.m_iCount;
00470         m_pTable = new MHashNode<T> * [rhs.m_iSize];
00471         m_iSize = rhs.m_iSize;
00472         
00473         memset( m_pTable, 0, m_iSize * sizeof( MHashNode<T>* ) );
00474 
00475         for( unsigned i = 0; i < m_iSize; ++i )
00476         {
00477             MHashNode <T> * TMP = rhs.m_pTable[i];
00478             while (TMP)
00479             {
00480                 m_pTable[i] = new MHashNode<T>( m_pTable[i], TMP->Index, TMP->Data );
00481                 TMP = TMP->Next;
00482             }
00483         }
00484         return *this;
00485     }
00486 
00487     void resize( int iNewSize )
00488     {
00489         MHashNode <T> ** pOldTable = m_pTable;
00490         int iOldSize = m_iSize;
00491 
00492         m_pTable = new MHashNode<T> * [iNewSize];
00493         m_iSize = iNewSize;
00494         memset( m_pTable, 0, iNewSize * sizeof( MHashNode<T>* ) );
00495 
00496         for( int i = 0; i < iOldSize; ++i )
00497         {
00498             while (pOldTable[i])
00499             {
00500                 MHashNode <T> * TMP = pOldTable[i];
00501                 pOldTable[i] = TMP->Next;
00502 
00503                 int iNewHash = TMP->Index.hash();
00504                 MHashNode <T> * TMP2 =  m_pTable[iNewHash%m_iSize];
00505                 m_pTable[iNewHash%m_iSize] = TMP;
00506                 TMP->Next = TMP2;
00507             }
00508         }
00509 
00510         free( pOldTable );
00511     }
00512 
00513     ~MHash()
00514     {
00515         for( unsigned i = 0; i < m_iSize; ++i )
00516             while (m_pTable[i])
00517             {
00518                 MHashNode <T> * TMP = m_pTable[i];
00519                 m_pTable[i] = TMP->Next;
00520                 SAFE_DELETE( TMP );
00521             }
00522         SAFE_DELETE( m_pTable );
00523     }
00524 
00525     void clear()
00526     {
00527         for( unsigned i = 0; i < m_iSize; ++i )
00528         {
00529             while (m_pTable[i])
00530             {
00531                 MHashNode <T> * TMP = m_pTable[i];
00532                 m_pTable[i] = TMP->Next;
00533                 SAFE_DELETE( TMP );
00534             }
00535             m_pTable[i] = 0;
00536         }
00537         m_iCount = 0;
00538     }
00539 
00541     T & operator[]( const MString & pIndex )
00542     {
00543         unsigned int iHash = pIndex.hash();
00544         MHashNode<T> * m_pTmp = m_pTable[iHash%m_iSize];
00545 
00546         while( m_pTmp )
00547             if( m_pTmp->Index == pIndex )
00548                 return m_pTmp->Data;
00549             else
00550                 m_pTmp = m_pTmp->Next;
00551 
00552         insert( pIndex, T() );
00553 
00554         m_pTmp = m_pTable[iHash%m_iSize];
00555 
00556         while( m_pTmp )
00557             if( m_pTmp->Index == pIndex )
00558                 return m_pTmp->Data;
00559             else
00560                 m_pTmp = m_pTmp->Next;
00561 
00562         //This should NEVER HAPPEN.
00563         FAIL( "FAIL! Hash insertion failed!" );
00564         return m_pNil;
00565     }
00566 
00568     void insert( const MString & pIndex, const T & pData )
00569     {
00570         unsigned int iHash = pIndex.hash();
00571         m_pTable[iHash%m_iSize] = new MHashNode<T>( m_pTable[iHash%m_iSize], pIndex, pData );
00572         
00573         if( ++m_iCount > m_iSize + 5 )
00574             resize( GetAPrime( ++m_iPrimest ) );
00575     }
00576 
00578     T * get( const MString & pIndex )
00579     {
00580         unsigned int iHash = pIndex.hash();
00581         MHashNode<T>    * m_pTmp = m_pTable[iHash%m_iSize];
00582 
00583         while( m_pTmp )
00584             if( m_pTmp->Index == pIndex )
00585                 return &m_pTmp->Data;
00586             else
00587                 m_pTmp = m_pTmp->Next;
00588 
00589         return 0;
00590     }
00591 
00592     bool remove( const MString & pIndex )
00593     {
00594         unsigned int iHash = pIndex.hash();
00595         MHashNode<T>    * m_pPrev = 0; 
00596         MHashNode<T>    * m_pTmp = m_pTable[iHash%m_iSize];
00597 
00598         while( m_pTmp )
00599             if( m_pTmp->Index == pIndex )
00600             {
00601                 if( m_pPrev )
00602                     m_pPrev->Next = m_pTmp->Next;
00603                 else
00604                     m_pTable[iHash%m_iSize] = m_pTable[iHash%m_iSize]->Next;
00605                 SAFE_DELETE( m_pTmp );
00606                 m_iCount--;
00607                 return true;
00608             }
00609             else
00610             {
00611                 m_pPrev = m_pTmp;
00612                 m_pTmp = m_pTmp->Next;
00613             }
00614 
00615         return false;
00616     }
00617 
00618     void VectorIndicies( MVector < MString > & vOut )
00619     {
00620         unsigned int i;
00621         MHashNode<T> * m_pTmp;
00622         for( i = 0; i < m_iSize; i++ )
00623         {
00624             m_pTmp = m_pTable[i];
00625             while( m_pTmp )
00626             {
00627                 vOut.push_back( m_pTmp->Index );
00628                 m_pTmp = m_pTmp->Next;
00629             }
00630         }
00631     }
00632 
00633 private:
00634     template<typename TC>
00635     struct MHashNode
00636     {
00637         MHashNode() : Next(0) { }
00638         MHashNode( MHashNode<TC> * pA, const MString & pIn, const TC & pD ) : Next( pA ), Index( pIn ), Data( pD ) { }
00639 
00640         MHashNode <TC> * Next;
00641         MString Index;
00642         TC      Data;
00643     };
00644 
00645     MHashNode <T> ** m_pTable;
00646     T               m_pNil;
00647     unsigned int    m_iSize;
00648     unsigned int    m_iPrimest;
00649     unsigned int    m_iCount;
00650 };
00651 
00652 #endif 
00653 
00654 /* 
00655  * Copyright (c) 2006 Joshua Allen (MVector), Charles Lohr (MList)
00656  * All rights reserved.
00657  *
00658  * Redistribution and use in source and binary forms, with or
00659  * without modification, are permitted provided that the following
00660  * conditions are met:
00661  *  -   Redistributions of source code must retain the above
00662  *      copyright notice, this list of conditions and the following disclaimer.
00663  *  -   Redistributions in binary form must reproduce the above copyright
00664  *      notice, this list of conditions and the following disclaimer in
00665  *      the documentation and/or other materials provided with the distribution.
00666  *  -   Neither the name of the Mercury Engine nor the names of its
00667  *      contributors may be used to endorse or promote products derived from
00668  *      this software without specific prior written permission.
00669  *
00670  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00671  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00672  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00673  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00674  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00675  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00676  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00677  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00678  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00679  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00680  */

Hosted by SourceForge.net Logo