SL_Array.h

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