SL_Array.h

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