//========= Copyright Valve Corporation, All rights reserved. ============// // // The copyright to the contents herein is the property of Valve, L.L.C. // The contents may be used and/or copied only with the written permission of // Valve, L.L.C., or in accordance with the terms and conditions stipulated in // the agreement/contract under which the contents have been supplied. // //***************************************************************************** // // Contents: // // CSimpleBitString // // Authors: chrisn // // Target restrictions: // // Tool restrictions: // // Things to do: // //***************************************************************************** //***************************************************************************** // // Include files required to build and use this module. // //***************************************************************************** // Precompiled header (must come first - includes project common headers) //#include "stdafx.h" #include "tier0/platform.h" #include "tier1/utlvector.h" #include "simplebitstring.h" //***************************************************************************** // // Class definitions: // //***************************************************************************** // // class CSimpleBitString::iterator // //----------------------------------------------------------------------------- // // Function: // //----------------------------------------------------------------------------- void CSimpleBitString::AppendBits( uint64 u64Data, uint32 NumSignificantLowBitsOfData ) { Assert ( NumSignificantLowBitsOfData <= 64 ); while ( NumSignificantLowBitsOfData > 0 ) { // Clear top bits of data if ( NumSignificantLowBitsOfData < 64 ) u64Data &= ( (1ULL << NumSignificantLowBitsOfData) - 1 ); // will fail for 64 bits uint32 Idx = m_uNumBits / 8; uint32 NumUsedBitsInLastByte = m_uNumBits % 8; uint32 NumAvailableBitsInLastByte = 8 - NumUsedBitsInLastByte; uint32 NumBitsToPutInThisByte = min( NumAvailableBitsInLastByte, NumSignificantLowBitsOfData ); uint8 BitsForThisByte = ( u64Data >> (NumSignificantLowBitsOfData - NumBitsToPutInThisByte) ) & ( (1ULL << NumBitsToPutInThisByte) - 1 ); m_vecU8[Idx] |= ( BitsForThisByte << ( NumAvailableBitsInLastByte - NumBitsToPutInThisByte ) ); m_uNumBits += NumBitsToPutInThisByte; NumAvailableBitsInLastByte -= NumBitsToPutInThisByte; if ( NumAvailableBitsInLastByte == 0 ) { m_vecU8[ m_vecU8.AddToTail() ] = 0x00; } // We've used the top N bits of data NumSignificantLowBitsOfData -= NumBitsToPutInThisByte; } } //----------------------------------------------------------------------------- // // Function: // //----------------------------------------------------------------------------- void CSimpleBitString::AppendBits( const uint8 * pData, uint32 NumBitsOfData ) { Assert( pData ); uint32 NumBytes = NumBitsOfData / 8; for ( uint32 i = 0; i < NumBytes; ++i ) { AppendBits( *(pData++), 8 ); } uint32 NumTailBits = NumBitsOfData % 8; AppendBits( (*pData) >> (8U - NumTailBits), NumTailBits ); } //----------------------------------------------------------------------------- // // Function: // //----------------------------------------------------------------------------- void CSimpleBitString::ReversiblyObfusticateBitsFromStart( uint NumBits, const uint8 * pObfusticationData, size_t uSizeOfObfusticationData ) { Assert( pObfusticationData ); if ( NumBits > m_uNumBits || NumBits > uSizeOfObfusticationData * 8 ) { AssertMsg( false, "ReversiblyObfusticateBitsFromStart(): Bad NumBits" ); return; // bugbug taylor bool return } uint8 * pBits = & m_vecU8[0]; uint NumBytes = NumBits / 8; for ( uint i = 0; i < NumBytes; ++i ) { *(pBits++) ^= *(pObfusticationData++); } uint NumTailBits = NumBits % 8; if ( NumTailBits > 0 ) { *pBits ^= ( *(pObfusticationData++) & (((1U << NumTailBits) - 1) << (8U - NumTailBits) ) ); } } //----------------------------------------------------------------------------- // // Function: // //----------------------------------------------------------------------------- uint8 CSimpleBitString::GetByteChecksumFromStart( uint NumBits ) const { if ( NumBits > m_uNumBits ) { AssertMsg( false, "GenerateByteChecksumFromStart(): Bad NumBits" ); return 0; } uint8 u8Checksum = 0; const uint8 * pBits = & m_vecU8[0]; uint NumBytes = NumBits / 8; for ( uint i = 0; i < NumBytes; ++i ) { u8Checksum += *(pBits++); } uint NumTailBits = NumBits % 8; if ( NumTailBits > 0 ) { u8Checksum += ( *(pBits) & (((1U << NumTailBits) - 1) << (8U - NumTailBits) ) ); } return u8Checksum; } // // class CSimpleBitString::iterator // uint32 CSimpleBitString::iterator::GetNextBits( uint32 NumBitsToGet ) { Assert ( NumBitsToGet <= 32 ); return static_cast( GetNextBits64( NumBitsToGet ) ); } uint64 CSimpleBitString::iterator::GetNextBits64( uint32 NumBitsToGet ) { Assert ( NumBitsToGet <= 64 ); if ( m_uNextBitIdx + NumBitsToGet > m_rSimpleBitString.m_uNumBits ) { AssertMsg( false, "Not enough bits in CSimpleBitString" ); return 0; } uint64 u64Data = 0; while ( NumBitsToGet > 0 ) { uint32 Idx = m_uNextBitIdx / 8; Assert( Idx < (uint32)m_rSimpleBitString.m_vecU8.Count() ); uint32 NumConsumedBitsInThisByte = m_uNextBitIdx % 8; uint32 NumAvailableBitsInThisByte = 8 - NumConsumedBitsInThisByte; uint32 NumBitsToGetFromThisByte = min( NumAvailableBitsInThisByte, NumBitsToGet ); uint8 BitsFromThisByte = ( m_rSimpleBitString.m_vecU8[Idx] >> (NumAvailableBitsInThisByte - NumBitsToGetFromThisByte) ) & ( (1UL << NumBitsToGetFromThisByte) - 1 ); u64Data <<= NumBitsToGetFromThisByte; u64Data |= BitsFromThisByte; m_uNextBitIdx += NumBitsToGetFromThisByte; NumBitsToGet -= NumBitsToGetFromThisByte; } return u64Data; }