mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2024-12-23 01:59:43 +08:00
317 lines
6.9 KiB
C++
317 lines
6.9 KiB
C++
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//===========================================================================//
|
|
|
|
#ifndef BITVEC_H
|
|
#define BITVEC_H
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#include "tier0/dbg.h"
|
|
#include "tier0/basetypes.h"
|
|
|
|
|
|
class CBitVecAccessor
|
|
{
|
|
public:
|
|
CBitVecAccessor(unsigned long *pDWords, int iBit);
|
|
|
|
void operator=(int val);
|
|
operator unsigned long();
|
|
|
|
private:
|
|
unsigned long *m_pDWords;
|
|
int m_iBit;
|
|
};
|
|
|
|
|
|
// CBitVec allows you to store a list of bits and do operations on them like they were an atomic type.
|
|
template<int NUM_BITS>
|
|
class CBitVec
|
|
{
|
|
public:
|
|
|
|
CBitVec();
|
|
|
|
// Get a pointer to the raw bits.
|
|
unsigned long* Base();
|
|
|
|
// Set all values to the specified value (0 or 1..)
|
|
void Init(int val = 0);
|
|
|
|
// Access the bits like an array.
|
|
CBitVecAccessor operator[](int i);
|
|
|
|
// Clear or set all bits.
|
|
void ClearAll( int nBits=NUM_BITS );
|
|
void SetAll( int nBits=NUM_BITS );
|
|
|
|
// Get the state of a bit.
|
|
unsigned long Get( unsigned long iBit ) const;
|
|
bool IsBitSet( unsigned long iBit ) const;
|
|
|
|
// Set or clear a bit.
|
|
void Set( unsigned long iBit );
|
|
void Clear( unsigned long iBit );
|
|
|
|
// Set a bit either on or off.
|
|
void Set( unsigned long iBit, int bOn );
|
|
|
|
// Copy the state of another CBitVec.
|
|
void Copy( CBitVec<NUM_BITS> const &other, int nBits=NUM_BITS );
|
|
|
|
// Returns true if the bit vectors have the same values.
|
|
bool Compare( CBitVec<NUM_BITS> const &other, int nBits=NUM_BITS );
|
|
|
|
// Operations on other bit vectors.
|
|
CBitVec& operator=(CBitVec<NUM_BITS> const &other);
|
|
bool operator==(CBitVec<NUM_BITS> const &other);
|
|
bool operator!=(CBitVec<NUM_BITS> const &other);
|
|
|
|
// Get underlying dword representations of the bits.
|
|
int GetNumDWords() const;
|
|
unsigned long GetDWord(int i) const;
|
|
void SetDWord(int i, unsigned long val);
|
|
|
|
int GetNumBits() const;
|
|
|
|
int FindNextSetBit(int iStartBit) const; // returns -1 if no set bit was found
|
|
|
|
private:
|
|
|
|
enum {NUM_DWORDS = NUM_BITS/32 + !!(NUM_BITS & 31)};
|
|
unsigned long m_DWords[NUM_DWORDS];
|
|
};
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------ //
|
|
// CBitVecAccessor inlines.
|
|
// ------------------------------------------------------------------------ //
|
|
|
|
inline CBitVecAccessor::CBitVecAccessor(unsigned long *pDWords, int iBit)
|
|
{
|
|
m_pDWords = pDWords;
|
|
m_iBit = iBit;
|
|
}
|
|
|
|
|
|
inline void CBitVecAccessor::operator=(int val)
|
|
{
|
|
if(val)
|
|
m_pDWords[m_iBit >> 5] |= (1 << (m_iBit & 31));
|
|
else
|
|
m_pDWords[m_iBit >> 5] &= ~(unsigned long)(1 << (m_iBit & 31));
|
|
}
|
|
|
|
inline CBitVecAccessor::operator unsigned long()
|
|
{
|
|
return m_pDWords[m_iBit >> 5] & (1 << (m_iBit & 31));
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------ //
|
|
// CBitVec inlines.
|
|
// ------------------------------------------------------------------------ //
|
|
|
|
template<int NUM_BITS>
|
|
inline int CBitVec<NUM_BITS>::GetNumBits() const
|
|
{
|
|
return NUM_BITS;
|
|
}
|
|
|
|
|
|
template<int NUM_BITS>
|
|
inline CBitVec<NUM_BITS>::CBitVec()
|
|
{
|
|
for(int i=0; i < NUM_DWORDS; i++)
|
|
m_DWords[i] = 0;
|
|
}
|
|
|
|
|
|
template<int NUM_BITS>
|
|
inline void CBitVec<NUM_BITS>::Init(int val)
|
|
{
|
|
unsigned long dwVal = val ? 0xFFFFFFFF : 0;
|
|
for( int i=0; i < NUM_DWORDS; i++ )
|
|
m_DWords[i] = dwVal;
|
|
}
|
|
|
|
|
|
template<int NUM_BITS>
|
|
inline unsigned long* CBitVec<NUM_BITS>::Base()
|
|
{
|
|
return m_DWords;
|
|
}
|
|
|
|
|
|
template<int NUM_BITS>
|
|
inline CBitVec<NUM_BITS>& CBitVec<NUM_BITS>::operator=(CBitVec<NUM_BITS> const &other)
|
|
{
|
|
memcpy(m_DWords, other.m_DWords, sizeof(m_DWords));
|
|
return *this;
|
|
}
|
|
|
|
|
|
template<int NUM_BITS>
|
|
inline CBitVecAccessor CBitVec<NUM_BITS>::operator[](int i)
|
|
{
|
|
Assert(i >= 0 && i < GetNumBits());
|
|
return CBitVecAccessor(m_DWords, i);
|
|
}
|
|
|
|
|
|
template< int SIZE >
|
|
inline void CBitVec<SIZE>::ClearAll( int nBits )
|
|
{
|
|
int nDWords = PAD_NUMBER( nBits, 32 ) >> 5;
|
|
Assert( nDWords <= NUM_DWORDS );
|
|
|
|
for( int i=0; i < nDWords; i++ )
|
|
m_DWords[i] = 0;
|
|
}
|
|
|
|
template< int SIZE >
|
|
inline void CBitVec<SIZE>::SetAll( int nBits )
|
|
{
|
|
int nDWords = PAD_NUMBER( nBits, 32 ) >> 5;
|
|
Assert( nDWords <= NUM_DWORDS );
|
|
|
|
for( int i=0; i < nDWords; i++ )
|
|
m_DWords[i] = 0xFFFFFFFF;
|
|
}
|
|
|
|
template< int SIZE >
|
|
inline unsigned long CBitVec<SIZE>::Get( unsigned long iBit ) const
|
|
{
|
|
Assert( iBit < SIZE );
|
|
return m_DWords[iBit >> 5] & (1 << (iBit & 31));
|
|
}
|
|
|
|
template< int SIZE >
|
|
bool CBitVec<SIZE>::IsBitSet( unsigned long iBit ) const
|
|
{
|
|
return ( m_DWords[iBit >> 5] & (1 << (iBit & 31)) ) != 0;
|
|
}
|
|
|
|
template< int SIZE >
|
|
inline void CBitVec<SIZE>::Set( unsigned long iBit )
|
|
{
|
|
Assert( iBit < SIZE );
|
|
m_DWords[iBit >> 5] |= (1 << (iBit & 31));
|
|
}
|
|
|
|
template< int SIZE >
|
|
inline void CBitVec<SIZE>::Clear( unsigned long iBit )
|
|
{
|
|
Assert( iBit < SIZE );
|
|
m_DWords[iBit >> 5] &= ~(1 << (iBit & 31));
|
|
}
|
|
|
|
template< int SIZE >
|
|
inline void CBitVec<SIZE>::Set( unsigned long iBit, int bOn )
|
|
{
|
|
if( bOn )
|
|
Set( iBit );
|
|
else
|
|
Clear( iBit );
|
|
}
|
|
|
|
template< int SIZE >
|
|
inline void CBitVec<SIZE>::Copy( CBitVec<SIZE> const &other, int nBits )
|
|
{
|
|
int nBytes = PAD_NUMBER( nBits, 8 ) >> 3;
|
|
Assert( nBytes <= NUM_DWORDS*4 );
|
|
memcpy( m_DWords, other.m_DWords, nBytes );
|
|
}
|
|
|
|
|
|
template< int SIZE >
|
|
inline bool CBitVec<SIZE>::Compare( CBitVec<SIZE> const &other, int nBits )
|
|
{
|
|
int nBytes = PAD_NUMBER( nBits, 8 ) >> 3;
|
|
Assert( nBytes <= NUM_DWORDS*4 );
|
|
|
|
return memcmp( m_DWords, other.m_DWords, nBytes ) == 0;
|
|
}
|
|
|
|
|
|
template<int NUM_BITS>
|
|
inline bool CBitVec<NUM_BITS>::operator==(CBitVec<NUM_BITS> const &other)
|
|
{
|
|
for(int i=0; i < NUM_DWORDS; i++)
|
|
if(m_DWords[i] != other.m_DWords[i])
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
template<int NUM_BITS>
|
|
inline bool CBitVec<NUM_BITS>::operator!=(CBitVec<NUM_BITS> const &other)
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
|
|
|
|
template<int NUM_BITS>
|
|
inline int CBitVec<NUM_BITS>::GetNumDWords() const
|
|
{
|
|
return NUM_DWORDS;
|
|
}
|
|
|
|
template<int NUM_BITS>
|
|
inline unsigned long CBitVec<NUM_BITS>::GetDWord(int i) const
|
|
{
|
|
Assert(i >= 0 && i < NUM_DWORDS);
|
|
return m_DWords[i];
|
|
}
|
|
|
|
|
|
template<int NUM_BITS>
|
|
inline void CBitVec<NUM_BITS>::SetDWord(int i, unsigned long val)
|
|
{
|
|
Assert(i >= 0 && i < NUM_DWORDS);
|
|
m_DWords[i] = val;
|
|
}
|
|
|
|
template<int NUM_BITS>
|
|
inline int CBitVec<NUM_BITS>::FindNextSetBit(int iStartBit) const
|
|
{
|
|
int currentBit = iStartBit;
|
|
|
|
while (currentBit < NUM_BITS)
|
|
{
|
|
// Early out for lots of zeros in a row
|
|
// check for 32 bit boundary...
|
|
if ( (currentBit & 31) == 0)
|
|
{
|
|
if (m_DWords[currentBit>>5] == 0)
|
|
{
|
|
currentBit += 32;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// One bit at a time...until we reach next DWord border
|
|
do
|
|
{
|
|
if( m_DWords[currentBit >> 5] & (1 << (currentBit & 31)) )
|
|
return currentBit; // found a set bit
|
|
|
|
++currentBit; // next please
|
|
|
|
} while ( (currentBit & 31) != 0 );
|
|
}
|
|
|
|
return -1; // no bit set in rest of bit array
|
|
}
|
|
|
|
|
|
|
|
#endif // BITVEC_H
|