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