array.h

Go to the documentation of this file.
00001 
00002 //**************************************************************************/
00003 // Copyright (c) 2008 Autodesk, Inc.
00004 // All rights reserved.
00005 //
00006 // Use of this software is subject to the terms of the Autodesk license
00007 // agreement provided at the time of installation or download, or which
00008 // otherwise accompanies this software in either electronic or hard copy form.
00009 //
00010 //**************************************************************************/
00011 // DESCRIPTION:
00012 // CREATED: October 2008
00013 //**************************************************************************/
00014 
00015 namespace mudbox {
00016 
00017 void MBDLL_DECL QuickSort( void *pBase, unsigned int  iNum, unsigned int  iSize, int ( * fComparator ) ( const void *, const void * ) );
00018 
00020 class MBDLL_DECL Block
00021 {
00022 protected:
00023     Block( const char *sName, unsigned int iItemSize )
00024     {                                                                     
00025         m_sName = sName;
00026         m_pNext = s_pHead;
00027         m_pPrev = 0;
00028         if ( m_pNext ) m_pNext->m_pPrev = this;
00029         s_pHead = this;
00030         m_iItemSize = iItemSize;
00031     };
00032 
00033     ~Block( void );
00034     Block *m_pNext, *m_pPrev;
00035     unsigned int m_iItemSize;
00036     static Block *s_pHead;
00037 
00038 public:
00039     inline static const Block *Head( void ) { return s_pHead; };
00040     inline const Block *Next( void ) const { return m_pNext; };
00041     inline unsigned int ItemSize( void ) const { return m_iItemSize; };
00042 
00043     const char *Name( void ) const;
00044     long long Size( void ) const;
00045     long long Address( void ) const;
00046     static void LogAll( float fSizeFilter = 0.01f, bool bSortByAddress = false );
00047     void Check( void ) const;
00048     static void CheckAll( void );
00049     static bool RegisterMemoryBlock( long long iSize );
00050     static bool UnregisterMemoryBlock( long long iSize );
00051     static void SetAllocatorID( const char *pAllocatorID );
00052     static void CopyMemoryBlock( void *pDestination, const void *pSource, long long iSize );
00053 
00054     const char *m_sName;
00055 };
00056 
00058 template < typename type >
00059 class MBDLL_TEMPLATE_DECL Array : public Block
00060 {
00061     friend class Block;
00062 public:
00063     Array( const char *sName ) : Block( sName, sizeof(type) )
00064     { 
00065         m_bData = true; 
00066         m_iSize = 0; 
00067         m_pArray = 0; 
00068         m_pThis = this;
00069     };
00070     Array( const char *sName, unsigned int iSize ) : Block( sName, sizeof(type) ) 
00071     { 
00072         m_bData = true; 
00073         m_iSize = iSize;
00074         m_pArray = 0;
00075         try
00076         {
00077             if ( RegisterMemoryBlock( sizeof(type)*iSize ) )
00078             {
00079                 SetAllocatorID( sName );
00080                 m_pArray = new type[iSize];
00081                 SetAllocatorID( 0 );
00082             }
00083             else
00084                 throw &Error::s_cBadAlloc;
00085         }
00086         catch ( ... )
00087         {
00088             LogAll();
00089             throw &Error::s_cBadAlloc;
00090         };
00091         m_pThis = this;
00092     };
00093     Array( const char *sName, const type *pArray, int iSize ) : Block( sName, sizeof(type) )
00094     { 
00095         m_bData = true; 
00096         m_pArray = 0;
00097         try
00098         {
00099             if ( RegisterMemoryBlock( sizeof(type)*iSize ) )
00100             {
00101                 SetAllocatorID( sName );
00102                 m_pArray = new type[iSize];
00103                 SetAllocatorID( 0 );
00104             }
00105             else
00106                 Error::ThrowBadAlloc();
00107         }
00108         catch ( ... )
00109         {
00110             // probably std::bad_alloc
00111             LogAll();
00112             throw &Error::s_cBadAlloc;
00113         };
00114         if( !m_pArray )
00115             return;
00116 
00117         memcpy( m_pArray, pArray, sizeof(type)*iSize ); 
00118         m_iSize = iSize; 
00119         m_pThis = this;
00120     };
00121     Array( const char *sName, bool bNoObjects ) : Block( sName, sizeof(type) )
00122     { 
00123         m_bData = bNoObjects; 
00124         m_iSize = 0; 
00125         m_pArray = 0; 
00126         m_pThis = this;
00127     };
00128     Array( const char *sName, const Array<type> &a ) : Block( sName, sizeof(type) )
00129     { 
00130         m_bData = true; 
00131         m_pArray = a.m_pArray; 
00132         m_iSize = a.m_iSize; 
00133         a.m_iSize = 0; 
00134         a.m_pArray = 0; 
00135         m_pThis = this;
00136     };
00137     void Clear( bool bDestruct = false ) 
00138     { 
00139         bDestruct = bDestruct;
00140 
00141         if ( m_pArray ) 
00142         {   
00143             UnregisterMemoryBlock( (long long)(sizeof(type)*m_iSize) );
00144 //          if ( bDestruct )
00145                 delete [] m_pArray; 
00146 //          else
00147 //              delete m_pArray;
00148             m_pArray = 0; 
00149         }; 
00150         m_iSize = 0; 
00151     };
00152     inline Array<type> Clone( void ) const { Array<type> a; Copy( a ); return a; };
00153     inline bool Copy( Array<type> &a ) const 
00154     { 
00155         if ( !a.Alloc( m_iSize ) )
00156             return false; 
00157         memcpy( a.m_pArray, m_pArray, sizeof(type)*a.m_iSize ); 
00158         return true;
00159     };
00160     inline void Set( unsigned int iStart, unsigned int iSize, unsigned char cPattern ) { MB_ASSERT( m_pThis == this ); MB_ASSERT( iStart+iSize <= m_iSize ); memset( m_pArray+iStart, int(cPattern), sizeof(type)*iSize ); };
00161     inline bool Extend( unsigned int iElementIndex )
00162     {
00163         if ( iElementIndex == 0xffffffff )
00164             return true;
00165         unsigned int iNewSize = m_iSize;
00166         while ( iElementIndex >= iNewSize )
00167             iNewSize = iNewSize*2+1;
00168         if( iNewSize > m_iSize )
00169             return Alloc( iNewSize );
00170         return true;
00171     };
00172     bool Alloc( unsigned int iNewSize )
00173     {
00174         if ( iNewSize == m_iSize )
00175             return true;
00176         MB_ASSERT( m_pThis == this ); 
00177         type *pNew = 0;
00178         try
00179         {
00180             if ( RegisterMemoryBlock( sizeof(type)*iNewSize ) )
00181             {
00182                 SetAllocatorID( m_sName );
00183                 pNew = new type[iNewSize];
00184                 SetAllocatorID( 0 );
00185             }
00186             else
00187                 throw &Error::s_cBadAlloc;      
00188         }
00189         catch ( Error * )
00190         {
00191             LogAll();
00192             return false;
00193         }
00194         catch ( ... )
00195         {
00196             // probably std::bad_alloc
00197             LogAll();
00198             throw &Error::s_cBadAlloc;
00199         };
00200         if( pNew == 0 )
00201             return false;
00202         if( m_iSize )
00203         {
00204             UnregisterMemoryBlock( sizeof(type)*m_iSize );
00205             if ( m_bData )          
00206                 CopyMemoryBlock( pNew, m_pArray, Min( iNewSize, m_iSize )*sizeof(type) );
00207             else
00208                 for ( unsigned int i = 0; i < Min( iNewSize, m_iSize ); i++ )
00209                     pNew[i] = m_pArray[i];
00210             delete [] m_pArray;
00211         };
00212         m_pArray = pNew;
00213         m_iSize = iNewSize;
00214         return true;
00215     };
00216 
00217     inline type &operator []( int iIndex )
00218     { 
00219         MB_ASSERT( m_pThis == this ); 
00220         MB_ONBUG( (unsigned int)(iIndex) >= m_iSize )
00221             return m_pArray[0];
00222         return m_pArray[iIndex]; 
00223     };
00224     inline type &operator []( unsigned int iIndex ) 
00225     { 
00226         MB_ASSERT( m_pThis == this ); 
00227         MB_ONBUG( iIndex >= m_iSize ) 
00228             return m_pArray[0];
00229         return m_pArray[iIndex];
00230     };
00231     inline const type &operator []( unsigned int iIndex )  const
00232     { 
00233         MB_ASSERT( m_pThis == this ); 
00234         MB_ONBUG( iIndex >= m_iSize )
00235             return m_pArray[0];
00236         return m_pArray[iIndex]; 
00237     };
00238     inline type *operator +( unsigned int iIndex ) { MB_ASSERT( m_pThis == this ); return &operator[]( iIndex ); };
00239     inline type *operator +( int iIndex ) { MB_ASSERT( m_pThis == this ); return &operator[]( iIndex ); };
00240     inline void operator =( const Array<type> &a ) { MB_ASSERT( m_pThis == this && a.m_pThis == &a ); Clear(); m_iSize = a.m_iSize; m_pArray = a.m_pArray; a.m_iSize = 0; a.m_pArray = 0; };
00241 
00242 protected:
00243 
00244     mutable type *m_pArray;
00245     mutable unsigned int m_iSize;
00246     mutable bool m_bData;
00247     mutable const Array<type> *m_pThis;
00248 
00249 public:
00250     ~Array( void ) { MB_ASSERT( m_pThis == this ); Clear(); };
00251     virtual long long MemoryUsage( void ) const { return m_iSize*sizeof(type); };
00252 };
00253 
00296 
00297 template < typename type >
00298 class MBDLL_TEMPLATE_DECL Store : public Array<type>
00299 {
00300 public:
00302     Store(
00303         const char *sName = "unknown"       
00304         ) : Array<type>( sName ) { m_iSize = 0; };
00305         
00314     Store(
00315         unsigned int iSize,     
00316         const char *sName       
00317         ) : Array<type>( sName, iSize ) { m_iSize = iSize; };
00318         
00324     Store(
00325         const type *pArray,             
00326         int iSize,                      
00327         const char *sName = "unknown"   
00328         ) : Array<type>( sName, pArray, iSize ) { m_iSize = iSize; };
00329         
00331     Store(
00332         bool bNoObjects,    
00333         const char *sName   
00334         ) : Array<type>( sName, bNoObjects ) { m_iSize = 0; };
00335         
00337     Store(
00338         const Store &s  
00339         ) : Array<type>( s.m_sName, s ) { m_iSize = s.m_iSize; s.m_iSize = 0; };
00340         
00342     ~Store( void ) { Clear( !Array<type>::m_bData ); };
00343 
00345     bool Copy(
00346         Store &s    
00347         ) const { s.m_iSize = m_iSize; return Array<type>::Copy( s ); };
00348     
00350     Store Clone( void ) const { Store s; s.SetItemCount( m_iSize ); Copy( s ); return s; };
00351     
00353     void Clone(
00354         Store &s    
00355         ) const { s.SetItemCount( m_iSize ); Copy( s ); };
00356 
00358     inline void Clear(
00359         bool bDestruct = false  
00360         ) { Array<type>::Clear( bDestruct ); m_iSize = 0; };
00361         
00367     inline bool SetItemCount(
00368         unsigned int iSize,         
00369         bool bKeepContent = false   
00370         ) 
00371     { 
00372         if ( iSize <= m_iSize )
00373         {
00374             m_iSize = iSize;
00375             return true;
00376         };
00377         if ( !bKeepContent ) 
00378             Clear(); 
00379         if ( Array<type>::Alloc( iSize ) ) 
00380         { 
00381             m_iSize = iSize; 
00382             return true; 
00383         };
00384         return false;
00385     };
00386     
00392     inline bool Allocate(
00393         unsigned int iSize,         
00394         bool bKeepContent = false   
00395         ) { if ( !bKeepContent ) Clear(); return Array<type>::Alloc( iSize ); };
00396         
00402     inline bool Extend(
00403         unsigned int iIndex     
00404         )
00405     { 
00406         if ( Array<type>::Extend( iIndex ) )
00407         {
00408             m_iSize = Max( m_iSize, iIndex+1 );
00409             return true;
00410         };
00411         return false;
00412     };
00413     
00419     inline bool Extend(
00420         int iIndex  
00421         ) { return Extend( (unsigned int)iIndex ); };
00422         
00424     inline void RemoveTail(
00425         int iItemCount = 1      
00426         ) { SetItemCount( ItemCount()-iItemCount ); };
00427         
00429     inline void Fill(
00430         type cPattern       
00431         ) { for ( unsigned int i = 0; i < m_iSize; i++ ) operator[](i) = cPattern; };
00432 
00437     inline unsigned int Add(
00438         const type &e   
00439         ) { if( Array<type>::Extend( m_iSize ) ) { Array<type>::operator[]( m_iSize ) = e; return m_iSize++; } else return 0xffffffff; };
00440     
00445     inline unsigned int Add(
00446         type &e 
00447         ) { if( Array<type>::Extend( m_iSize ) ) { Array<type>::operator[]( m_iSize ) = e; return m_iSize++; } else return 0xffffffff; };
00448 
00452     inline Store &operator =( const Store &s ) { m_iSize = s.m_iSize; s.m_iSize = 0; Array<type>::operator =( s ); return *this; };
00453     
00457     void GetFrom(
00458         Store &s    
00459         ) { m_iSize = s.m_iSize; Array<type>::operator =( s ); };
00460     
00462     const type &operator []( unsigned int iIndex ) const { return Array<type>::m_pArray[iIndex]; };
00463     
00465     type &operator []( unsigned int iIndex ) { MB_ASSERT( iIndex < m_iSize ); return Array<type>::m_pArray[iIndex]; };
00466     
00468     const type &operator []( int iIndex ) const { return operator[]( (unsigned int)iIndex ); };
00469     
00471     type &operator []( int iIndex ) { return operator[]( (unsigned int)iIndex ); };
00472     
00478     inline type *operator +( unsigned int iIndex ) { return &operator[]( iIndex ); };
00479     
00485     inline type *operator +( int iIndex ) { return &operator[]( iIndex ); };
00486     
00488     inline bool IsEmpty( void ) const { return ItemCount() == 0; };
00489     
00491     inline operator bool( void ) const { return !IsEmpty(); };
00492     
00494     inline bool operator !( void ) const { return IsEmpty(); };
00495 
00505     void SetBuffer( type *pData, unsigned int iSize = 0 ) { m_iSize = Array<type>::m_iSize = iSize; Array<type>::m_pArray = pData; };
00506 
00508     void Serialize(
00509         class Stream &s     
00510                    );
00511 
00524     inline void Sort( void ) { QuickSort( Array<type>::m_pArray, m_iSize, sizeof(type), Compare ); };
00525     
00534     inline type *Find(
00535         type a      
00536         ) { return (type *) bsearch( &a, Array<type>::m_pArray, m_iSize, sizeof(type), Compare ); };
00537     
00546     inline type *Find( type *a ) { return (type *) bsearch( a, Array<type>::m_pArray, m_iSize, sizeof(type), Compare ); };
00547     
00552     inline unsigned int IndexOf( type pValue )
00553     {
00554         for(unsigned int i = 0; i < ItemCount(); ++i )
00555             if( (*this)[i] == pValue )
00556                 return i;
00557         return 0xffffffff;
00558     };
00560     unsigned int Remove(
00561         const type &e   
00562         )
00563     {
00564         unsigned int j = 0, i = 0;
00565         while ( i < ItemCount() )
00566         {
00567             if ( operator[]( i ) != e )
00568                 operator[]( j++ ) = operator[]( i );
00569             i++;
00570         };
00571         SetItemCount( j );
00572         return i-j;
00573     };
00574     
00576     void Remove(
00577         unsigned int iIndex     
00578         )
00579     {
00580         while ( iIndex+1 < ItemCount( ) )
00581         {
00582             operator[]( iIndex ) = operator[]( iIndex+1 );
00583             iIndex++;
00584         };
00585         SetItemCount( Min(iIndex,ItemCount()-1) );
00586     };
00587     
00594     unsigned int RemoveDuplicates( void )
00595     {
00596         if ( ItemCount() == 0 )
00597             return 0;
00598         Sort();
00599         unsigned int j = 0;
00600         for ( unsigned int i = 0; i < ItemCount()-1; i++ )
00601         {
00602             if ( operator[]( i ) != operator[]( i+1 ) )
00603                 operator[]( j++ ) = operator[]( i );
00604         };
00605         operator[]( j++ ) = operator[]( ItemCount()-1 );
00606         unsigned iRemoved = ItemCount()-j;
00607         m_iSize = j;
00608         return iRemoved;
00609     };
00610 
00612     inline unsigned int ItemCount( void ) const { return m_iSize; };
00613     
00615     inline type &Last( void ) { if ( ItemCount() ) return operator []( ItemCount()-1 ); else throw new Error( "Store::LastItem called for an empty store" ); };
00616 
00626     inline void Optimize( void ) { Array<type>::Alloc( m_iSize ); };
00627 
00628 protected:
00629     static int Compare( const void *a, const void *b ) { return (int)(*((type *)a)-*((type *)b)); };
00630 
00631 public:
00632     mutable unsigned int m_iSize;
00633 };
00634 
00635 }; // end of namespace mudbox
00636