# 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__