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 
00197     SICPPSDK_INLINE ~CIndexSet();
00198 
00202     SICPPSDK_INLINE Iterator Begin();
00203 
00204     protected:
00205     SICPPSDK_INLINE void            RemoveElement( Iterator& io_it );
00206     SICPPSDK_INLINE bool            GetNextBit(LONG& in_it) const;
00207     SICPPSDK_INLINE ULONG*&         GetDataRef();
00208     SICPPSDK_INLINE ULONG&          GetIndexOffsetRef();
00209     SICPPSDK_INLINE void*&          GetHandleRef();
00210     SICPPSDK_INLINE ULONG&          GetCountRef();
00211     SICPPSDK_INLINE StorageMode&    GetStorageModeRef();
00212     SICPPSDK_INLINE ICENodeContext& GetContextRef();
00213     SICPPSDK_INLINE CBitsetHelper&  GetBitsetRef();
00214 
00215     ULONG*          m_pData;
00216     ULONG           m_nIndexOffset;
00217     void*           m_pHandle;
00218     ULONG           m_nCount;
00219     StorageMode     m_eStorageMode;
00220     ICENodeContext  m_ctxt;
00221     CBitsetHelper   m_bitset;
00222 };
00223 
00224 SICPPSDK_INLINE CIndexSet::CIndexSet( const ICENodeContext& in_ctxt )
00225 {
00226     m_ctxt = in_ctxt;
00227     m_eStorageMode = Unknown;
00228     m_nIndexOffset = 0;
00229     m_pHandle = NULL;
00230     m_pData = NULL;
00231     m_nCount = 0;
00232     m_pData = NULL;
00233 }
00234 
00235 SICPPSDK_INLINE CIndexSet::~CIndexSet()
00236 {
00237     m_ctxt.ReleaseIndexSet( *this );
00238 }
00239 
00240 SICPPSDK_INLINE CIndexSet::Iterator CIndexSet::Begin()
00241 {
00242     m_ctxt.AcquireIndexSet( *this );
00243     return CIndexSet::Iterator((PtrType)this);
00244 }
00245 
00246 SICPPSDK_INLINE void CIndexSet::RemoveElement( CIndexSet::Iterator& io_it )
00247 {
00248     m_ctxt.RemoveElementFromIndexSet( *this, io_it.m_nPos, io_it.m_nPos, io_it.m_bEnd );
00249 }
00250 
00251 SICPPSDK_INLINE bool CIndexSet::GetNextBit(LONG& in_it) const
00252 {
00253     if ( m_eStorageMode != Bitset )
00254     {
00255         assert(false);
00256         return false;
00257     }
00258 
00259     return m_bitset.GetNextBit( in_it );
00260 }
00261 
00262 SICPPSDK_INLINE ULONG*& CIndexSet::GetDataRef()
00263 {
00264     return m_pData;
00265 }
00266 
00267 SICPPSDK_INLINE ULONG& CIndexSet::GetIndexOffsetRef()
00268 {
00269     return m_nIndexOffset;
00270 }
00271 
00272 SICPPSDK_INLINE void*& CIndexSet::GetHandleRef()
00273 {
00274     return m_pHandle;
00275 }
00276 
00277 SICPPSDK_INLINE ULONG& CIndexSet::GetCountRef()
00278 {
00279     return m_nCount;
00280 }
00281 
00282 SICPPSDK_INLINE CIndexSet::StorageMode& CIndexSet::GetStorageModeRef()
00283 {
00284     return m_eStorageMode;
00285 }
00286 
00287 SICPPSDK_INLINE ICENodeContext& CIndexSet::GetContextRef()
00288 {
00289     return m_ctxt;
00290 }
00291 
00292 SICPPSDK_INLINE CBitsetHelper& CIndexSet::GetBitsetRef()
00293 {
00294     return m_bitset;
00295 }
00296 
00297 SICPPSDK_INLINE CIndexSet::Iterator::Iterator( CIndexSet::PtrType in_pSet ) : m_pSet(in_pSet), m_nPos(0), m_bEnd(false)
00298 {
00299 }
00300 
00301 // Goto next element
00302 SICPPSDK_INLINE void CIndexSet::Iterator::Next()
00303 {
00304     switch(m_pSet->m_eStorageMode)
00305     {
00306         case Range:
00307             m_bEnd = (ULONG)(++m_nPos) == m_pSet->m_nCount;
00308             break;
00309         case Bitset:
00310             m_bEnd = !m_pSet->GetNextBit(m_nPos);
00311             break;
00312         case Indices:
00313             while(true)
00314             {
00315                 ++m_nPos;
00316                 if (m_nPos == m_pSet->m_nCount)
00317                 {
00318                     m_bEnd = true;
00319                     break;
00320                 }
00321 
00322                 if(m_pSet->m_pData[m_nPos] != UINT_MAX)
00323                 {
00324                     break;
00325                 }
00326             }
00327         break;
00328     };
00329 }
00330 
00331 SICPPSDK_INLINE ULONG CIndexSet::Iterator::GetIndex() const
00332 {
00333     switch(m_pSet->m_eStorageMode)
00334     {
00335         case Indices:
00336             return m_pSet->m_pData[m_nPos];
00337         default:
00338             return m_nPos;
00339     }
00340 }
00341 
00342 SICPPSDK_INLINE ULONG CIndexSet::Iterator::GetAbsoluteIndex() const
00343 {
00344     return GetIndex() + m_pSet->m_nIndexOffset;
00345 }
00346 
00347 SICPPSDK_INLINE CIndexSet::Iterator::operator ULONG () const
00348 {
00349     return GetIndex( );
00350 }
00351 
00352 SICPPSDK_INLINE bool CIndexSet::Iterator::HasNext() const
00353 {
00354     return m_bEnd == false && m_pSet->m_nCount > 0;
00355 }
00356 
00357 SICPPSDK_INLINE void CIndexSet::Iterator::Remove()
00358 {
00359     if (m_bEnd )
00360     {
00361         return;
00362     }
00363 
00364     m_pSet->RemoveElement( *this );
00365 }
00366 
00367 // CBitsetHelper
00368 SICPPSDK_INLINE CBitsetHelper::CBitsetHelper( ) : m_nCount(UINT_MAX), m_pArray(NULL) {}
00369 
00370 SICPPSDK_INLINE void CBitsetHelper::Clear( )
00371 {
00372     m_nCount = 0;
00373     m_pArray = 0;
00374 }
00375 
00376 SICPPSDK_INLINE CBitsetHelper& CBitsetHelper::operator = ( const CBitsetHelper& in_bitset )
00377 {
00378     m_nCount = in_bitset.m_nCount;
00379     m_pArray = in_bitset.m_pArray;
00380     return *this;
00381 }
00382 
00383 SICPPSDK_INLINE LONG& CBitsetHelper::GetCountRef( )
00384 {
00385     return m_nCount;
00386 }
00387 
00388 SICPPSDK_INLINE LONG CBitsetHelper::GetCount( ) const
00389 {
00390     return m_nCount;
00391 }
00392 
00393 SICPPSDK_INLINE ULONG*& CBitsetHelper::GetArrayRef()
00394 {
00395     return m_pArray;
00396 }
00397 
00398 SICPPSDK_INLINE bool CBitsetHelper::GetNextBit( LONG& in_it ) const
00399 {
00400     return ( in_it = GetNextBitInternal( in_it ) ) != m_nCount;
00401 }
00402 
00403 SICPPSDK_INLINE bool CBitsetHelper::GetBit( LONG in_index ) const
00404 {
00405     if ( in_index >= (LONG)m_nCount )
00406     {
00407         assert( false );
00408         return false;
00409     }
00410 
00411     return ( m_pArray[ in_index >> kBitShift ] & ( 1 << ( in_index % kBitSize ) ) ) != 0;
00412 }
00413 
00414 SICPPSDK_INLINE CStatus CBitsetHelper::SetBit( LONG in_index, bool in_bVal )
00415 {
00416     if ( in_bVal )
00417     {
00418         SetBit( in_index );
00419     }
00420     else
00421     {
00422         ClearBit( in_index );
00423     }
00424     return CStatus::OK;
00425 }
00426 
00427 SICPPSDK_INLINE CStatus CBitsetHelper::SetBit( LONG in_index )
00428 {
00429     assert ( in_index < m_nCount );
00430     m_pArray[ in_index >> kBitShift ] |= ( 1 << ( in_index % kBitSize ) );
00431     return CStatus::OK;
00432 }
00433 
00434 SICPPSDK_INLINE CStatus CBitsetHelper::ClearBit( LONG in_index )
00435 {
00436     assert ( in_index < m_nCount );
00437     m_pArray[ in_index >> kBitShift ] &= ~( 1 << ( in_index % kBitSize ) );
00438     return CStatus::OK;
00439 }
00440 
00441 SICPPSDK_INLINE LONG CBitsetHelper::GetNextBitInternal( LONG& in_index ) const
00442 {
00443     LONG nCurrentBit = in_index+1;
00444     if (nCurrentBit >= m_nCount)
00445     {
00446         return m_nCount;
00447     }
00448 
00449     LONG nCurrentIdx = nCurrentBit >> kBitShift;
00450 
00451     ULONG nVal = m_pArray[nCurrentIdx];
00452     nVal >>= (nCurrentBit - (nCurrentIdx << kBitShift));
00453 
00454     LONG nDeltaBit;
00455     if ((nDeltaBit = GetFirstBit(nVal)) == 32)
00456     {
00457         LONG nMaxIdx = ((m_nCount-1)>>kBitShift)+1;
00458 
00459         for( nCurrentIdx++; nCurrentIdx != nMaxIdx; nCurrentIdx++ )
00460         {
00461             nDeltaBit = GetFirstBit(m_pArray[nCurrentIdx]);
00462 
00463             if(nDeltaBit != 32)
00464             {
00465                 break;
00466             }
00467         }
00468 
00469         if( nCurrentIdx == nMaxIdx )
00470         {
00471             return m_nCount;
00472         }
00473         else
00474         {
00475             nCurrentBit = ( nCurrentIdx << kBitShift ) + nDeltaBit;
00476         }
00477     }
00478     else
00479     {
00480         nCurrentBit += nDeltaBit;
00481     }
00482 
00483     if( nCurrentBit > m_nCount )
00484     {
00485         return m_nCount;
00486     }
00487 
00488     return nCurrentBit;
00489 }
00490 
00491 SICPPSDK_INLINE LONG CBitsetHelper::GetFirstBit( ULONG in_nVal ) const
00492 {
00493     return GetRevLogBase2( in_nVal );
00494 }
00495 
00496 SICPPSDK_INLINE LONG CBitsetHelper::GetRevLogBase2( ULONG in_nVal ) const
00497 {
00498     register unsigned int t, tt; // temporaries
00499 
00500     if ( tt = in_nVal & 0xFFFF, tt != 0 )
00501     {
00502       return (t = in_nVal & 0xFF, t != 0 ) ? kRevLogTable256[t] : 8 + kRevLogTable256[tt >> 8];
00503     }
00504     else
00505     {
00506       return (t = in_nVal & 0x00FF0000, t != 0 ) ? 16 + kRevLogTable256[t >> 16] : 24 + kRevLogTable256[in_nVal >> 24];
00507     }
00508 }
00509 
00510 };
00511 
00512 #endif // __XSIINDEXSET_H__