Fixed bitbuf compilation
This commit is contained in:
1487
external/sourcesdk/bitbuf.cpp
vendored
Normal file
1487
external/sourcesdk/bitbuf.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
794
external/sourcesdk/bitbuf.h
vendored
Normal file
794
external/sourcesdk/bitbuf.h
vendored
Normal file
@ -0,0 +1,794 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
// NOTE: bf_read is guaranteed to return zeros if it overflows.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "valve_support.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Forward declarations.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class Vector;
|
||||
class QAngle;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// You can define a handler function that will be called in case of
|
||||
// out-of-range values and overruns here.
|
||||
//
|
||||
// NOTE: the handler is only called in debug mode.
|
||||
//
|
||||
// Call SetBitBufErrorHandler to install a handler.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BITBUFERROR_VALUE_OUT_OF_RANGE=0, // Tried to write a value with too few bits.
|
||||
BITBUFERROR_BUFFER_OVERRUN, // Was about to overrun a buffer.
|
||||
|
||||
BITBUFERROR_NUM_ERRORS
|
||||
} BitBufErrorType;
|
||||
|
||||
|
||||
typedef void (*BitBufErrorHandler)( BitBufErrorType errorType, const char *pDebugName );
|
||||
|
||||
|
||||
#if defined( _DEBUG )
|
||||
extern void InternalBitBufErrorHandler( BitBufErrorType errorType, const char *pDebugName );
|
||||
#define CallErrorHandler( errorType, pDebugName ) InternalBitBufErrorHandler( errorType, pDebugName );
|
||||
#else
|
||||
#define CallErrorHandler( errorType, pDebugName )
|
||||
#endif
|
||||
|
||||
|
||||
// Use this to install the error handler. Call with NULL to uninstall your error handler.
|
||||
void SetBitBufErrorHandler( BitBufErrorHandler fn );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline int BitByte( int bits )
|
||||
{
|
||||
// return PAD_NUMBER( bits, 8 ) >> 3;
|
||||
return (bits + 7) >> 3;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// namespaced helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace bitbuf
|
||||
{
|
||||
// ZigZag Transform: Encodes signed integers so that they can be
|
||||
// effectively used with varint encoding.
|
||||
//
|
||||
// varint operates on unsigned integers, encoding smaller numbers into
|
||||
// fewer bytes. If you try to use it on a signed integer, it will treat
|
||||
// this number as a very large unsigned integer, which means that even
|
||||
// small signed numbers like -1 will take the maximum number of bytes
|
||||
// (10) to encode. ZigZagEncode() maps signed integers to unsigned
|
||||
// in such a way that those with a small absolute value will have smaller
|
||||
// encoded values, making them appropriate for encoding using varint.
|
||||
//
|
||||
// int32 -> uint32
|
||||
// -------------------------
|
||||
// 0 -> 0
|
||||
// -1 -> 1
|
||||
// 1 -> 2
|
||||
// -2 -> 3
|
||||
// ... -> ...
|
||||
// 2147483647 -> 4294967294
|
||||
// -2147483648 -> 4294967295
|
||||
//
|
||||
// >> encode >>
|
||||
// << decode <<
|
||||
|
||||
inline uint32 ZigZagEncode32(int32 n)
|
||||
{
|
||||
// Note: the right-shift must be arithmetic
|
||||
return(n << 1) ^ (n >> 31);
|
||||
}
|
||||
|
||||
inline int32 ZigZagDecode32(uint32 n)
|
||||
{
|
||||
return(n >> 1) ^ -static_cast<int32>(n & 1);
|
||||
}
|
||||
|
||||
inline uint64 ZigZagEncode64(int64 n)
|
||||
{
|
||||
// Note: the right-shift must be arithmetic
|
||||
return(n << 1) ^ (n >> 63);
|
||||
}
|
||||
|
||||
inline int64 ZigZagDecode64(uint64 n)
|
||||
{
|
||||
return(n >> 1) ^ -static_cast<int64>(n & 1);
|
||||
}
|
||||
|
||||
const int kMaxVarintBytes = 10;
|
||||
const int kMaxVarint32Bytes = 5;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Used for serialization
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class bf_write
|
||||
{
|
||||
public:
|
||||
bf_write();
|
||||
|
||||
// nMaxBits can be used as the number of bits in the buffer.
|
||||
// It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
|
||||
bf_write( void *pData, int nBytes, int nMaxBits = -1 );
|
||||
bf_write( const char *pDebugName, void *pData, int nBytes, int nMaxBits = -1 );
|
||||
|
||||
// Start writing to the specified buffer.
|
||||
// nMaxBits can be used as the number of bits in the buffer.
|
||||
// It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
|
||||
void StartWriting( void *pData, int nBytes, int iStartBit = 0, int nMaxBits = -1 );
|
||||
|
||||
// Restart buffer writing.
|
||||
void Reset();
|
||||
|
||||
// Get the base pointer.
|
||||
unsigned char* GetBasePointer() { return (unsigned char*) m_pData; }
|
||||
|
||||
// Enable or disable assertion on overflow. 99% of the time, it's a bug that we need to catch,
|
||||
// but there may be the occasional buffer that is allowed to overflow gracefully.
|
||||
void SetAssertOnOverflow( bool bAssert );
|
||||
|
||||
// This can be set to assign a name that gets output if the buffer overflows.
|
||||
const char* GetDebugName();
|
||||
void SetDebugName( const char *pDebugName );
|
||||
|
||||
|
||||
// Seek to a specific position.
|
||||
public:
|
||||
|
||||
void SeekToBit( int bitPos );
|
||||
|
||||
|
||||
// Bit functions.
|
||||
public:
|
||||
|
||||
void WriteOneBit(int nValue);
|
||||
void WriteOneBitNoCheck(int nValue);
|
||||
void WriteOneBitAt( int iBit, int nValue );
|
||||
|
||||
// Write signed or unsigned. Range is only checked in debug.
|
||||
void WriteUBitLong( unsigned int data, int numbits, bool bCheckRange=true );
|
||||
void WriteSBitLong( int data, int numbits );
|
||||
|
||||
// Tell it whether or not the data is unsigned. If it's signed,
|
||||
// cast to unsigned before passing in (it will cast back inside).
|
||||
void WriteBitLong(unsigned int data, int numbits, bool bSigned);
|
||||
|
||||
// Write a list of bits in.
|
||||
bool WriteBits(const void *pIn, int nBits);
|
||||
|
||||
// writes an unsigned integer with variable bit length
|
||||
void WriteUBitVar( unsigned int data );
|
||||
|
||||
// writes a varint encoded integer
|
||||
void WriteVarInt32( uint32 data );
|
||||
void WriteVarInt64( uint64 data );
|
||||
void WriteSignedVarInt32( int32 data );
|
||||
void WriteSignedVarInt64( int64 data );
|
||||
int ByteSizeVarInt32( uint32 data );
|
||||
int ByteSizeVarInt64( uint64 data );
|
||||
int ByteSizeSignedVarInt32( int32 data );
|
||||
int ByteSizeSignedVarInt64( int64 data );
|
||||
|
||||
// Copy the bits straight out of pIn. This seeks pIn forward by nBits.
|
||||
// Returns an error if this buffer or the read buffer overflows.
|
||||
bool WriteBitsFromBuffer( class bf_read *pIn, int nBits );
|
||||
|
||||
void WriteBitAngle( float fAngle, int numbits );
|
||||
void WriteBitCoord (const float f);
|
||||
void WriteBitCoordMP( const float f, bool bIntegral, bool bLowPrecision );
|
||||
void WriteBitFloat(float val);
|
||||
void WriteBitVec3Coord( const Vector& fa );
|
||||
void WriteBitNormal( float f );
|
||||
void WriteBitVec3Normal( const Vector& fa );
|
||||
void WriteBitAngles( const QAngle& fa );
|
||||
|
||||
|
||||
// Byte functions.
|
||||
public:
|
||||
|
||||
void WriteChar(int val);
|
||||
void WriteByte(int val);
|
||||
void WriteShort(int val);
|
||||
void WriteWord(int val);
|
||||
void WriteLong(long val);
|
||||
void WriteLongLong(int64 val);
|
||||
void WriteFloat(float val);
|
||||
bool WriteBytes( const void *pBuf, int nBytes );
|
||||
|
||||
// Returns false if it overflows the buffer.
|
||||
bool WriteString(const char *pStr);
|
||||
|
||||
|
||||
// Status.
|
||||
public:
|
||||
|
||||
// How many bytes are filled in?
|
||||
int GetNumBytesWritten() const;
|
||||
int GetNumBitsWritten() const;
|
||||
int GetMaxNumBits();
|
||||
int GetNumBitsLeft();
|
||||
int GetNumBytesLeft();
|
||||
unsigned char* GetData();
|
||||
const unsigned char* GetData() const;
|
||||
|
||||
// Has the buffer overflowed?
|
||||
bool CheckForOverflow(int nBits);
|
||||
inline bool IsOverflowed() const {return m_bOverflow;}
|
||||
|
||||
void SetOverflowFlag();
|
||||
|
||||
|
||||
public:
|
||||
// The current buffer.
|
||||
unsigned long* __restrict m_pData;
|
||||
int m_nDataBytes;
|
||||
int m_nDataBits;
|
||||
|
||||
// Where we are in the buffer.
|
||||
int m_iCurBit;
|
||||
|
||||
private:
|
||||
|
||||
// Errors?
|
||||
bool m_bOverflow;
|
||||
|
||||
bool m_bAssertOnOverflow;
|
||||
const char *m_pDebugName;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inlined methods
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// How many bytes are filled in?
|
||||
inline int bf_write::GetNumBytesWritten() const
|
||||
{
|
||||
return BitByte(m_iCurBit);
|
||||
}
|
||||
|
||||
inline int bf_write::GetNumBitsWritten() const
|
||||
{
|
||||
return m_iCurBit;
|
||||
}
|
||||
|
||||
inline int bf_write::GetMaxNumBits()
|
||||
{
|
||||
return m_nDataBits;
|
||||
}
|
||||
|
||||
inline int bf_write::GetNumBitsLeft()
|
||||
{
|
||||
return m_nDataBits - m_iCurBit;
|
||||
}
|
||||
|
||||
inline int bf_write::GetNumBytesLeft()
|
||||
{
|
||||
return GetNumBitsLeft() >> 3;
|
||||
}
|
||||
|
||||
inline unsigned char* bf_write::GetData()
|
||||
{
|
||||
return (unsigned char*) m_pData;
|
||||
}
|
||||
|
||||
inline const unsigned char* bf_write::GetData() const
|
||||
{
|
||||
return (unsigned char*) m_pData;
|
||||
}
|
||||
|
||||
inline bool bf_write::CheckForOverflow(int nBits)
|
||||
{
|
||||
if ( m_iCurBit + nBits > m_nDataBits )
|
||||
{
|
||||
SetOverflowFlag();
|
||||
CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
|
||||
}
|
||||
|
||||
return m_bOverflow;
|
||||
}
|
||||
|
||||
inline void bf_write::SetOverflowFlag()
|
||||
{
|
||||
#ifdef DBGFLAG_ASSERT
|
||||
if ( m_bAssertOnOverflow )
|
||||
{
|
||||
Assert( false );
|
||||
}
|
||||
#endif
|
||||
m_bOverflow = true;
|
||||
}
|
||||
|
||||
inline void bf_write::WriteOneBitNoCheck(int nValue)
|
||||
{
|
||||
#if __i386__
|
||||
if(nValue)
|
||||
m_pData[m_iCurBit >> 5] |= 1u << (m_iCurBit & 31);
|
||||
else
|
||||
m_pData[m_iCurBit >> 5] &= ~(1u << (m_iCurBit & 31));
|
||||
#else
|
||||
extern unsigned long g_LittleBits[32];
|
||||
if(nValue)
|
||||
m_pData[m_iCurBit >> 5] |= g_LittleBits[m_iCurBit & 31];
|
||||
else
|
||||
m_pData[m_iCurBit >> 5] &= ~g_LittleBits[m_iCurBit & 31];
|
||||
#endif
|
||||
|
||||
++m_iCurBit;
|
||||
}
|
||||
|
||||
inline void bf_write::WriteOneBit(int nValue)
|
||||
{
|
||||
if( m_iCurBit >= m_nDataBits )
|
||||
{
|
||||
SetOverflowFlag();
|
||||
CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
|
||||
return;
|
||||
}
|
||||
WriteOneBitNoCheck( nValue );
|
||||
}
|
||||
|
||||
|
||||
inline void bf_write::WriteOneBitAt( int iBit, int nValue )
|
||||
{
|
||||
if( iBit >= m_nDataBits )
|
||||
{
|
||||
SetOverflowFlag();
|
||||
CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
|
||||
return;
|
||||
}
|
||||
|
||||
#if __i386__
|
||||
if(nValue)
|
||||
m_pData[iBit >> 5] |= 1u << (iBit & 31);
|
||||
else
|
||||
m_pData[iBit >> 5] &= ~(1u << (iBit & 31));
|
||||
#else
|
||||
extern unsigned long g_LittleBits[32];
|
||||
if(nValue)
|
||||
m_pData[iBit >> 5] |= g_LittleBits[iBit & 31];
|
||||
else
|
||||
m_pData[iBit >> 5] &= ~g_LittleBits[iBit & 31];
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void bf_write::WriteUBitLong( unsigned int curData, int numbits, bool bCheckRange ) __restrict
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
// Make sure it doesn't overflow.
|
||||
if ( bCheckRange && numbits < 32 )
|
||||
{
|
||||
if ( curData >= (unsigned long)(1 << numbits) )
|
||||
{
|
||||
CallErrorHandler( BITBUFERROR_VALUE_OUT_OF_RANGE, GetDebugName() );
|
||||
}
|
||||
}
|
||||
Assert( numbits >= 0 && numbits <= 32 );
|
||||
#endif
|
||||
|
||||
if ( GetNumBitsLeft() < numbits )
|
||||
{
|
||||
m_iCurBit = m_nDataBits;
|
||||
SetOverflowFlag();
|
||||
CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
|
||||
return;
|
||||
}
|
||||
|
||||
int iCurBitMasked = m_iCurBit & 31;
|
||||
int iDWord = m_iCurBit >> 5;
|
||||
m_iCurBit += numbits;
|
||||
|
||||
// Mask in a dword.
|
||||
assert( (iDWord*4 + sizeof(long)) <= (unsigned int)m_nDataBytes );
|
||||
unsigned long * __restrict pOut = &m_pData[iDWord];
|
||||
|
||||
// Rotate data into dword alignment
|
||||
curData = (curData << iCurBitMasked) | (curData >> (32 - iCurBitMasked));
|
||||
|
||||
// Calculate bitmasks for first and second word
|
||||
unsigned int temp = 1 << (numbits-1);
|
||||
unsigned int mask1 = (temp*2-1) << iCurBitMasked;
|
||||
unsigned int mask2 = (temp-1) >> (31 - iCurBitMasked);
|
||||
|
||||
// Only look beyond current word if necessary (avoid access violation)
|
||||
int i = mask2 & 1;
|
||||
unsigned long dword1 = LoadLittleDWord( pOut, 0 );
|
||||
unsigned long dword2 = LoadLittleDWord( pOut, i );
|
||||
|
||||
// Drop bits into place
|
||||
dword1 ^= ( mask1 & ( curData ^ dword1 ) );
|
||||
dword2 ^= ( mask2 & ( curData ^ dword2 ) );
|
||||
|
||||
// Note reversed order of writes so that dword1 wins if mask2 == 0 && i == 0
|
||||
StoreLittleDWord( pOut, i, dword2 );
|
||||
StoreLittleDWord( pOut, 0, dword1 );
|
||||
}
|
||||
|
||||
// writes an unsigned integer with variable bit length
|
||||
inline void bf_write::WriteUBitVar( unsigned int data )
|
||||
{
|
||||
/* Reference:
|
||||
if ( data < 0x10u )
|
||||
WriteUBitLong( 0, 2 ), WriteUBitLong( data, 4 );
|
||||
else if ( data < 0x100u )
|
||||
WriteUBitLong( 1, 2 ), WriteUBitLong( data, 8 );
|
||||
else if ( data < 0x1000u )
|
||||
WriteUBitLong( 2, 2 ), WriteUBitLong( data, 12 );
|
||||
else
|
||||
WriteUBitLong( 3, 2 ), WriteUBitLong( data, 32 );
|
||||
*/
|
||||
// a < b ? -1 : 0 translates into a CMP, SBB instruction pair
|
||||
// with no flow control. should also be branchless on consoles.
|
||||
int n = (data < 0x10u ? -1 : 0) + (data < 0x100u ? -1 : 0) + (data < 0x1000u ? -1 : 0);
|
||||
WriteUBitLong( data*4 + n + 3, 6 + n*4 + 12 );
|
||||
if ( data >= 0x1000u )
|
||||
{
|
||||
WriteUBitLong( data >> 16, 16 );
|
||||
}
|
||||
}
|
||||
|
||||
// write raw IEEE float bits in little endian form
|
||||
inline void bf_write::WriteBitFloat(float val)
|
||||
{
|
||||
long intVal;
|
||||
|
||||
Assert(sizeof(long) == sizeof(float));
|
||||
Assert(sizeof(float) == 4);
|
||||
|
||||
intVal = *((long*)&val);
|
||||
WriteUBitLong( intVal, 32 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This is useful if you just want a buffer to write into on the stack.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<int SIZE>
|
||||
class old_bf_write_static : public bf_write
|
||||
{
|
||||
public:
|
||||
inline old_bf_write_static() : bf_write(m_StaticData, SIZE) {}
|
||||
|
||||
char m_StaticData[SIZE];
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Used for unserialization
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class bf_read
|
||||
{
|
||||
public:
|
||||
bf_read();
|
||||
|
||||
// nMaxBits can be used as the number of bits in the buffer.
|
||||
// It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
|
||||
bf_read( const void *pData, int nBytes, int nBits = -1 );
|
||||
bf_read( const char *pDebugName, const void *pData, int nBytes, int nBits = -1 );
|
||||
|
||||
// Start reading from the specified buffer.
|
||||
// pData's start address must be dword-aligned.
|
||||
// nMaxBits can be used as the number of bits in the buffer.
|
||||
// It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
|
||||
void StartReading( const void *pData, int nBytes, int iStartBit = 0, int nBits = -1 );
|
||||
|
||||
// Restart buffer reading.
|
||||
void Reset();
|
||||
|
||||
// Enable or disable assertion on overflow. 99% of the time, it's a bug that we need to catch,
|
||||
// but there may be the occasional buffer that is allowed to overflow gracefully.
|
||||
void SetAssertOnOverflow( bool bAssert );
|
||||
|
||||
// This can be set to assign a name that gets output if the buffer overflows.
|
||||
const char* GetDebugName() const { return m_pDebugName; }
|
||||
void SetDebugName( const char *pName );
|
||||
|
||||
void ExciseBits( int startbit, int bitstoremove );
|
||||
|
||||
|
||||
// Bit functions.
|
||||
public:
|
||||
|
||||
// Returns 0 or 1.
|
||||
int ReadOneBit();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
unsigned int CheckReadUBitLong(int numbits); // For debugging.
|
||||
int ReadOneBitNoCheck(); // Faster version, doesn't check bounds and is inlined.
|
||||
bool CheckForOverflow(int nBits);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Get the base pointer.
|
||||
const unsigned char* GetBasePointer() { return m_pData; }
|
||||
|
||||
inline int TotalBytesAvailable( void ) const
|
||||
{
|
||||
return m_nDataBytes;
|
||||
}
|
||||
|
||||
// Read a list of bits in.
|
||||
void ReadBits(void *pOut, int nBits);
|
||||
// Read a list of bits in, but don't overrun the destination buffer.
|
||||
// Returns the number of bits read into the buffer. The remaining
|
||||
// bits are skipped over.
|
||||
int ReadBitsClamped_ptr(void *pOut, size_t outSizeBytes, size_t nBits);
|
||||
// Helper 'safe' template function that infers the size of the destination
|
||||
// array. This version of the function should be preferred.
|
||||
// Usage: char databuffer[100];
|
||||
// ReadBitsClamped( dataBuffer, msg->m_nLength );
|
||||
template <typename T, size_t N>
|
||||
int ReadBitsClamped( T (&pOut)[N], size_t nBits )
|
||||
{
|
||||
return ReadBitsClamped_ptr( pOut, N * sizeof(T), nBits );
|
||||
}
|
||||
|
||||
float ReadBitAngle( int numbits );
|
||||
|
||||
unsigned int ReadUBitLong( int numbits ) __restrict;
|
||||
unsigned int ReadUBitLongNoInline( int numbits ) __restrict;
|
||||
unsigned int PeekUBitLong( int numbits );
|
||||
int ReadSBitLong( int numbits );
|
||||
|
||||
// reads an unsigned integer with variable bit length
|
||||
unsigned int ReadUBitVar();
|
||||
unsigned int ReadUBitVarInternal( int encodingType );
|
||||
|
||||
// reads a varint encoded integer
|
||||
uint32 ReadVarInt32();
|
||||
uint64 ReadVarInt64();
|
||||
int32 ReadSignedVarInt32();
|
||||
int64 ReadSignedVarInt64();
|
||||
|
||||
// You can read signed or unsigned data with this, just cast to
|
||||
// a signed int if necessary.
|
||||
unsigned int ReadBitLong(int numbits, bool bSigned);
|
||||
|
||||
float ReadBitCoord();
|
||||
float ReadBitCoordMP( bool bIntegral, bool bLowPrecision );
|
||||
float ReadBitFloat();
|
||||
float ReadBitNormal();
|
||||
void ReadBitVec3Coord( Vector& fa );
|
||||
void ReadBitVec3Normal( Vector& fa );
|
||||
void ReadBitAngles( QAngle& fa );
|
||||
|
||||
// Faster for comparisons but do not fully decode float values
|
||||
unsigned int ReadBitCoordBits();
|
||||
unsigned int ReadBitCoordMPBits( bool bIntegral, bool bLowPrecision );
|
||||
|
||||
// Byte functions (these still read data in bit-by-bit).
|
||||
public:
|
||||
|
||||
inline int ReadChar() { return (char)ReadUBitLong(8); }
|
||||
inline int ReadByte() { return ReadUBitLong(8); }
|
||||
inline int ReadShort() { return (short)ReadUBitLong(16); }
|
||||
inline int ReadWord() { return ReadUBitLong(16); }
|
||||
inline long ReadLong() { return ReadUBitLong(32); }
|
||||
int64 ReadLongLong();
|
||||
float ReadFloat();
|
||||
bool ReadBytes(void *pOut, int nBytes);
|
||||
|
||||
// Returns false if bufLen isn't large enough to hold the
|
||||
// string in the buffer.
|
||||
//
|
||||
// Always reads to the end of the string (so you can read the
|
||||
// next piece of data waiting).
|
||||
//
|
||||
// If bLine is true, it stops when it reaches a '\n' or a null-terminator.
|
||||
//
|
||||
// pStr is always null-terminated (unless bufLen is 0).
|
||||
//
|
||||
// pOutNumChars is set to the number of characters left in pStr when the routine is
|
||||
// complete (this will never exceed bufLen-1).
|
||||
//
|
||||
bool ReadString( char *pStr, int bufLen, bool bLine=false, int *pOutNumChars=NULL );
|
||||
|
||||
// Reads a string and allocates memory for it. If the string in the buffer
|
||||
// is > 2048 bytes, then pOverflow is set to true (if it's not NULL).
|
||||
char* ReadAndAllocateString( bool *pOverflow = 0 );
|
||||
|
||||
// Returns nonzero if any bits differ
|
||||
int CompareBits( bf_read * __restrict other, int bits ) __restrict;
|
||||
int CompareBitsAt( int offset, bf_read * __restrict other, int otherOffset, int bits ) __restrict;
|
||||
|
||||
// Status.
|
||||
public:
|
||||
int GetNumBytesLeft();
|
||||
int GetNumBytesRead();
|
||||
int GetNumBitsLeft();
|
||||
int GetNumBitsRead() const;
|
||||
|
||||
// Has the buffer overflowed?
|
||||
inline bool IsOverflowed() const {return m_bOverflow;}
|
||||
|
||||
inline bool Seek(int iBit); // Seek to a specific bit.
|
||||
inline bool SeekRelative(int iBitDelta); // Seek to an offset from the current position.
|
||||
|
||||
// Called when the buffer is overflowed.
|
||||
void SetOverflowFlag();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// The current buffer.
|
||||
const unsigned char* __restrict m_pData;
|
||||
int m_nDataBytes;
|
||||
int m_nDataBits;
|
||||
|
||||
// Where we are in the buffer.
|
||||
int m_iCurBit;
|
||||
|
||||
|
||||
private:
|
||||
// Errors?
|
||||
bool m_bOverflow;
|
||||
|
||||
// For debugging..
|
||||
bool m_bAssertOnOverflow;
|
||||
|
||||
const char *m_pDebugName;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inlines.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline int bf_read::GetNumBytesRead()
|
||||
{
|
||||
return BitByte(m_iCurBit);
|
||||
}
|
||||
|
||||
inline int bf_read::GetNumBitsLeft()
|
||||
{
|
||||
return m_nDataBits - m_iCurBit;
|
||||
}
|
||||
|
||||
inline int bf_read::GetNumBytesLeft()
|
||||
{
|
||||
return GetNumBitsLeft() >> 3;
|
||||
}
|
||||
|
||||
inline int bf_read::GetNumBitsRead() const
|
||||
{
|
||||
return m_iCurBit;
|
||||
}
|
||||
|
||||
inline bool bf_read::Seek(int iBit)
|
||||
{
|
||||
if(iBit < 0 || iBit > m_nDataBits)
|
||||
{
|
||||
SetOverflowFlag();
|
||||
m_iCurBit = m_nDataBits;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iCurBit = iBit;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Seek to an offset from the current position.
|
||||
inline bool bf_read::SeekRelative(int iBitDelta)
|
||||
{
|
||||
return Seek(m_iCurBit+iBitDelta);
|
||||
}
|
||||
|
||||
inline bool bf_read::CheckForOverflow(int nBits)
|
||||
{
|
||||
if( m_iCurBit + nBits > m_nDataBits )
|
||||
{
|
||||
SetOverflowFlag();
|
||||
CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
|
||||
}
|
||||
|
||||
return m_bOverflow;
|
||||
}
|
||||
|
||||
inline int bf_read::ReadOneBitNoCheck()
|
||||
{
|
||||
int ret;
|
||||
if (is_little_endian())
|
||||
{
|
||||
unsigned int value = ((unsigned long * __restrict)m_pData)[m_iCurBit >> 5] >> (m_iCurBit & 31);
|
||||
ret = value & 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char value = m_pData[m_iCurBit >> 3] >> (m_iCurBit & 7);
|
||||
ret = value & 1;
|
||||
}
|
||||
++m_iCurBit;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int bf_read::ReadOneBit()
|
||||
{
|
||||
if( GetNumBitsLeft() <= 0 )
|
||||
{
|
||||
SetOverflowFlag();
|
||||
CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
|
||||
return 0;
|
||||
}
|
||||
return ReadOneBitNoCheck();
|
||||
}
|
||||
|
||||
inline float bf_read::ReadBitFloat()
|
||||
{
|
||||
union { uint32 u; float f; } c = { ReadUBitLong(32) };
|
||||
return c.f;
|
||||
}
|
||||
|
||||
inline unsigned int bf_read::ReadUBitVar()
|
||||
{
|
||||
// six bits: low 2 bits for encoding + first 4 bits of value
|
||||
unsigned int sixbits = ReadUBitLong(6);
|
||||
unsigned int encoding = sixbits & 3;
|
||||
if ( encoding )
|
||||
{
|
||||
// this function will seek back four bits and read the full value
|
||||
return ReadUBitVarInternal( encoding );
|
||||
}
|
||||
return sixbits >> 2;
|
||||
}
|
||||
|
||||
inline unsigned int bf_read::ReadUBitLong( int numbits ) __restrict
|
||||
{
|
||||
Assert( numbits > 0 && numbits <= 32 );
|
||||
|
||||
if ( GetNumBitsLeft() < numbits )
|
||||
{
|
||||
m_iCurBit = m_nDataBits;
|
||||
SetOverflowFlag();
|
||||
CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int iStartBit = m_iCurBit & 31u;
|
||||
int iLastBit = m_iCurBit + numbits - 1;
|
||||
unsigned int iWordOffset1 = m_iCurBit >> 5;
|
||||
unsigned int iWordOffset2 = iLastBit >> 5;
|
||||
m_iCurBit += numbits;
|
||||
|
||||
#if __i386__
|
||||
unsigned int bitmask = (2 << (numbits-1)) - 1;
|
||||
#else
|
||||
extern unsigned long g_ExtraMasks[33];
|
||||
unsigned int bitmask = g_ExtraMasks[numbits];
|
||||
#endif
|
||||
|
||||
unsigned int dw1 = LoadLittleDWord( (unsigned long* __restrict)m_pData, iWordOffset1 ) >> iStartBit;
|
||||
unsigned int dw2 = LoadLittleDWord( (unsigned long* __restrict)m_pData, iWordOffset2 ) << (32 - iStartBit);
|
||||
|
||||
return (dw1 | dw2) & bitmask;
|
||||
}
|
||||
|
||||
inline int bf_read::CompareBits( bf_read * __restrict other, int numbits ) __restrict
|
||||
{
|
||||
return (ReadUBitLong(numbits) != other->ReadUBitLong(numbits));
|
||||
}
|
||||
|
158
external/sourcesdk/valve_support.h
vendored
Normal file
158
external/sourcesdk/valve_support.h
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
#include "vector.h"
|
||||
|
||||
using uint64 = std::uint64_t;
|
||||
using uint32 = std::uint32_t;
|
||||
using uint16 = std::uint16_t;
|
||||
using uint8 = std::uint8_t;
|
||||
using int64 = std::int64_t;
|
||||
using int32 = std::int32_t;
|
||||
using int16 = std::int16_t;
|
||||
using int8 = std::int8_t;
|
||||
using uint = unsigned int;
|
||||
using byte = char;
|
||||
|
||||
#if defined(_M_IX86)
|
||||
#define __i386__ 1
|
||||
#endif
|
||||
|
||||
#define IsPC() true
|
||||
#ifdef _WIN64
|
||||
#define PLATFORM_WINDOWS_PC64 1
|
||||
#endif
|
||||
|
||||
#define NULL nullptr
|
||||
|
||||
#define Assert(x) assert(x)
|
||||
#define AssertMsg(x, ...) assert(x)
|
||||
#define AssertMsg2(x, ...) assert(x)
|
||||
#define AssertFatalMsg(x, ...) assert(x)
|
||||
|
||||
#define Q_memcpy memcpy
|
||||
|
||||
bool is_little_endian()
|
||||
{
|
||||
union {
|
||||
uint32 i;
|
||||
uint8 c[4];
|
||||
} bint = { 0x01020304 };
|
||||
|
||||
return bint.c[0] == 4;
|
||||
}
|
||||
|
||||
// OVERALL Coordinate Size Limits used in COMMON.C MSG_*BitCoord() Routines (and someday the HUD)
|
||||
#define COORD_INTEGER_BITS 14
|
||||
#define COORD_FRACTIONAL_BITS 5
|
||||
#define COORD_DENOMINATOR (1<<(COORD_FRACTIONAL_BITS))
|
||||
#define COORD_RESOLUTION (1.0/(COORD_DENOMINATOR))
|
||||
|
||||
// Special threshold for networking multiplayer origins
|
||||
#define COORD_INTEGER_BITS_MP 11
|
||||
#define COORD_FRACTIONAL_BITS_MP_LOWPRECISION 3
|
||||
#define COORD_DENOMINATOR_LOWPRECISION (1<<(COORD_FRACTIONAL_BITS_MP_LOWPRECISION))
|
||||
#define COORD_RESOLUTION_LOWPRECISION (1.0/(COORD_DENOMINATOR_LOWPRECISION))
|
||||
|
||||
#define NORMAL_FRACTIONAL_BITS 11
|
||||
#define NORMAL_DENOMINATOR ( (1<<(NORMAL_FRACTIONAL_BITS)) - 1 )
|
||||
#define NORMAL_RESOLUTION (1.0/(NORMAL_DENOMINATOR))
|
||||
|
||||
template <typename T>
|
||||
inline T DWordSwapC( T dw )
|
||||
{
|
||||
uint32 temp;
|
||||
temp = *((uint32 *)&dw) >> 24;
|
||||
temp |= ((*((uint32 *)&dw) & 0x00FF0000) >> 8);
|
||||
temp |= ((*((uint32 *)&dw) & 0x0000FF00) << 8);
|
||||
temp |= ((*((uint32 *)&dw) & 0x000000FF) << 24);
|
||||
return *((T*)&temp);
|
||||
}
|
||||
|
||||
#if defined( _MSC_VER ) && !defined( PLATFORM_WINDOWS_PC64 )
|
||||
#define DWordSwap DWordSwapAsm
|
||||
#pragma warning(push)
|
||||
#pragma warning (disable:4035) // no return value
|
||||
template <typename T>
|
||||
inline T DWordSwapAsm( T dw )
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, dw
|
||||
bswap eax
|
||||
}
|
||||
}
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
#define DWordSwap DWordSwapC
|
||||
#endif
|
||||
|
||||
inline unsigned long LoadLittleDWord(const unsigned long *base, unsigned int dwordIndex)
|
||||
{
|
||||
return (is_little_endian() ? base[dwordIndex] : (DWordSwap(base[dwordIndex])));
|
||||
}
|
||||
|
||||
inline void StoreLittleDWord(unsigned long *base, unsigned int dwordIndex, unsigned long dword)
|
||||
{
|
||||
base[dwordIndex] = (is_little_endian() ? dword : (DWordSwap(dword)));
|
||||
}
|
||||
|
||||
// If a swapped float passes through the fpu, the bytes may get changed.
|
||||
// Prevent this by swapping floats as DWORDs.
|
||||
#define SafeSwapFloat( pOut, pIn ) (*((uint*)pOut) = DWordSwap( *((uint*)pIn) ))
|
||||
|
||||
inline void LittleFloat(float* pOut, float* pIn)
|
||||
{
|
||||
if (is_little_endian())
|
||||
{
|
||||
*pOut = *pIn;
|
||||
}
|
||||
else
|
||||
{
|
||||
SafeSwapFloat(pOut, pIn);
|
||||
}
|
||||
}
|
||||
|
||||
#define BITS_PER_INT 32
|
||||
|
||||
inline int GetBitForBitnum( int bitNum )
|
||||
{
|
||||
static int bitsForBitnum[] =
|
||||
{
|
||||
( 1 << 0 ),
|
||||
( 1 << 1 ),
|
||||
( 1 << 2 ),
|
||||
( 1 << 3 ),
|
||||
( 1 << 4 ),
|
||||
( 1 << 5 ),
|
||||
( 1 << 6 ),
|
||||
( 1 << 7 ),
|
||||
( 1 << 8 ),
|
||||
( 1 << 9 ),
|
||||
( 1 << 10 ),
|
||||
( 1 << 11 ),
|
||||
( 1 << 12 ),
|
||||
( 1 << 13 ),
|
||||
( 1 << 14 ),
|
||||
( 1 << 15 ),
|
||||
( 1 << 16 ),
|
||||
( 1 << 17 ),
|
||||
( 1 << 18 ),
|
||||
( 1 << 19 ),
|
||||
( 1 << 20 ),
|
||||
( 1 << 21 ),
|
||||
( 1 << 22 ),
|
||||
( 1 << 23 ),
|
||||
( 1 << 24 ),
|
||||
( 1 << 25 ),
|
||||
( 1 << 26 ),
|
||||
( 1 << 27 ),
|
||||
( 1 << 28 ),
|
||||
( 1 << 29 ),
|
||||
( 1 << 30 ),
|
||||
( 1 << 31 ),
|
||||
};
|
||||
return bitsForBitnum[ (bitNum) & (BITS_PER_INT-1) ];
|
||||
}
|
53
external/sourcesdk/vector.h
vendored
Normal file
53
external/sourcesdk/vector.h
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
|
||||
class QAngle
|
||||
{
|
||||
public:
|
||||
float x, y, z;
|
||||
void Init( void )
|
||||
{
|
||||
x = y = z = 0.0f;
|
||||
}
|
||||
void Init( float _x, float _y, float _z )
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
};
|
||||
|
||||
class Vector
|
||||
{
|
||||
public:
|
||||
float x, y, z;
|
||||
Vector()
|
||||
{
|
||||
}
|
||||
Vector(float X, float Y, float Z)
|
||||
{
|
||||
x = X; y = Y; z = Z;
|
||||
}
|
||||
void Init( void )
|
||||
{
|
||||
x = y = z = 0.0f;
|
||||
}
|
||||
void Init( float _x, float _y, float _z )
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
float& Vector::operator[](int i)
|
||||
{
|
||||
assert( (i >= 0) && (i < 3) );
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
float Vector::operator[](int i) const
|
||||
{
|
||||
assert( (i >= 0) && (i < 3) );
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user