xsi_indexset.h
Go to the documentation of this file.
00001 //*****************************************************************************
00011 //*****************************************************************************
00012 
00013 #if (_MSC_VER > 1000) || defined(SGI_COMPILER)
00014 #pragma once
00015 #endif
00016 
00017 #ifndef __XSIINDEXSET_H__
00018 #define __XSIINDEXSET_H__
00019 
00020 #include <sicppsdk.h>
00021 #include <xsi_icenodecontext.h>
00022 
00023 namespace XSI {
00024 
00025 static const char kRevLogTable256[] =
00026 {
00027   8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00028   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00029   5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00030   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00031   6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00032   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00033   5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00034   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00035   7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00036   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00037   5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00038   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00039   6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00040   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00041   5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00042   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
00043 };
00044 
00045 const LONG kBitShift= 5;
00046 const LONG kBitSize = 32;
00047 
00048 class CBitsetHelper
00049 {
00050     public:
00051     SICPPSDK_INLINE CBitsetHelper( );
00052 
00053     SICPPSDK_INLINE LONG& GetCountRef( );
00054     SICPPSDK_INLINE LONG GetCount( ) const;
00055     SICPPSDK_INLINE ULONG*& GetArrayRef();
00056 
00057     SICPPSDK_INLINE bool GetNextBit( LONG& in_index) const;
00058     SICPPSDK_INLINE CStatus SetBit( LONG in_index, bool in_bVal );
00059     SICPPSDK_INLINE bool GetBit( LONG in_index ) const;
00060     SICPPSDK_INLINE void Clear( );
00061 
00062     SICPPSDK_INLINE CBitsetHelper& operator = ( const CBitsetHelper& in_bitset );
00063 
00064 private:
00065     SICPPSDK_INLINE LONG GetNextBitInternal(LONG& in_index) const;
00066     SICPPSDK_INLINE LONG GetFirstBit( ULONG in_nVal) const;
00067     SICPPSDK_INLINE LONG GetRevLogBase2( ULONG in_nVal ) const;
00068     SICPPSDK_INLINE CStatus SetBit( LONG in_index );
00069     SICPPSDK_INLINE CStatus ClearBit( LONG in_index );
00070 
00071     LONG    m_nCount;
00072     ULONG*  m_pArray;
00073 };
00074 
00075 //*****************************************************************************
00120 //*****************************************************************************
00121 
00122 class CIndexSet
00123 {
00124 public:
00125     typedef CIndexSet* PtrType;
00126 
00127     enum StorageMode
00128     {
00129         Range,
00130         Bitset,
00131         Indices,
00132         Unknown
00133     };
00134 
00135     //*****************************************************************************
00143     //*****************************************************************************
00144     class Iterator
00145     {
00146         public:
00147         friend class CIndexSet;
00148 
00153         SICPPSDK_INLINE void Remove();
00154 
00158         SICPPSDK_INLINE bool HasNext() const;
00159 
00163         SICPPSDK_INLINE ULONG GetIndex() const;
00164 
00168         SICPPSDK_INLINE ULONG GetAbsoluteIndex() const;
00169 
00172         SICPPSDK_INLINE void Next();
00173 
00177         SICPPSDK_INLINE operator ULONG () const;
00178 
00179         private:
00180         SICPPSDK_INLINE Iterator( PtrType in_pSet );
00181 
00182         bool    m_bEnd;
00183         LONG    m_nPos;
00184         PtrType m_pSet;
00185     };
00186 
00187     friend class ICENodeContext;
00188     friend class Iterator;
00189 
00193     SICPPSDK_INLINE CIndexSet( const ICENodeContext& in_ctxt );
00194 
00203     SICPPSDK_INLINE CIndexSet( const ICENodeContext& in_ctxt, ULONG in_nInputPortID, ULONG in_nInstanceIndex=0 ) ;
00204 
00207     SICPPSDK_INLINE ~CIndexSet();
00208 
00212     SICPPSDK_INLINE Iterator Begin();
00213 
00216     SICPPSDK_INLINE ULONG GetFilteredCount() const;
00217 
00218     protected:
00219     SICPPSDK_INLINE void            RemoveElement( Iterator& io_it );
00220     SICPPSDK_INLINE bool            GetNextBit(LONG& in_it) const;
00221     SICPPSDK_INLINE ULONG*&         GetDataRef();
00222     SICPPSDK_INLINE ULONG&          GetIndexOffsetRef();
00223     SICPPSDK_INLINE void*&          GetHandleRef();
00224     SICPPSDK_INLINE ULONG&          GetCountRef();
00225     SICPPSDK_INLINE StorageMode&    GetStorageModeRef();
00226     SICPPSDK_INLINE ICENodeContext& GetContextRef();
00227     SICPPSDK_INLINE CBitsetHelper&  GetBitsetRef();
00228 
00229     ULONG*          m_pData;
00230     ULONG           m_nIndexOffset;
00231     void*           m_pHandle;
00232     ULONG           m_nCount;
00233     StorageMode     m_eStorageMode;
00234     ICENodeContext  m_ctxt;
00235     CBitsetHelper   m_bitset;
00236 };
00237 
00238 SICPPSDK_INLINE CIndexSet::CIndexSet( const ICENodeContext& in_ctxt )
00239 {
00240     m_ctxt = in_ctxt;
00241     m_eStorageMode = Unknown;
00242     m_nIndexOffset = 0;
00243     m_pHandle = NULL;
00244     m_pData = NULL;
00245     m_nCount = 0;
00246     m_pData = NULL;
00247 
00248     m_ctxt.AcquireIndexSet( *this );    
00249 }
00250 
00251 SICPPSDK_INLINE CIndexSet::CIndexSet( const ICENodeContext& in_ctxt, ULONG in_nInputPortID, ULONG in_nInstanceIndex )   
00252 {
00253     m_ctxt = in_ctxt;
00254     m_eStorageMode = Unknown;
00255     m_nIndexOffset = 0;
00256     m_pHandle = NULL;
00257     m_pData = NULL;
00258     m_nCount = 0;
00259     m_pData = NULL;
00260     
00261     m_ctxt.AcquireIndexSetFromPort( *this, in_nInputPortID, in_nInstanceIndex );
00262 }
00263 
00264 SICPPSDK_INLINE CIndexSet::~CIndexSet()
00265 {
00266     m_ctxt.ReleaseIndexSet( *this );
00267 }
00268 
00269 SICPPSDK_INLINE CIndexSet::Iterator CIndexSet::Begin()
00270 {
00271     return CIndexSet::Iterator((PtrType)this);
00272 }
00273 
00274 SICPPSDK_INLINE ULONG CIndexSet::GetFilteredCount() const
00275 {
00276     ULONG l_ulCount = 0;
00277     m_ctxt.GetFilteredCountFromIndexSet( *this, l_ulCount );
00278 
00279     return l_ulCount;
00280 }
00281 
00282 SICPPSDK_INLINE void CIndexSet::RemoveElement( CIndexSet::Iterator& io_it )
00283 {
00284     m_ctxt.RemoveElementFromIndexSet( *this, io_it.m_nPos, io_it.m_nPos, io_it.m_bEnd );
00285 }
00286 
00287 SICPPSDK_INLINE bool CIndexSet::GetNextBit(LONG& in_it) const
00288 {
00289     if ( m_eStorageMode != Bitset )
00290     {
00291         assert(false);
00292         return false;
00293     }
00294 
00295     return m_bitset.GetNextBit( in_it );
00296 }
00297 
00298 SICPPSDK_INLINE ULONG*& CIndexSet::GetDataRef()
00299 {
00300     return m_pData;
00301 }
00302 
00303 SICPPSDK_INLINE ULONG& CIndexSet::GetIndexOffsetRef()
00304 {
00305     return m_nIndexOffset;
00306 }
00307 
00308 SICPPSDK_INLINE void*& CIndexSet::GetHandleRef()
00309 {
00310     return m_pHandle;
00311 }
00312 
00313 SICPPSDK_INLINE ULONG& CIndexSet::GetCountRef()
00314 {
00315     return m_nCount;
00316 }
00317 
00318 SICPPSDK_INLINE CIndexSet::StorageMode& CIndexSet::GetStorageModeRef()
00319 {
00320     return m_eStorageMode;
00321 }
00322 
00323 SICPPSDK_INLINE ICENodeContext& CIndexSet::GetContextRef()
00324 {
00325     return m_ctxt;
00326 }
00327 
00328 SICPPSDK_INLINE CBitsetHelper& CIndexSet::GetBitsetRef()
00329 {
00330     return m_bitset;
00331 }
00332 
00333 SICPPSDK_INLINE CIndexSet::Iterator::Iterator( CIndexSet::PtrType in_pSet ) : 
00334     m_bEnd(false),
00335     m_nPos(-1), 
00336     m_pSet(in_pSet)
00337 {
00338     Next();
00339 }
00340 
00341 // Goto next element
00342 SICPPSDK_INLINE void CIndexSet::Iterator::Next()
00343 {
00344     switch(m_pSet->m_eStorageMode)
00345     {
00346         case Range:
00347             m_bEnd = (ULONG)(++m_nPos) == m_pSet->m_nCount;
00348             break;
00349         case Bitset:
00350             m_bEnd = !m_pSet->GetNextBit(m_nPos);
00351             break;
00352         case Indices:
00353             while(true)
00354             {
00355                 ++m_nPos;
00356                 if ((ULONG)m_nPos == m_pSet->m_nCount)
00357                 {
00358                     m_bEnd = true;
00359                     break;
00360                 }
00361 
00362                 if(m_pSet->m_pData[m_nPos] != UINT_MAX)
00363                 {
00364                     break;
00365                 }
00366             }
00367             break;
00368         default:
00369             break;
00370     };
00371 }
00372 
00373 SICPPSDK_INLINE ULONG CIndexSet::Iterator::GetIndex() const
00374 {
00375     switch(m_pSet->m_eStorageMode)
00376     {
00377         case Indices:
00378             return m_pSet->m_pData[m_nPos];
00379         default:
00380             return m_nPos;
00381     }
00382 }
00383 
00384 SICPPSDK_INLINE ULONG CIndexSet::Iterator::GetAbsoluteIndex() const
00385 {
00386     return GetIndex() + m_pSet->m_nIndexOffset;
00387 }
00388 
00389 SICPPSDK_INLINE CIndexSet::Iterator::operator ULONG () const
00390 {
00391     return GetIndex( );
00392 }
00393 
00394 SICPPSDK_INLINE bool CIndexSet::Iterator::HasNext() const
00395 {
00396     return m_bEnd == false && m_pSet->m_nCount > 0;
00397 }
00398 
00399 SICPPSDK_INLINE void CIndexSet::Iterator::Remove()
00400 {
00401     if (m_bEnd )
00402     {
00403         return;
00404     }
00405 
00406     m_pSet->RemoveElement( *this );
00407 }
00408 
00409 // CBitsetHelper
00410 SICPPSDK_INLINE CBitsetHelper::CBitsetHelper( ) : m_nCount(UINT_MAX), m_pArray(NULL) {}
00411 
00412 SICPPSDK_INLINE void CBitsetHelper::Clear( )
00413 {
00414     m_nCount = 0;
00415     m_pArray = 0;
00416 }
00417 
00418 SICPPSDK_INLINE CBitsetHelper& CBitsetHelper::operator = ( const CBitsetHelper& in_bitset )
00419 {
00420     m_nCount = in_bitset.m_nCount;
00421     m_pArray = in_bitset.m_pArray;
00422     return *this;
00423 }
00424 
00425 SICPPSDK_INLINE LONG& CBitsetHelper::GetCountRef( )
00426 {
00427     return m_nCount;
00428 }
00429 
00430 SICPPSDK_INLINE LONG CBitsetHelper::GetCount( ) const
00431 {
00432     return m_nCount;
00433 }
00434 
00435 SICPPSDK_INLINE ULONG*& CBitsetHelper::GetArrayRef()
00436 {
00437     return m_pArray;
00438 }
00439 
00440 SICPPSDK_INLINE bool CBitsetHelper::GetNextBit( LONG& in_it ) const
00441 {
00442     return ( in_it = GetNextBitInternal( in_it ) ) != m_nCount;
00443 }
00444 
00445 SICPPSDK_INLINE bool CBitsetHelper::GetBit( LONG in_index ) const
00446 {
00447     if ( !m_pArray )
00448     {
00449         return false;
00450     }
00451 
00452     return ( m_pArray[ in_index >> kBitShift ] & ( 1 << ( in_index % kBitSize ) ) ) != 0;
00453 }
00454 
00455 SICPPSDK_INLINE CStatus CBitsetHelper::SetBit( LONG in_index, bool in_bVal )
00456 {
00457     if ( in_bVal )
00458     {
00459         SetBit( in_index );
00460     }
00461     else
00462     {
00463         ClearBit( in_index );
00464     }
00465     return CStatus::OK;
00466 }
00467 
00468 SICPPSDK_INLINE CStatus CBitsetHelper::SetBit( LONG in_index )
00469 {
00470     if ( !m_pArray )
00471     {
00472         return CStatus::AccessDenied;
00473     }
00474     
00475     m_pArray[ in_index >> kBitShift ] |= ( 1 << ( in_index % kBitSize ) );
00476     return CStatus::OK;
00477 }
00478 
00479 SICPPSDK_INLINE CStatus CBitsetHelper::ClearBit( LONG in_index )
00480 {
00481     if ( !m_pArray )
00482     {
00483         return CStatus::AccessDenied;
00484     }
00485 
00486     m_pArray[ in_index >> kBitShift ] &= ~( 1 << ( in_index % kBitSize ) );
00487     return CStatus::OK;
00488 }
00489 
00490 SICPPSDK_INLINE LONG CBitsetHelper::GetNextBitInternal( LONG& in_index ) const
00491 {
00492     LONG nCurrentBit = in_index+1;
00493     if (nCurrentBit >= m_nCount)
00494     {
00495         return m_nCount;
00496     }
00497 
00498     LONG nCurrentIdx = nCurrentBit >> kBitShift;
00499 
00500     ULONG nVal = m_pArray[nCurrentIdx];
00501     nVal >>= (nCurrentBit - (nCurrentIdx << kBitShift));
00502 
00503     LONG nDeltaBit;
00504     if ((nDeltaBit = GetFirstBit(nVal)) == 32)
00505     {
00506         LONG nMaxIdx = ((m_nCount-1)>>kBitShift)+1;
00507 
00508         for( nCurrentIdx++; nCurrentIdx != nMaxIdx; nCurrentIdx++ )
00509         {
00510             nDeltaBit = GetFirstBit(m_pArray[nCurrentIdx]);
00511 
00512             if(nDeltaBit != 32)
00513             {
00514                 break;
00515             }
00516         }
00517 
00518         if( nCurrentIdx == nMaxIdx )
00519         {
00520             return m_nCount;
00521         }
00522         else
00523         {
00524             nCurrentBit = ( nCurrentIdx << kBitShift ) + nDeltaBit;
00525         }
00526     }
00527     else
00528     {
00529         nCurrentBit += nDeltaBit;
00530     }
00531 
00532     if( nCurrentBit > m_nCount )
00533     {
00534         return m_nCount;
00535     }
00536 
00537     return nCurrentBit;
00538 }
00539 
00540 SICPPSDK_INLINE LONG CBitsetHelper::GetFirstBit( ULONG in_nVal ) const
00541 {
00542     return GetRevLogBase2( in_nVal );
00543 }
00544 
00545 SICPPSDK_INLINE LONG CBitsetHelper::GetRevLogBase2( ULONG in_nVal ) const
00546 {
00547     register unsigned int t, tt; // temporaries
00548 
00549     if ( tt = in_nVal & 0xFFFF, tt != 0 )
00550     {
00551       return (t = in_nVal & 0xFF, t != 0 ) ? kRevLogTable256[t] : 8 + kRevLogTable256[tt >> 8];
00552     }
00553     else
00554     {
00555       return (t = in_nVal & 0x00FF0000, t != 0 ) ? 16 + kRevLogTable256[t >> 16] : 24 + kRevLogTable256[in_nVal >> 24];
00556     }
00557 }
00558 
00559 };
00560 
00561 #endif // __XSIINDEXSET_H__