SIBCArray.h

Go to the documentation of this file.
00001 //***************************************************************************************
00002 // File supervisor: Crosswalk team
00012 //***************************************************************************************
00013 
00014 //***************************************************************************************
00015 // Defines
00016 //***************************************************************************************
00017 #ifndef __CSIBCArray_H__
00018 #define __CSIBCArray_H__
00019 
00020 #ifdef _DEBUG
00021 #include <assert.h>
00022 #define _SI_ASSERT(x) assert(x)
00023 #else
00024 #define _SI_ASSERT(exp)
00025 #endif
00026 
00027 #include "SIBCUtil.h"
00028 #include <string.h>
00029 
00030 // Disable "identifier was truncated to '255' characters in the debug information" warning.
00031 #if defined(_WIN32) || defined(_WIN32_WCE) || defined( _XBOX )
00032 #pragma warning( disable : 4786 )
00033 #endif
00034 
00035 //***************************************************************************************
00036 // CSIBCArray | Simple, all-purpose chunked array used by other classes.
00037 //***************************************************************************************
00038 
00044 template < class CElemType >
00045 class CSIBCArray
00046 {
00047     private :
00048         LONG        m_lNbUsedElem;      // Number of elements used in the array
00049         LONG        m_lNbAllocElem;     // Number of elements allocated to the array
00050         CElemType   *m_pElem;           // Array of elements
00051 
00052     public:
00053 
00058         inline CSIBCArray( const LONG in_lNbElem = 0 );
00061         inline ~CSIBCArray() { DisposeData(); }
00062 
00068         inline LONG GetUsed() const;
00069 
00075         inline LONG GetSize() const;
00076 
00082         inline LONG UsedMem() const;
00083 
00090         inline LONG AllocatedMem() const;
00091 
00101         inline LONG Reserve( const LONG in_lNbElem );
00102 
00113         inline LONG Resize( const LONG in_lNewNbElem );
00114 
00124         inline LONG Extend( const LONG in_lNbElem );
00125 
00135         inline LONG Add(CElemType   in_Elem);
00136 
00147         inline LONG InsertAt(const LONG idx, const LONG nb);
00148 
00155         inline void DeleteAt(const LONG idx, const LONG nb);
00156 
00163         inline CElemType & operator [] ( const ULONG in_lIndex ) const;
00164 
00171         inline CElemType & operator [] ( const ULONG in_lIndex );
00172 
00180         inline LONG Pack( LONG i_MaxWasted = 4 );
00181 
00186         inline void DisposeData( void );
00187 
00196         inline int Become( CSIBCArray<CElemType>& in_rSrcObject );
00197 
00206         inline int Copy( const CSIBCArray<CElemType>& in_rSrcObject );
00207 
00214         inline CSIBCArray<CElemType>& operator = ( const CSIBCArray<CElemType>& in_rSrcObject );
00215 
00219         inline CElemType * ArrayPtr( void ) { return m_pElem; }
00220 
00225         inline CElemType * * ArrayPtrPtr( void ) { return &m_pElem; }
00226 
00233         inline void Set( LONG start, LONG nb, CElemType value );
00234 
00235     private:
00236 
00237 };
00238 
00239 // Constructor
00240 template <class CElemType>
00241 inline CSIBCArray<CElemType>::CSIBCArray
00242 (
00243     const LONG in_lNbElem
00244 ) : m_lNbUsedElem( 0 ),
00245     m_pElem( NULL ),
00246     m_lNbAllocElem( 0 )
00247 {
00248     if ( in_lNbElem > 0 )
00249         Resize( in_lNbElem );
00250 }
00251 
00252 template <class CElemType>
00253 /*  Returns the number of elements currently used in the array.
00254     \return Number of used elements
00255 */
00256 inline LONG  CSIBCArray<CElemType>::GetUsed() const
00257 {
00258     return m_lNbUsedElem;
00259 }
00260 
00261 template <class CElemType>
00262 /*  Returns the number of elements allocated in the array.
00263     \return Number of elements allocated
00264 */
00265 inline LONG  CSIBCArray<CElemType>::GetSize() const
00266 {
00267     return m_lNbAllocElem;
00268 }
00269 
00270 template <class CElemType>
00271 /*  Returns how much memory is used by the used array elements.
00272     \return Memory used by used array elements
00273 */
00274 inline LONG CSIBCArray<CElemType>::UsedMem() const
00275 {
00276     return m_lNbUsedElem * sizeof( CElemType );
00277 }
00278 
00279 template <class CElemType>
00280 /*  Returns how much memory is allocated for the array.
00281     \return Memory allocated for the array
00282 */
00283 inline LONG CSIBCArray<CElemType>::AllocatedMem() const
00284 {
00285     return m_lNbAllocElem * sizeof( CElemType );
00286 }
00287 
00288 template <class CElemType>
00289 /*  Like Resize(), but allocates only the requested amount. If the requested amount is
00290     greater than the specified one, it marks the number of used objects but does not
00291     allocate any more.
00292     \param[in] in_lNbElem Number of elements to allocate
00293     \return Number of used elements
00294 */
00295 inline LONG CSIBCArray<CElemType>::Reserve( const LONG in_lNbElem )
00296 {
00297     CElemType * l_pTmp;
00298     int loop;
00299 
00300     //If we've got allocated elements that are unused
00301     //use one of them instead of allocating more memory
00302     if ( m_lNbAllocElem >= in_lNbElem )
00303     {
00304         return ( m_lNbUsedElem = in_lNbElem );
00305     }
00306     else
00307     {
00308         //Create the new array consisting of the desired number of elements
00309         l_pTmp = new CElemType[in_lNbElem];
00310 
00311         //If it was successful, copy the old array over
00312         if (l_pTmp != NULL )
00313         {
00314             //Copy and remove memory
00315             if (m_pElem)
00316             {
00317 /*
00318                 memcpy( l_pTmp, m_pElem, m_lNbUsedElem * sizeof( CElemType ));
00319 */
00320                 for (loop = 0; loop < m_lNbUsedElem; loop++)
00321                     l_pTmp[loop] = m_pElem[loop];
00322 
00323                 delete [] m_pElem;
00324             }
00325 
00326             //Assign member array to the newly created array.
00327             m_pElem = l_pTmp;
00328 
00329 
00330             //Number allocated is different than the number used.
00331             m_lNbAllocElem = in_lNbElem;
00332 
00333             return ( m_lNbUsedElem = in_lNbElem );
00334         }
00335 
00336         return m_lNbUsedElem;
00337     }
00338 }
00339 
00340 template <class CElemType>
00341 /*  Like Resize(), but allocates only the requested amount. If the requested amount is
00342     greater than the specified one, it marks the number of used objects but does not
00343     allocate any more.
00344     \param[in] in_lNewNbElem Number of elements to allocate
00345     \return Number of used elements
00346 */
00347 inline LONG CSIBCArray<CElemType>::Resize( const LONG in_lNewNbElem )
00348 {
00349     CElemType * l_pTmp;
00350     int i;
00351 
00352     //If we've got allocated elements that are unused
00353     //use one of them instead of allocating more memory
00354     if ( m_lNbAllocElem >= in_lNewNbElem )
00355     {
00356         return ( m_lNbUsedElem = in_lNewNbElem );
00357     }
00358     else
00359     {
00360         //Add 100% onto the array in order to buffer
00361         LONG l_lNbAlloc = in_lNewNbElem + in_lNewNbElem;
00362 
00363         //Create the new array consisting of the desired number of elements
00364         l_pTmp = new CElemType[l_lNbAlloc];
00365 
00366         //If it was successful, copy the old array over
00367         if (l_pTmp != NULL )
00368         {
00369             //Copy and remove memory
00370             if (m_pElem)
00371             {
00372                 for ( i = 0; i < m_lNbUsedElem; i++ )
00373                 {
00374                     l_pTmp[i] = m_pElem[i];
00375                 }
00376 
00377                 delete [] m_pElem;
00378             }
00379 
00380             //Assign member array to the newly created array.
00381             m_pElem = l_pTmp;
00382 
00383 
00384             //Number allocated is different than the number used.
00385             m_lNbAllocElem = l_lNbAlloc;
00386 
00387             return ( m_lNbUsedElem = in_lNewNbElem );
00388         }
00389 
00390         return m_lNbUsedElem;
00391     }
00392 }
00393 
00394 template <class CElemType>
00395 /*  Calls Resize() with the current number used + the number requested.
00396     \param[in] in_lNbElem Number of elements requested
00397     \return Number of used elements
00398 */
00399 inline LONG CSIBCArray<CElemType>::Extend( const LONG in_lNbElem )
00400 {
00401     return Resize( m_lNbUsedElem + in_lNbElem );
00402 }
00403 
00404 
00405 template <class CElemType>
00406 /*  Copies another array.
00407     \param[in] in_rSrcObject Array to copy
00408     \return Number of used elements
00409 */
00410 inline int CSIBCArray<CElemType>::Copy
00411 (
00412     const CSIBCArray<CElemType> & in_rSrcObject
00413 )
00414 {
00415     int     loop;
00416     DisposeData();
00417 
00418 
00419 
00420     if (in_rSrcObject.GetUsed() > 0)
00421     {
00422         //Pre-allocate needed memory
00423         Reserve( in_rSrcObject.GetUsed() );
00424 
00425         //Say that we will use all of it.
00426         Resize( in_rSrcObject.GetUsed() );
00427 
00428         //Check to see that everything worked correctly
00429         if (m_lNbUsedElem >= in_rSrcObject.GetUsed())
00430         {
00431             //Copy over data from other object
00432             for (loop = 0; loop < m_lNbUsedElem; loop++)
00433                 m_pElem[loop] = in_rSrcObject.m_pElem[loop];
00434 
00435 
00436             //Return the number of elements in the array
00437             return m_lNbUsedElem;
00438         }
00439     }
00440 
00441     return 0;
00442 }
00443 
00444 template <class CElemType>
00445 /*  Moves the array data from \c in_rSrcObject to this CSIBArray and sets \c in_rSrcObject to null.
00446     \param[in] in_rSrcObject Reference object from which to move data
00447     \return \c 0
00448 */
00449 inline int CSIBCArray<CElemType>::Become( CSIBCArray<CElemType>& in_rSrcObject )
00450 {
00451     DisposeData();
00452 
00453     //Copy values
00454     m_pElem         = in_rSrcObject.m_pElem;
00455     m_lNbUsedElem   = in_rSrcObject.m_lNbUsedElem;
00456     m_lNbAllocElem  = in_rSrcObject.m_lNbAllocElem;
00457 
00458     //kill source
00459     in_rSrcObject.m_pElem           = NULL;
00460     in_rSrcObject.m_lNbUsedElem     = 0;
00461     in_rSrcObject.m_lNbAllocElem    = 0;
00462 
00463     return 0;
00464 }
00465 
00466 template <class CElemType>
00467 /*  Copies another array.
00468     \param[in] i_That Type of element
00469     \return Pointer to the array
00470 */
00471 inline CSIBCArray<CElemType> & CSIBCArray<CElemType>::operator =
00472 (
00473     const CSIBCArray<CElemType> & i_That
00474 )
00475 {
00476     this->Copy( i_That );
00477 
00478     return *this;
00479 }
00480 
00481 template <class CElemType>
00482 /*  Deletes all the data allocated to the object and sets the number used/allocated to \c 0.
00483     \return void
00484 */
00485 inline void CSIBCArray<CElemType>::DisposeData()
00486 {
00487     //If the elements exist, delete them
00488     if ( m_pElem != NULL )
00489     {
00490         //Delete the array pointer and set it to null for reference
00491         delete [] m_pElem;
00492     }
00493 
00494     //Eliminate the counts to 0.
00495     m_lNbUsedElem = 0;
00496     m_lNbAllocElem = 0;
00497     m_pElem = NULL;
00498 }
00499 
00500 template <class CElemType>
00501 /*  Removes the excess space after the array by allocating a new one of the same length
00502     and then copying the old one over.  To be used after major array resizing only.
00503     \param[in] i_MaxWasted Number of elements in array
00504     \return The number possible based on the used elements
00505 */
00506 LONG CSIBCArray<CElemType>::Pack( LONG i_MaxWasted )
00507 {
00508     int loop;
00509 
00510     //Check to see if packing is neccesary
00511     if (( m_lNbAllocElem - m_lNbUsedElem ) > i_MaxWasted )
00512     {
00513 
00514         //Update the number of allocated element count
00515         m_lNbAllocElem = m_lNbUsedElem;
00516 
00517         //Create the new array
00518         CElemType * l_pTmp = new CElemType[m_lNbUsedElem];
00519 
00520         //If we were successful, copy the old elements over
00521         if ( l_pTmp != NULL )
00522         {
00523             //If there are old elements, copy them
00524             if (m_pElem)
00525             {
00526                 //Byte copy old elements (number * size)
00527 /*
00528                 memcpy( l_pTmp, m_pElem, m_lNbUsedElem * sizeof(CElemType) );
00529 */
00530                 for (loop = 0; loop < m_lNbUsedElem; loop++)
00531                     l_pTmp[loop] = m_pElem[loop];
00532 
00533                 //Delete original array
00534                 delete [] m_pElem;
00535             }
00536 
00537             //copy pointer to new array since old was deleted or null
00538             m_pElem = l_pTmp;
00539         }
00540 
00541     }
00542 
00543     //Return the number possible based on the used elements
00544     return m_lNbUsedElem;
00545 
00546 }
00547 
00548 template <class CElemType>
00549 /*  Returns item at the specified position in the array.
00550     \param[in] in_lIndex Index of the element to retrieve
00551     \return Reference to the element in the array
00552 */
00553 inline CElemType & CSIBCArray<CElemType>::operator []
00554 (
00555     const ULONG in_lIndex
00556 ) const
00557 {
00558     _SI_ASSERT(in_lIndex < ((ULONG)m_lNbUsedElem));
00559     _SI_ASSERT(in_lIndex >= 0);
00560     return m_pElem[in_lIndex];
00561 }
00562 
00563 // Operator [] overload
00564 template <class CElemType>
00565 inline CElemType & CSIBCArray<CElemType>::operator []
00566 (
00567     const ULONG in_lIndex
00568 )
00569 {
00570     _SI_ASSERT(in_lIndex < ((ULONG)m_lNbUsedElem));
00571     _SI_ASSERT(in_lIndex >= 0);
00572     return m_pElem[in_lIndex];
00573 }
00574 
00575 template <class CElemType>
00576 /*  Sets a range of elements to the specified value.
00577     \param[in] start First element in the array
00578     \param[in] nb First element in the array
00579     \param[in] value Number of elements in the array
00580 */
00581 inline void CSIBCArray<CElemType>::Set
00582 (
00583 
00584     LONG start,
00585     LONG nb,
00586     CElemType value
00587 )
00588 {
00589     //Make sure elements exist
00590     if ( m_pElem != NULL )
00591     {
00592         LONG    l_lEnd = start + nb;
00593 
00594         if ( l_lEnd > m_lNbUsedElem )
00595             l_lEnd = m_lNbUsedElem;
00596 
00597         for ( LONG i = start; i < l_lEnd; i++ )
00598             m_pElem[i] = value;
00599     }
00600 }
00601 
00602 template <class CElemType>
00603 /*  Inserts elements at the specified location.
00604     \param[in] in_lIndex Index location
00605     \param[in] in_lNbElem Number of elements
00606     \return The number of used elements
00607 */
00608 inline LONG CSIBCArray<CElemType>::InsertAt
00609 (
00610     const LONG in_lIndex,
00611     const LONG in_lNbElem
00612 )
00613 {
00614     LONG    l_lOldNb    = m_lNbUsedElem;
00615     LONG    l_lNb       = m_lNbUsedElem + in_lNbElem;
00616     LONG    l_lInsert   = in_lIndex;
00617 
00618     //Check to make sure it's inside the boudns
00619     if (l_lInsert > m_lNbUsedElem)
00620         l_lInsert = m_lNbUsedElem;
00621 
00622     //Ensure we have enough space
00623     Reserve( l_lNb );
00624 
00625     //Use all of it
00626     Resize( l_lNb );
00627 
00628     if (l_lOldNb > in_lIndex)
00629         memmove(&m_pElem[in_lIndex + in_lNbElem], &m_pElem[in_lIndex], (unsigned int) (sizeof(CElemType) *  (l_lOldNb - in_lIndex)));
00630 
00631     return m_lNbUsedElem;
00632 }
00633 
00634 template <class CElemType>
00635 /*  Removes the specified elements from the array starting at the specified location.
00636     \param[in] in_lIndex Index location
00637     \param[in] in_lNbElem Number of elements
00638 */
00639 inline void CSIBCArray<CElemType>::DeleteAt
00640 (
00641     const LONG in_lIndex,
00642     const LONG in_lNbElem
00643 )
00644 {
00645     LONG l_lToDelete = in_lNbElem;
00646 
00647     if ( l_lToDelete > m_lNbUsedElem  )
00648         l_lToDelete = m_lNbUsedElem;
00649 
00650     if ((in_lIndex + in_lNbElem) < m_lNbUsedElem )
00651         memmove( &m_pElem[ in_lIndex ], &m_pElem [ in_lIndex + l_lToDelete ], (unsigned int) (sizeof(CElemType) * (m_lNbUsedElem -  (in_lIndex + l_lToDelete ))));
00652 
00653     m_lNbUsedElem -= l_lToDelete;
00654 }
00655 
00656 template <class CElemType>
00657 /*  Adds a new element to the end of the array.
00658     \param[in] in_Elem Element to add
00659     \return The number of used elements
00660 */
00661 inline LONG CSIBCArray<CElemType>::Add
00662 (
00663     CElemType in_Elem
00664 )
00665 {
00666     Extend(1);
00667     m_pElem[m_lNbUsedElem - 1] = in_Elem;
00668     return m_lNbUsedElem;
00669 
00670 }
00671 
00672 #ifdef _WIN32
00673 #pragma warning(disable:4251)
00674 #endif
00675 
00676 #endif // ALREADY_INCLUDED_CSIBCArray