SL_Array.h

00001 //***************************************************************************************
00002 //
00003 // File supervisor: Softimage 3D Games & 3D Bridge team
00004 //
00005 // (c) Copyright 2001-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 #ifndef __SL_ARRAY_H__
00025 #define __SL_ARRAY_H__
00026 
00027 #if defined(_WIN32) || defined(_WIN32_WCE) || defined(_XBOX)
00028 // Disable "identifier was truncated to '255' characters in the debug information" warning.
00029 #pragma warning( disable : 4786 )
00030 #endif // defined(_WIN32) || defined(_WIN32_WCE)
00031 
00032 #include <SIBCArray.h>  // CdotXSITemplate
00033 #include "SL_Int.h" // CSLIntProxy
00034 #include <new.h>
00035 
00036 // Align structure elements on 4-byte boundaries.
00037 #if defined(_WIN32) || defined(_WIN32_WCE) || defined(_XBOX)
00038 #pragma pack(push,4)
00039 #elif defined(CODEWARRIOR)
00040 #pragma options align= mac86k4byte
00041 #endif
00042 
00044 
00075 template <class CElemType, class CSubElemType, SI_Int StructSize>
00076 class XSIEXPORT CSLArrayProxy
00077 {
00078 public:
00083     CSLArrayProxy( CdotXSITemplate *in_pTemplate, SI_Long in_Index);
00084 
00087     CSLArrayProxy();
00088 
00092     ~CSLArrayProxy();
00093 
00099     SI_Error Connect( CdotXSITemplate *in_pTemplate, SI_Long in_lArrayIndex );
00100 
00107     inline SI_Long GetUsed() const;     
00108 
00114     inline SI_Long GetSize() const;     
00115 
00120     inline SI_Long UsedMem() const;     
00121 
00126     inline SI_Long AllocatedMem() const;    
00127 
00139     SI_Long Reserve( const SI_Long in_lNbElem );            
00140 
00155     SI_Long Resize( const SI_Long in_lNewNbElem );          
00156 
00171     SI_Long Extend( const SI_Long in_lNbElem );         
00172 
00189     SI_Long InsertAt(const SI_Long in_lIndex, const SI_Long in_lNbElem);
00190     
00200     inline SI_Long Add(CElemType in_Elem);
00201 
00206     SI_Void DeleteAt(const SI_Long in_lIndex, const SI_Long in_lNbElem);    
00207 
00212     inline CElemType & operator [] ( const SI_Long in_lIndex ) const;   
00213 
00218     inline CElemType & operator [] ( const SI_Long in_lIndex );
00219 
00228     SI_Long Pack( SI_Long i_lMaxWasted = 4L );      
00229 
00233     SI_Void DisposeData( SI_Void );             
00234 
00240     SI_Int Copy( const CSIBCArray<CElemType>& in_rSrcObject );
00241 
00247     SI_Int Copy( const CSLArrayProxy<CElemType, CSubElemType, StructSize>& in_rSrcObject );
00248 
00254     CSLArrayProxy& operator = ( const CSIBCArray<CElemType>& in_rSrcObject );
00255 
00261     CSLArrayProxy& operator = ( const CSLArrayProxy<CElemType, CSubElemType, StructSize>& in_rSrcObject );
00262 
00266     inline CElemType* ArrayPtr( SI_Void );
00267 
00273     inline SI_Void Set( SI_Long start, SI_Long in_lNbElem, CElemType value );   
00274 
00275 private :
00276     SI_Long m_lNbUsedElem;
00277     SI_Long m_lNbAllocElem;
00278 
00279     SI_TinyVariant *m_pVariant;
00280 
00281     SI_Long ExpandArray
00282     ( 
00283         const SI_Long in_lNewSize, 
00284         const SI_Long in_lExpandRatio = 1
00285     );
00286 };
00287 
00289 // implementation
00290 
00291 template <class CElemType, class CSubElemType, SI_Int StructSize>
00292 CSLArrayProxy<CElemType, CSubElemType, StructSize>::CSLArrayProxy
00293 ( 
00294     CdotXSITemplate *in_pTemplate, 
00295     SI_Long in_lArrayIndex
00296 )
00297 {
00298     Connect(in_pTemplate, in_lArrayIndex);
00299 }
00300 
00301 template <class CElemType, class CSubElemType, SI_Int StructSize>
00302 CSLArrayProxy<CElemType, CSubElemType, StructSize>::CSLArrayProxy
00303 ( 
00304 )
00305 {
00306 }
00307 
00308 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00309 CSLArrayProxy<CElemType, CSubElemType, StructSize>::~CSLArrayProxy()
00310 { 
00311 }
00312 
00313 template <class CElemType, class CSubElemType, SI_Int StructSize>
00314 SI_Error CSLArrayProxy<CElemType, CSubElemType, StructSize>::Connect
00315 ( 
00316     CdotXSITemplate *in_pTemplate, 
00317     SI_Long in_lArrayIndex
00318 ) 
00319 {
00320     // get the pointer to the array
00321     _SI_ASSERT(in_pTemplate);
00322     CdotXSIParam *l_pParam = in_pTemplate->Params().Item( in_lArrayIndex );
00323 
00324     if ( !l_pParam )
00325         return SI_SUCCESS;
00326 
00327     _SI_ASSERT(l_pParam);
00328     m_pVariant = l_pParam->GetVariantPtr();
00329 
00330     // get the current size of the array
00331     _SI_ASSERT(m_pVariant);
00332 
00333     if(m_pVariant->p_voidVal == NULL)
00334     {
00335         m_pVariant->numElems = 0;
00336     }
00337 
00338     m_lNbUsedElem = m_pVariant->numElems / StructSize;
00339     m_lNbAllocElem = m_lNbUsedElem;
00340 
00341     return SI_SUCCESS;
00342 }
00343 
00344 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00345 inline SI_Long CSLArrayProxy<CElemType, CSubElemType, StructSize>::GetUsed() const
00346 {
00347     return m_lNbUsedElem;
00348 }
00349 
00350 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00351 inline SI_Long CSLArrayProxy<CElemType, CSubElemType, StructSize>::GetSize() const
00352 {
00353     return m_lNbAllocElem;
00354 }
00355 
00356 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00357 inline SI_Long CSLArrayProxy<CElemType, CSubElemType, StructSize>::UsedMem() const
00358 {
00359     return GetUsed() * StructSize;
00360 }
00361 
00362 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00363 inline SI_Long CSLArrayProxy<CElemType, CSubElemType, StructSize>::AllocatedMem() const
00364 {
00365     return GetSize() * StructSize;
00366 }
00367 
00368 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00369 SI_Long CSLArrayProxy<CElemType, CSubElemType, StructSize>::Reserve
00370 ( 
00371     const SI_Long in_lNbElem 
00372 )
00373 {
00374     return ExpandArray(in_lNbElem);
00375 }
00376 
00377 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00378 SI_Long CSLArrayProxy<CElemType, CSubElemType, StructSize>::Resize
00379 ( 
00380     const SI_Long in_lNewNbElem 
00381 )
00382 {
00383     return ExpandArray( in_lNewNbElem, 2 );
00384 }
00385 
00386 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00387 SI_Long CSLArrayProxy<CElemType, CSubElemType, StructSize>::Extend
00388 ( 
00389     const SI_Long in_lNbElem 
00390 )
00391 {
00392     return Resize( m_lNbUsedElem + in_lNbElem );
00393 }
00394 
00395 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00396 SI_Long CSLArrayProxy<CElemType, CSubElemType, StructSize>::InsertAt
00397 (
00398     const SI_Long in_lIndex, 
00399     const SI_Long in_lNbElem
00400 )
00401 {
00402     _SI_ASSERT(in_lNbElem); // inserting 0 elements does not make any sense
00403 
00404     SI_Long    l_lOldNb = m_lNbUsedElem;
00405     SI_Long    l_lNb        = m_lNbUsedElem + in_lNbElem;
00406     SI_Long l_lInsert   = in_lIndex;
00407 
00408     //Check to make sure it's inside the boudns
00409     if (l_lInsert > m_lNbUsedElem)
00410         l_lInsert = m_lNbUsedElem;
00411 
00412     //Ensure we have enough space
00413     Reserve( l_lNb );
00414 
00415     if (l_lOldNb > in_lIndex)
00416     {
00417         CElemType *l_pDest = ((CElemType*)m_pVariant->p_voidVal) + (in_lIndex + in_lNbElem);
00418         CElemType *l_pSrc  = ((CElemType*)m_pVariant->p_voidVal) + in_lIndex;
00419 
00420         memmove( l_pDest, l_pSrc, (l_lOldNb - in_lIndex) * sizeof(CSubElemType) * StructSize);
00421     }
00422 
00423     m_pVariant->numElems = m_lNbUsedElem * StructSize;
00424     return m_lNbUsedElem;
00425 }
00426 
00427 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00428 SI_Void CSLArrayProxy<CElemType, CSubElemType, StructSize>::DeleteAt
00429 (
00430     const SI_Long in_lIndex, 
00431     const SI_Long in_lNbElem
00432 )
00433 {
00434     _SI_ASSERT(in_lNbElem);  // deleting 0 elements does not make any sense
00435     SI_Long l_lToDelete = in_lNbElem;
00436 
00437     if ( l_lToDelete > m_lNbUsedElem  )
00438         l_lToDelete = m_lNbUsedElem;
00439 
00440     if ((in_lIndex + in_lNbElem) < m_lNbUsedElem )
00441     {
00442         CElemType *l_pSrc = ((CElemType*)m_pVariant->p_voidVal) + in_lIndex + in_lNbElem;
00443         CElemType *l_pDest= ((CElemType*)m_pVariant->p_voidVal) + in_lIndex ;
00444         CElemType *l_pEnd = ((CElemType*)m_pVariant->p_voidVal) + m_lNbUsedElem;
00445 
00446         memmove( l_pDest, l_pSrc, (l_pEnd - l_pSrc) * sizeof(CSubElemType) * StructSize);
00447     }
00448 
00449     m_lNbUsedElem = m_lNbUsedElem - l_lToDelete;
00450     m_pVariant->numElems = m_lNbUsedElem * StructSize;
00451 }
00452 
00453 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00454 inline CElemType& CSLArrayProxy<CElemType, CSubElemType, StructSize>::operator []
00455 ( 
00456     const SI_Long in_lIndex 
00457 ) const
00458 {
00459     _SI_ASSERT(in_lIndex < ((SI_Long)m_lNbUsedElem));
00460     _SI_ASSERT(in_lIndex >= 0);
00461 
00462     return *( ( (CElemType*) m_pVariant->p_voidVal ) + in_lIndex);
00463 }
00464 
00465 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00466 inline CElemType& CSLArrayProxy<CElemType, CSubElemType, StructSize>::operator []
00467 ( 
00468     const SI_Long in_lIndex 
00469 )
00470 {
00471     _SI_ASSERT(in_lIndex < ((SI_Long)m_lNbUsedElem));
00472     _SI_ASSERT(in_lIndex >= 0);
00473 
00474     return *( ( (CElemType*) m_pVariant->p_voidVal ) + in_lIndex);
00475 }
00476 
00477 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00478 SI_Long CSLArrayProxy<CElemType, CSubElemType, StructSize>::Pack
00479 ( 
00480     SI_Long i_lMaxWasted 
00481 )
00482 {
00483     //Check to see if packing is neccesary
00484     if (( m_lNbAllocElem - m_lNbUsedElem ) > i_lMaxWasted )
00485     {
00486         //Create the new array
00487         CElemType * l_pNewArray = (CElemType *) FTK_calloc( m_lNbUsedElem * StructSize, sizeof( CSubElemType )) ;
00488 
00489         //If we were successful
00490         if ( l_pNewArray != NULL )
00491         {
00492             // copy exisiting array data into new array
00493             CElemType *l_pCurrentArray = (CElemType*)m_pVariant->p_voidVal;
00494             register SI_Long i;
00495 
00496             for ( i = 0; i < GetUsed(); i++)
00497             {
00498                 l_pNewArray[i] = l_pCurrentArray[i];
00499             }
00500 
00501             //Delete original array
00502             for ( i = 0; i < GetUsed(); i++)
00503             {
00504                 l_pCurrentArray[i].~CElemType();
00505             }
00506             FTK_free((void *) l_pCurrentArray );
00507 
00508             //copy pointer to new array since old was deleted or null
00509             m_pVariant->p_voidVal = l_pNewArray;
00510 
00511             // update number of allocated elements
00512             m_lNbAllocElem = m_lNbUsedElem;     
00513             m_pVariant->numElems = m_lNbUsedElem * StructSize;
00514         }
00515     }
00516 
00517     return m_lNbUsedElem;
00518 }
00519 
00520 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00521 SI_Void CSLArrayProxy<CElemType, CSubElemType, StructSize>::DisposeData
00522 ()
00523 {
00524     CElemType *l_pCurrentArray = (CElemType*)m_pVariant->p_voidVal;
00525     for (register SI_Long i = 0; i < m_lNbAllocElem; i++ )
00526     {
00527         l_pCurrentArray[i].~CElemType();
00528     }
00529     FTK_free( (void *) m_pVariant->p_voidVal );
00530     m_lNbAllocElem = 0; m_lNbUsedElem = 0; 
00531     m_pVariant->numElems = 0;
00532 
00533     Reserve(1); // we don't want a null ptr here.  
00534 }
00535 
00536 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00537 SI_Int CSLArrayProxy<CElemType, CSubElemType, StructSize>::Copy
00538 ( 
00539     const CSIBCArray<CElemType>& in_rSrcObject 
00540 )
00541 {
00542     DisposeData();
00543 
00544     if (in_rSrcObject.GetUsed() > 0)
00545     {
00546         //Pre-allocate needed memory
00547         Reserve( in_rSrcObject.GetUsed() );
00548 
00549         //Check to see that everything worked correctly
00550         if (m_lNbUsedElem >= in_rSrcObject.GetUsed())
00551         {
00552             CElemType *l_pDestinationArray = (CElemType*)m_pVariant->p_voidVal;
00553             
00554             //Copy over data from other object
00555             for ( register SI_Long i = 0; i < m_lNbUsedElem; i++)
00556             {
00557                 l_pDestinationArray[i] =  in_rSrcObject[i];
00558             }
00559 
00560             //Returns the number of elements in the array
00561             return m_lNbUsedElem;
00562         }
00563     }
00564 
00565     return 0;
00566 }
00567 
00568 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00569 SI_Int CSLArrayProxy<CElemType, CSubElemType, StructSize>::Copy
00570 ( 
00571     const CSLArrayProxy<CElemType, CSubElemType, StructSize>& in_rSrcObject 
00572 )
00573 {
00574     DisposeData();
00575 
00576     if (in_rSrcObject.GetUsed() > 0)
00577     {
00578         //Pre-allocate needed memory
00579         Reserve( in_rSrcObject.GetUsed() );
00580 
00581         //Check to see that everything worked correctly
00582         if (m_lNbUsedElem >= in_rSrcObject.GetUsed())
00583         {
00584             CElemType *l_pDestinationArray = (CElemType*)m_pVariant->p_voidVal;
00585             
00586             //Copy over data from other object
00587             for ( register SI_Long i = 0; i < m_lNbUsedElem; i++)
00588             {
00589                 l_pDestinationArray[i] =  in_rSrcObject[i];
00590             }
00591 
00592             //Returns the number of elements in the array
00593             return m_lNbUsedElem;
00594         }
00595     }
00596 
00597     return 0;
00598 }
00599 
00600 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00601 CSLArrayProxy<CElemType, CSubElemType, StructSize>& CSLArrayProxy<CElemType, CSubElemType, StructSize>::operator =
00602 ( 
00603     const CSIBCArray<CElemType>& in_rSrcObject 
00604 )
00605 {
00606     Copy(in_rSrcObject);
00607     return *this;
00608 }
00609 
00610 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00611 CSLArrayProxy<CElemType, CSubElemType, StructSize>& CSLArrayProxy<CElemType, CSubElemType, StructSize>::operator =
00612 ( 
00613     const CSLArrayProxy<CElemType, CSubElemType, StructSize>& in_rSrcObject 
00614 )
00615 {
00616     Copy(in_rSrcObject);
00617     return *this;
00618 }
00619 
00620 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00621 inline CElemType* CSLArrayProxy<CElemType, CSubElemType, StructSize>::ArrayPtr()
00622 { 
00623     return (CElemType*)m_pVariant->p_voidVal;
00624 }           
00625 
00626 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00627 inline SI_Void CSLArrayProxy<CElemType, CSubElemType, StructSize>::Set
00628 ( 
00629     SI_Long in_lstart, 
00630     SI_Long in_lNbElem, 
00631     CElemType in_Value 
00632 )
00633 {
00634     SI_Long    l_lEnd = in_lstart + in_lNbElem;
00635 
00636     if ( l_lEnd > m_lNbUsedElem )
00637     {
00638         l_lEnd = m_lNbUsedElem;
00639     }
00640 
00641     CElemType* l_pArrayToSet = (CElemType*)m_pVariant->p_voidVal;
00642     for ( register SI_Long i = in_lstart; i < l_lEnd; i++ )
00643     {
00644         l_pArrayToSet[i] = in_Value;
00645     }
00646 }
00647 
00654 template <class CElemType, class CSubElemType, SI_Int StructSize> 
00655 SI_Long CSLArrayProxy<CElemType, CSubElemType, StructSize>::ExpandArray
00656 ( 
00657     const SI_Long in_lNewSize,
00658     const SI_Long in_lExpandRatio   
00659 )
00660 {
00661     // if there's already enough elements
00662     if ( GetSize() >= in_lNewSize )
00663     {
00664         m_lNbUsedElem = in_lNewSize;
00665         m_pVariant->numElems = m_lNbUsedElem * StructSize;
00666 
00667         return m_lNbUsedElem;
00668     }
00669     // we need to allocate some new elements
00670     else
00671     {
00672         // compute new size for the array
00673         SI_Long l_lNewArraySize = in_lNewSize * in_lExpandRatio;
00674         
00675         // allocate new array
00676         CElemType * l_pNewArray = (CElemType *) FTK_calloc( sizeof( CSubElemType), l_lNewArraySize * StructSize );
00677                 
00678         if (l_pNewArray) 
00679         {
00680             // copy exisiting array data into new array
00681             CElemType *l_pCurrentArray = (CElemType*)m_pVariant->p_voidVal;
00682             register SI_Long i;
00683 
00684             for ( i = 0; i < GetUsed(); i++)
00685             {
00686                 l_pNewArray[i] = l_pCurrentArray[i];
00687             }
00688             for ( i = GetUsed(); i< l_lNewArraySize; i++)
00689             {
00690                 ::new((void*)&l_pNewArray[i]) CElemType;
00691             }
00692 
00693             //Delete original array
00694             for ( i = 0; i < GetUsed(); i++)
00695             {
00696                 l_pCurrentArray[i].~CElemType();
00697             }
00698             // flush the old array and replace it with the new one
00699             FTK_free((void *) l_pCurrentArray );
00700 
00701             m_pVariant->p_voidVal = l_pNewArray;
00702 
00703             // set the total number of raw elements in the variant
00704             m_pVariant->numElems = in_lNewSize * StructSize;
00705 
00706             // set allocated size to the size of the new array
00707             m_lNbAllocElem = l_lNewArraySize;
00708             
00709             return m_lNbUsedElem = in_lNewSize;
00710         }
00711     }
00712 
00713     // expand not required or memory allocation failed
00714     return m_lNbUsedElem;
00715 }
00716 
00717 template <class CElemType, class CSubElemType, SI_Int StructSize>
00718 inline SI_Long CSLArrayProxy<CElemType, CSubElemType, StructSize>::Add
00719 (
00720     CElemType in_Elem
00721 )
00722 {
00723     Extend(1);
00724     (*this)[m_lNbUsedElem - 1] = in_Elem;
00725     return m_lNbUsedElem;    
00726 }
00727 
00728 #if defined(_WIN32) || defined(_WIN32_WCE) || defined(_XBOX)
00729 #pragma pack(pop)
00730 #elif defined (CODEWARRIOR)
00731 #pragma options align= reset
00732 #endif
00733 
00734 #endif // __SL_ARRAY_H__