SIBCArray.h

00001 //***************************************************************************************
00002 //
00003 // File supervisor: Softimage 3D Games & 3D Bridge team
00004 //
00005 // (c) Copyright 1999-2002 Avid Technology, Inc. . All rights reserved.
00006 //
00007 //***************************************************************************************
00008 
00009 /****************************************************************************************
00010 THIS CODE IS PUBLISHED AS A SAMPLE ONLY AND IS PROVIDED "AS IS".
00011 IN NO EVENT SHALL SOFTIMAGE, AVID TECHNOLOGY, INC. AND/OR THEIR RESPECTIVE
00012 SUPPLIERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
00013 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00014 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
00015 CONNECTION WITH THE USE OR PERFORMANCE OF THIS CODE .
00016 
00017 COPYRIGHT NOTICE. Copyright © 1999-2002 Avid Technology Inc. . All rights reserved. 
00018 
00019 SOFTIMAGE is a registered trademark of Avid Technology Inc. or its subsidiaries 
00020 or divisions. Windows NT is a registered trademark of Microsoft Corp. All other
00021 trademarks contained herein are the property of their respective owners. 
00022 ****************************************************************************************/
00023 
00024 //***************************************************************************************
00025 // Defines
00026 //***************************************************************************************
00027 #ifndef __CSIBCArray_H__
00028 #define __CSIBCArray_H__
00029 
00030 #ifdef _DEBUG
00031 #include <assert.h>
00032 #define _SI_ASSERT(x) assert(x) 
00033 #else
00034 #define _SI_ASSERT(exp)
00035 #endif
00036 
00037 #include "SIBCUtil.h"
00038 #include <string.h>
00039 
00040 // Disable "identifier was truncated to '255' characters in the debug information" warning.
00041 #if defined(_WIN32) || defined(_WIN32_WCE) || defined( _XBOX )
00042 #pragma warning( disable : 4786 )
00043 #endif
00044 
00045 //***************************************************************************************
00046 // CSIBCArray | Simple, all-purpose chunked array used by other classes.
00047 //***************************************************************************************
00048 
00050 
00053 template < class CElemType > 
00054 class CSIBCArray
00055 {
00056     private :
00057         LONG        m_lNbUsedElem;      // Number of elements used in the array
00058         LONG        m_lNbAllocElem;     // Number of elements allocated to the array
00059         CElemType   *m_pElem;           // Array of elements
00060 
00061     public:
00062 
00067         inline CSIBCArray( const LONG in_lNbElem = 0 );
00068         inline ~CSIBCArray() { DisposeData(); }
00069 
00075         inline LONG GetUsed() const;
00076 
00082         inline LONG GetSize() const;
00083 
00089         inline LONG UsedMem() const;
00090 
00097         inline LONG AllocatedMem() const;
00098 
00108         inline LONG Reserve( const LONG in_lNbElem );
00109 
00120         inline LONG Resize( const LONG in_lNewNbElem );
00121 
00131         inline LONG Extend( const LONG in_lNbElem );
00132 
00142         inline LONG Add(CElemType   in_Elem);
00143 
00154         inline LONG InsertAt(const LONG idx, const LONG nb);
00155 
00162         inline void DeleteAt(const LONG idx, const LONG nb);
00163 
00170         inline CElemType & operator [] ( const ULONG in_lIndex ) const;
00171 
00178         inline CElemType & operator [] ( const ULONG in_lIndex );
00179 
00187         inline LONG Pack( LONG i_MaxWasted = 4 );
00188 
00193         inline void DisposeData( void );
00194 
00203         inline int Become( CSIBCArray<CElemType>& in_rSrcObject );
00204 
00213         inline int Copy( const CSIBCArray<CElemType>& in_rSrcObject );
00214 
00221         inline CSIBCArray<CElemType>& operator = ( const CSIBCArray<CElemType>& in_rSrcObject );
00222 
00226         inline CElemType * ArrayPtr( void ) { return m_pElem; }         
00227 
00232         inline CElemType * * ArrayPtrPtr( void ) { return &m_pElem; }
00233 
00240         inline void Set( LONG start, LONG nb, CElemType value );
00241 
00242     private:
00243 
00244 };
00245 
00246 // Constructor
00247 template <class CElemType>
00248 inline CSIBCArray<CElemType>::CSIBCArray
00249 (
00250     const LONG in_lNbElem
00251 ) : m_lNbUsedElem( 0 ),
00252     m_pElem( NULL ),
00253     m_lNbAllocElem( 0 )
00254 {   
00255     if ( in_lNbElem > 0 )
00256         Resize( in_lNbElem );
00257 }
00258 
00259 //***************************************************************************************
00260 //
00261 // Author : Softimage Games Team
00262 // Date   : 
00263 //
00264 // Gets the current number of elements used in the array.
00265 //
00266 // class | CElemType | Type of element.
00267 //
00268 // Returns the number of used elements in the array.
00269 //
00270 //***************************************************************************************
00271 template <class CElemType>
00272 inline LONG  CSIBCArray<CElemType>::GetUsed() const
00273 {
00274     return m_lNbUsedElem;
00275 }
00276 
00277 //***************************************************************************************
00278 //
00279 // Author : Softimage Games Team
00280 // Date   : 
00281 //
00282 // Gets the current number of elements allocated for the array.
00283 //
00284 // class | CElemType | Type of element.
00285 //
00286 // Returns the number of elements allocated in the array.
00287 //
00288 //***************************************************************************************
00289 template <class CElemType>
00290 inline LONG  CSIBCArray<CElemType>::GetSize() const
00291 {
00292     return m_lNbAllocElem;
00293 }
00294 
00295 //***************************************************************************************
00296 //
00297 // Author : Softimage Games Team
00298 // Date   : 
00299 //
00300 // Returns how much memory used by the used array elements.
00301 //
00302 // class | CElemType | Type of element.
00303 //
00304 // Returns how much memory is used by used array elements.
00305 //***************************************************************************************
00306 template <class CElemType>
00307 inline LONG CSIBCArray<CElemType>::UsedMem() const
00308 {
00309     return m_lNbUsedElem * sizeof( CElemType );
00310 }
00311 
00312 //***************************************************************************************
00313 //
00314 // Author : Softimage Games Team
00315 // Date   : 
00316 //
00317 // Returns how much memory is allocated for the array.
00318 //
00319 // class | CElemType | Type of element.
00320 //
00321 // Returns how much memory is allocated for the array.
00322 //***************************************************************************************
00323 template <class CElemType>
00324 inline LONG CSIBCArray<CElemType>::AllocatedMem() const
00325 {
00326     return m_lNbAllocElem * sizeof( CElemType );
00327 }
00328 
00329 //***************************************************************************************
00330 //
00331 // Author : Softimage Games Team
00332 // Date   : 
00333 //
00334 // Like Resize, but allocates only the requested amount. If the requested amount is
00335 //          greater than the specified one, it marks the number of used objects but
00336 //          does not allocate any more.
00337 //
00338 // LONG | in_lNbElem | number of elements to allocate.
00339 //
00340 // class | CElemType | Type of element.
00341 //
00342 // returns the number of used elements.
00343 //
00344 //***************************************************************************************
00345 template <class CElemType>
00346 inline LONG CSIBCArray<CElemType>::Reserve( const LONG in_lNbElem )
00347 {
00348     CElemType * l_pTmp;
00349     int loop;
00350 
00351     //If we've got allocated elements that are unused
00352     //use one of them instead of allocating more memory
00353     if ( m_lNbAllocElem >= in_lNbElem )
00354     {
00355         return ( m_lNbUsedElem = in_lNbElem );
00356     }
00357     else
00358     {
00359         //Create the new array consisting of the desired number of elements
00360         l_pTmp = new CElemType[in_lNbElem];
00361         
00362         //If it was successful, copy the old array over
00363         if (l_pTmp != NULL )
00364         {
00365             //Copy and remove memory
00366             if (m_pElem)
00367             {
00368 /*
00369                 memcpy( l_pTmp, m_pElem, m_lNbUsedElem * sizeof( CElemType ));
00370 */
00371                 for (loop = 0; loop < m_lNbUsedElem; loop++)
00372                     l_pTmp[loop] = m_pElem[loop];
00373                 
00374                 delete [] m_pElem;
00375             }
00376 
00377             //Assign member array to the newly created array.
00378             m_pElem = l_pTmp;
00379 
00380 
00381             //Number allocated is different than the number used.
00382             m_lNbAllocElem = in_lNbElem;
00383 
00384             return ( m_lNbUsedElem = in_lNbElem );
00385         }
00386 
00387         return m_lNbUsedElem;
00388     }
00389 }
00390 
00391 //***************************************************************************************
00392 //
00393 // Author : Softimage Games Team
00394 // Date   : 
00395 //
00396 // Resizes changes the number of used cells in the array.  This is the primary device
00397 //          to change the size of the array.  If we already have enough space for the 
00398 //          number requested, the array is not resized, just the number of used elements is changed.
00399 //          If we need to allocate more space, we allocate double the requested amount and set the
00400 //          the amount used to the number requested.  This prevents us from having to allocate more
00401 //          frequently.
00402 //
00403 // LONG | in_lNewNbElem | number of elements to allocate.
00404 //
00405 // class | CElemType | Type of element.
00406 //
00407 // Returns the number of used elements
00408 //
00409 //***************************************************************************************
00410 template <class CElemType>
00411 inline LONG CSIBCArray<CElemType>::Resize( const LONG in_lNewNbElem )
00412 {
00413     CElemType * l_pTmp;
00414     int i;
00415 
00416     //If we've got allocated elements that are unused
00417     //use one of them instead of allocating more memory
00418     if ( m_lNbAllocElem >= in_lNewNbElem )
00419     {
00420         return ( m_lNbUsedElem = in_lNewNbElem );
00421     }
00422     else
00423     {
00424         //Add 100% onto the array in order to buffer
00425         LONG l_lNbAlloc = in_lNewNbElem + in_lNewNbElem;
00426         
00427         //Create the new array consisting of the desired number of elements
00428         l_pTmp = new CElemType[l_lNbAlloc];
00429 
00430         //If it was successful, copy the old array over
00431         if (l_pTmp != NULL )
00432         {
00433             //Copy and remove memory
00434             if (m_pElem)
00435             {
00436                 for ( i = 0; i < m_lNbUsedElem; i++ )
00437                 {
00438                     l_pTmp[i] = m_pElem[i];
00439                 }
00440 
00441                 delete [] m_pElem;
00442             }
00443 
00444             //Assign member array to the newly created array.
00445             m_pElem = l_pTmp;
00446 
00447 
00448             //Number allocated is different than the number used.
00449             m_lNbAllocElem = l_lNbAlloc;
00450 
00451             return ( m_lNbUsedElem = in_lNewNbElem );
00452         }
00453 
00454         return m_lNbUsedElem;
00455     }
00456 }
00457 
00458 //***************************************************************************************
00459 //
00460 // Author : Softimage Games Team
00461 // Date   : 
00462 //
00463 // Calls resize with the current number used + the number requested.
00464 //
00465 // LONG | in_lNbElem | number of elements requested.
00466 //
00467 // class | CElemType | Type of element.
00468 //
00469 // rdesc    Returns the number of used elements.
00470 //
00471 //***************************************************************************************
00472 template <class CElemType>
00473 inline LONG CSIBCArray<CElemType>::Extend( const LONG in_lNbElem )
00474 {
00475     return Resize( m_lNbUsedElem + in_lNbElem );
00476 }
00477 
00478 
00479 //***************************************************************************************
00480 //
00481 // Author : Softimage Games Team
00482 // Date   : 
00483 //
00484 // Copies another array.
00485 //
00486 // class | CElemType | Type of element.
00487 //
00488 // Returns the number of used elements.
00489 //
00490 //***************************************************************************************
00491 template <class CElemType>
00492 inline int CSIBCArray<CElemType>::Copy
00493 (
00494     const CSIBCArray<CElemType> & in_rSrcObject
00495 )
00496 {
00497     int     loop;
00498     DisposeData();
00499 
00500 
00501 
00502     if (in_rSrcObject.GetUsed() > 0)
00503     {
00504         //Pre-allocate needed memory
00505         Reserve( in_rSrcObject.GetUsed() );
00506 
00507         //Say that we will use all of it.
00508         Resize( in_rSrcObject.GetUsed() );
00509 
00510         //Check to see that everything worked correctly
00511         if (m_lNbUsedElem >= in_rSrcObject.GetUsed())
00512         {
00513             //Copy over data from other object
00514             for (loop = 0; loop < m_lNbUsedElem; loop++)
00515                 m_pElem[loop] = in_rSrcObject.m_pElem[loop];
00516 
00517 
00518             //Return the number of elements in the array
00519             return m_lNbUsedElem;
00520         }
00521     }
00522 
00523     return 0;
00524 }
00525 
00526 //***************************************************************************************
00527 //
00528 // Author : Softimage Games Team
00529 // Date   : 
00530 //
00531 // Moves the array data from in_rSrcObject to this CSIBArray and sets in_rSrcObject to null.
00532 //
00533 // class | CElemType | Type of element.
00534 //
00535 // Returns 0.
00536 //***************************************************************************************
00537 template <class CElemType>
00538 inline int CSIBCArray<CElemType>::Become( CSIBCArray<CElemType>& in_rSrcObject )
00539 {
00540     DisposeData();
00541 
00542     //Copy values
00543     m_pElem         = in_rSrcObject.m_pElem;
00544     m_lNbUsedElem   = in_rSrcObject.m_lNbUsedElem;
00545     m_lNbAllocElem  = in_rSrcObject.m_lNbAllocElem;
00546 
00547     //kill source
00548     in_rSrcObject.m_pElem           = NULL;
00549     in_rSrcObject.m_lNbUsedElem     = 0;
00550     in_rSrcObject.m_lNbAllocElem    = 0;
00551 
00552     return 0;
00553 }
00554 
00555 //***************************************************************************************
00556 //
00557 // Author : Softimage Games Team
00558 // Date   : 
00559 //
00560 // Copies another array.
00561 //
00562 // class | CElemType | Type of element.
00563 //
00564 // Returns a pointer to the array.
00565 //
00566 //***************************************************************************************
00567 template <class CElemType>
00568 inline CSIBCArray<CElemType> & CSIBCArray<CElemType>::operator = 
00569 (
00570     const CSIBCArray<CElemType> & i_That
00571 )
00572 {
00573     this->Copy( i_That );
00574 
00575     return *this;
00576 }
00577 
00578 //***************************************************************************************
00579 //
00580 // Author : Softimage Games Team
00581 // Date   : 
00582 //
00583 // Deletes all the data allocated to the object and sets the number used/allocated to 0.
00584 //
00585 // class | CElemType | Type of element.
00586 //
00587 // Returns void.
00588 //
00589 //***************************************************************************************
00590 
00591 template <class CElemType> 
00592 inline void CSIBCArray<CElemType>::DisposeData()
00593 {
00594     //If the elements exist, delete them
00595     if ( m_pElem != NULL )
00596     {
00597         //Delete the array pointer and set it to null for reference
00598         delete [] m_pElem;
00599     }
00600 
00601     //Eliminate the counts to 0.
00602     m_lNbUsedElem = 0;
00603     m_lNbAllocElem = 0;
00604     m_pElem = NULL;
00605 }
00606 
00607 //***************************************************************************************
00608 //
00609 // Author : Softimage Games Team
00610 // Date   : 
00611 //
00612 // Removes the excess space after the array by allocating a new one of the same length
00613 //  and then copying the old one over.  To be used after major array resizing only.
00614 //
00615 // LONG | i_MaxWasted | number of elements in array.
00616 //
00617 // class | CElemType | Type of element.
00618 //
00619 // Returns the number possible based on the used elements.
00620 //
00621 //***************************************************************************************
00622 
00623 template <class CElemType> 
00624 LONG CSIBCArray<CElemType>::Pack( LONG i_MaxWasted )
00625 {
00626     int loop;
00627 
00628     //Check to see if packing is neccesary
00629     if (( m_lNbAllocElem - m_lNbUsedElem ) > i_MaxWasted )
00630     {
00631         
00632         //Update the number of allocated element count
00633         m_lNbAllocElem = m_lNbUsedElem;     
00634 
00635         //Create the new array
00636         CElemType * l_pTmp = new CElemType[m_lNbUsedElem];        
00637 
00638         //If we were successful, copy the old elements over
00639         if ( l_pTmp != NULL )
00640         {
00641             //If there are old elements, copy them
00642             if (m_pElem)
00643             {
00644                 //Byte copy old elements (number * size)
00645 /*
00646                 memcpy( l_pTmp, m_pElem, m_lNbUsedElem * sizeof(CElemType) );
00647 */
00648                 for (loop = 0; loop < m_lNbUsedElem; loop++)
00649                     l_pTmp[loop] = m_pElem[loop];
00650                 
00651                 //Delete original array
00652                 delete [] m_pElem;
00653             }
00654 
00655             //copy pointer to new array since old was deleted or null
00656             m_pElem = l_pTmp;
00657         }
00658 
00659     }
00660 
00661     //Return the number possible based on the used elements
00662     return m_lNbUsedElem;
00663 
00664 }
00665 
00666 //***************************************************************************************
00667 //
00668 // Author : Softimage Games Team
00669 // Date   : 
00670 //
00671 // Indexes into the array.
00672 //
00673 // class | CElemType | Type of element.
00674 //
00675 // Returns a reference to the element in the array.
00676 //
00677 //***************************************************************************************
00678 template <class CElemType>
00679 inline CElemType & CSIBCArray<CElemType>::operator []
00680 (
00681     const ULONG in_lIndex
00682 ) const
00683 {
00684     _SI_ASSERT(in_lIndex < ((ULONG)m_lNbUsedElem));
00685     _SI_ASSERT(in_lIndex >= 0);
00686     return m_pElem[in_lIndex];
00687 }
00688 
00689 // Operator [] overload
00690 template <class CElemType>
00691 inline CElemType & CSIBCArray<CElemType>::operator []
00692 (
00693     const ULONG in_lIndex
00694 )
00695 {
00696     _SI_ASSERT(in_lIndex < ((ULONG)m_lNbUsedElem));
00697     _SI_ASSERT(in_lIndex >= 0);
00698     return m_pElem[in_lIndex];
00699 }
00700 
00701 //***************************************************************************************
00702 //
00703 // Author : Softimage Games Team
00704 // Date   : 
00705 //
00706 // Sets a range of elements to the specified value.
00707 //
00708 // LONG | start | first element in the array.
00709 // LONG | nb     | number of elements in the array.
00710 //
00711 // class | CElemType | Type of element.
00712 //
00713 // Returns void
00714 //
00715 //***************************************************************************************
00716 template <class CElemType> 
00717 inline void CSIBCArray<CElemType>::Set
00718 ( 
00719  
00720     LONG start, 
00721     LONG nb, 
00722     CElemType value 
00723 )
00724 {
00725     //Make sure elements exist
00726     if ( m_pElem != NULL )
00727     {
00728         LONG    l_lEnd = start + nb;
00729 
00730         if ( l_lEnd > m_lNbUsedElem )
00731             l_lEnd = m_lNbUsedElem;
00732 
00733         for ( LONG i = start; i < l_lEnd; i++ )
00734             m_pElem[i] = value;
00735     }
00736 }
00737 
00738 //***************************************************************************************
00739 //
00740 // Author : Softimage Games Team
00741 // Date   : 
00742 //
00743 // Inserts elements at the specified location.
00744 //
00745 // LONG | in_lIndex | index location.
00746 // LONG | in_lNbElem | number of elements.
00747 //
00748 // class | CElemType | Type of element.
00749 //
00750 // Returns the number of used elements.
00751 //
00752 //***************************************************************************************
00753 template <class CElemType>
00754 inline LONG CSIBCArray<CElemType>::InsertAt
00755 (
00756     const LONG in_lIndex,
00757     const LONG in_lNbElem
00758 )
00759 {
00760     LONG    l_lOldNb    = m_lNbUsedElem;
00761     LONG    l_lNb       = m_lNbUsedElem + in_lNbElem;
00762     LONG    l_lInsert   = in_lIndex;
00763 
00764     //Check to make sure it's inside the boudns
00765     if (l_lInsert > m_lNbUsedElem)
00766         l_lInsert = m_lNbUsedElem;
00767 
00768     //Ensure we have enough space
00769     Reserve( l_lNb );
00770 
00771     //Use all of it
00772     Resize( l_lNb );
00773 
00774     if (l_lOldNb > in_lIndex)   
00775         memmove(&m_pElem[in_lIndex + in_lNbElem], &m_pElem[in_lIndex], (unsigned int) (sizeof(CElemType) *  (l_lOldNb - in_lIndex)));
00776 
00777     return m_lNbUsedElem;    
00778 }
00779 
00780 //***************************************************************************************
00781 //
00782 // Author : Softimage Games Team
00783 // Date   : 
00784 //
00785 // Removes some cells at the place specified.
00786 //
00787 // LONG | in_lIndex | index location.
00788 // LONG | in_lNbElem | number of elements in the array.
00789 //
00790 // class | CElemType | Type of element.
00791 //
00792 // Returns void.
00793 //
00794 //***************************************************************************************
00795 template <class CElemType>
00796 inline void CSIBCArray<CElemType>::DeleteAt
00797 (
00798     const LONG in_lIndex,
00799     const LONG in_lNbElem
00800 )
00801 {
00802     LONG l_lToDelete = in_lNbElem;
00803 
00804     if ( l_lToDelete > m_lNbUsedElem  )
00805         l_lToDelete = m_lNbUsedElem;
00806 
00807     if ((in_lIndex + in_lNbElem) < m_lNbUsedElem )
00808         memmove( &m_pElem[ in_lIndex ], &m_pElem [ in_lIndex + l_lToDelete ], (unsigned int) (sizeof(CElemType) * (m_lNbUsedElem -  (in_lIndex + l_lToDelete ))));
00809 
00810     m_lNbUsedElem -= l_lToDelete;
00811 }
00812 
00813 //***************************************************************************************
00814 //
00815 // Author : Softimage Games Team
00816 // Date   : 
00817 //
00818 // adds a new element
00819 //
00820 // CElemType | in_Elem | element to add at the end of the array
00821 //
00822 // class | CElemType | Type of element.
00823 //
00824 // Returns the number of used elements.
00825 //
00826 //***************************************************************************************
00827 template <class CElemType>
00828 inline LONG CSIBCArray<CElemType>::Add
00829 (
00830     CElemType in_Elem
00831 )
00832 {
00833     Extend(1);
00834     m_pElem[m_lNbUsedElem - 1] = in_Elem;
00835     return m_lNbUsedElem;    
00836 
00837 }
00838 
00839 #ifdef _WIN32
00840 #pragma warning(disable:4251)
00841 #endif
00842                             
00843 #endif // ALREADY_INCLUDED_CSIBCArray