00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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
00145 delete [] m_pArray;
00146
00147
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
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 };
00636