866 lines
26 KiB
C
866 lines
26 KiB
C
|
|
||
|
#ifndef __BITMSG_H__
|
||
|
#define __BITMSG_H__
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
idBitMsg
|
||
|
|
||
|
Handles byte ordering and avoids alignment errors.
|
||
|
Allows concurrent writing and reading.
|
||
|
The data set with Init is never freed.
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
class idBitMsg {
|
||
|
public:
|
||
|
idBitMsg();
|
||
|
~idBitMsg() {}
|
||
|
|
||
|
void Init( byte *data, int length );
|
||
|
void Init( const byte *data, int length );
|
||
|
byte * GetData( void ); // get data for writing
|
||
|
const byte * GetData( void ) const; // get data for reading
|
||
|
const byte * GetReadData( void ) const;
|
||
|
int GetMaxSize( void ) const; // get the maximum message size
|
||
|
void SetAllowOverflow( bool set ); // generate error if not set and message is overflowed
|
||
|
bool IsOverflowed( void ) const; // returns true if the message was overflowed
|
||
|
|
||
|
int GetSize( void ) const; // size of the message in bytes
|
||
|
void SetSize( int size ); // set the message size
|
||
|
int GetWriteBit( void ) const; // get current write bit
|
||
|
void SetWriteBit( int bit ); // set current write bit
|
||
|
int GetNumBitsWritten( void ) const; // returns number of bits written
|
||
|
int GetRemainingSpace( void ) const; // space left in bytes for writing
|
||
|
int GetRemainingWriteBits( void ) const; // space left in bits for writing
|
||
|
void SaveWriteState( int &s, int &b ) const; // save the write state
|
||
|
void RestoreWriteState( int s, int b ); // restore the write state
|
||
|
|
||
|
int GetReadCount( void ) const; // bytes read so far
|
||
|
void SetReadCount( int bytes ); // set the number of bytes and bits read
|
||
|
int GetReadBit( void ) const; // get current read bit
|
||
|
void SetReadBit( int bit ); // set current read bit
|
||
|
int GetNumBitsRead( void ) const; // returns number of bits read
|
||
|
int GetRemainingData( void ) const; // number of bytes left to read
|
||
|
int GetRemainingReadBits( void ) const; // number of bits left to read
|
||
|
void SaveReadState( int &c, int &b ) const; // save the read state
|
||
|
void RestoreReadState( int c, int b ) const; // restore the read state
|
||
|
|
||
|
void BeginWriting( void ); // begin writing
|
||
|
void WriteByteAlign( void ); // write up to the next byte boundary
|
||
|
void WriteBits( int value, int numBits ); // write the specified number of bits
|
||
|
void WriteChar( int c );
|
||
|
void WriteByte( int c );
|
||
|
void WriteShort( int c );
|
||
|
void WriteUShort( int c );
|
||
|
void WriteLong( int c );
|
||
|
void WriteFloat( float f );
|
||
|
void WriteFloat( float f, int exponentBits, int mantissaBits );
|
||
|
void WriteAngle8( float f );
|
||
|
void WriteAngle16( float f );
|
||
|
void WriteDir( const idVec3 &dir, int numBits );
|
||
|
void WriteString( const char *s, int maxLength = -1 );
|
||
|
void WriteData( const void *data, int length );
|
||
|
void WriteNetadr( const netadr_t adr );
|
||
|
|
||
|
void WriteDeltaChar( int oldValue, int newValue );
|
||
|
void WriteDeltaByte( int oldValue, int newValue );
|
||
|
void WriteDeltaShort( int oldValue, int newValue );
|
||
|
void WriteDeltaLong( int oldValue, int newValue );
|
||
|
void WriteDeltaFloat( float oldValue, float newValue );
|
||
|
void WriteDeltaFloat( float oldValue, float newValue, int exponentBits, int mantissaBits );
|
||
|
void WriteDeltaByteCounter( int oldValue, int newValue );
|
||
|
void WriteDeltaShortCounter( int oldValue, int newValue );
|
||
|
void WriteDeltaLongCounter( int oldValue, int newValue );
|
||
|
bool WriteDeltaDict( const idDict &dict, const idDict *base );
|
||
|
|
||
|
void BeginReading( void ) const; // begin reading.
|
||
|
void ReadByteAlign( void ) const; // read up to the next byte boundary
|
||
|
int ReadBits( int numBits ) const; // read the specified number of bits
|
||
|
int ReadChar( void ) const;
|
||
|
int ReadByte( void ) const;
|
||
|
int ReadShort( void ) const;
|
||
|
int ReadUShort( void ) const;
|
||
|
int ReadLong( void ) const;
|
||
|
float ReadFloat( void ) const;
|
||
|
float ReadFloat( int exponentBits, int mantissaBits ) const;
|
||
|
float ReadAngle8( void ) const;
|
||
|
float ReadAngle16( void ) const;
|
||
|
idVec3 ReadDir( int numBits ) const;
|
||
|
int ReadString( char *buffer, int bufferSize ) const;
|
||
|
int ReadData( void *data, int length ) const;
|
||
|
void ReadNetadr( netadr_t *adr ) const;
|
||
|
|
||
|
int ReadDeltaChar( int oldValue ) const;
|
||
|
int ReadDeltaByte( int oldValue ) const;
|
||
|
int ReadDeltaShort( int oldValue ) const;
|
||
|
int ReadDeltaLong( int oldValue ) const;
|
||
|
float ReadDeltaFloat( float oldValue ) const;
|
||
|
float ReadDeltaFloat( float oldValue, int exponentBits, int mantissaBits ) const;
|
||
|
int ReadDeltaByteCounter( int oldValue ) const;
|
||
|
int ReadDeltaShortCounter( int oldValue ) const;
|
||
|
int ReadDeltaLongCounter( int oldValue ) const;
|
||
|
bool ReadDeltaDict( idDict &dict, const idDict *base ) const;
|
||
|
|
||
|
static int DirToBits( const idVec3 &dir, int numBits );
|
||
|
static idVec3 BitsToDir( int bits, int numBits );
|
||
|
|
||
|
private:
|
||
|
byte * writeData; // pointer to data for writing
|
||
|
const byte * readData; // pointer to data for reading
|
||
|
int maxSize; // maximum size of message in bytes
|
||
|
int curSize; // current size of message in bytes
|
||
|
int writeBit; // number of bits written to the last written byte
|
||
|
mutable int readCount; // number of bytes read so far
|
||
|
mutable int readBit; // number of bits read from the last read byte
|
||
|
bool allowOverflow; // if false, generate an error when the message is overflowed
|
||
|
bool overflowed; // set to true if the buffer size failed (with allowOverflow set)
|
||
|
|
||
|
private:
|
||
|
bool CheckOverflow( int numBits );
|
||
|
byte * GetByteSpace( int length );
|
||
|
void WriteDelta( int oldValue, int newValue, int numBits );
|
||
|
int ReadDelta( int oldValue, int numBits ) const;
|
||
|
};
|
||
|
|
||
|
|
||
|
ID_INLINE void idBitMsg::Init( byte *data, int length ) {
|
||
|
writeData = data;
|
||
|
readData = data;
|
||
|
maxSize = length;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::Init( const byte *data, int length ) {
|
||
|
writeData = NULL;
|
||
|
readData = data;
|
||
|
maxSize = length;
|
||
|
}
|
||
|
|
||
|
ID_INLINE byte *idBitMsg::GetData( void ) {
|
||
|
return writeData;
|
||
|
}
|
||
|
|
||
|
ID_INLINE const byte *idBitMsg::GetData( void ) const {
|
||
|
return readData;
|
||
|
}
|
||
|
|
||
|
ID_INLINE const byte *idBitMsg::GetReadData( void ) const {
|
||
|
return ( readData + readCount );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::GetMaxSize( void ) const {
|
||
|
return maxSize;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::SetAllowOverflow( bool set ) {
|
||
|
allowOverflow = set;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idBitMsg::IsOverflowed( void ) const {
|
||
|
return overflowed;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::GetSize( void ) const {
|
||
|
return curSize;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::SetSize( int size ) {
|
||
|
if ( size > maxSize ) {
|
||
|
curSize = maxSize;
|
||
|
} else {
|
||
|
curSize = size;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::GetWriteBit( void ) const {
|
||
|
return writeBit;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::SetWriteBit( int bit ) {
|
||
|
writeBit = bit & 7;
|
||
|
if ( writeBit ) {
|
||
|
writeData[curSize - 1] &= ( 1 << writeBit ) - 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::GetNumBitsWritten( void ) const {
|
||
|
// return ( ( curSize << 3 ) - ( writeBit ? 8 - writeBit : 0 ) );
|
||
|
return ( ( curSize << 3 ) - ( ( 8 - writeBit ) & 7 ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::GetRemainingSpace( void ) const {
|
||
|
return maxSize - curSize;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::GetRemainingWriteBits( void ) const {
|
||
|
return ( maxSize << 3 ) - GetNumBitsWritten();
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::SaveWriteState( int &s, int &b ) const {
|
||
|
s = curSize;
|
||
|
b = writeBit;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::RestoreWriteState( int s, int b ) {
|
||
|
curSize = s;
|
||
|
writeBit = b & 7;
|
||
|
if ( writeBit ) {
|
||
|
writeData[curSize - 1] &= ( 1 << writeBit ) - 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::GetReadCount( void ) const {
|
||
|
return readCount;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::SetReadCount( int bytes ) {
|
||
|
readCount = bytes;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::GetReadBit( void ) const {
|
||
|
return readBit;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::SetReadBit( int bit ) {
|
||
|
readBit = bit & 7;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::GetNumBitsRead( void ) const {
|
||
|
// return ( ( readCount << 3 ) - ( readBit ? 8 - readBit : 0 ) );
|
||
|
return ( ( readCount << 3 ) - ( ( 8 - readBit ) & 7 ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::GetRemainingData( void ) const {
|
||
|
return curSize - readCount;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::GetRemainingReadBits( void ) const {
|
||
|
return ( curSize << 3 ) - GetNumBitsRead();
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::SaveReadState( int &c, int &b ) const {
|
||
|
c = readCount;
|
||
|
b = readBit;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::RestoreReadState( int c, int b ) const {
|
||
|
readCount = c;
|
||
|
readBit = b & 7;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::BeginWriting( void ) {
|
||
|
curSize = 0;
|
||
|
overflowed = false;
|
||
|
writeBit = 0;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteByteAlign( void ) {
|
||
|
writeBit = 0;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteChar( int c ) {
|
||
|
WriteBits( c, -8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteByte( int c ) {
|
||
|
WriteBits( c, 8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteShort( int c ) {
|
||
|
WriteBits( c, -16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteUShort( int c ) {
|
||
|
WriteBits( c, 16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteLong( int c ) {
|
||
|
WriteBits( c, 32 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteFloat( float f ) {
|
||
|
WriteBits( *reinterpret_cast<int *>(&f), 32 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteFloat( float f, int exponentBits, int mantissaBits ) {
|
||
|
int bits = idMath::FloatToBits( f, exponentBits, mantissaBits );
|
||
|
WriteBits( bits, 1 + exponentBits + mantissaBits );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteAngle8( float f ) {
|
||
|
WriteByte( ANGLE2BYTE( f ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteAngle16( float f ) {
|
||
|
WriteShort( ANGLE2SHORT(f) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteDir( const idVec3 &dir, int numBits ) {
|
||
|
WriteBits( DirToBits( dir, numBits ), numBits );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteDeltaChar( int oldValue, int newValue ) {
|
||
|
WriteDelta( oldValue, newValue, -8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteDeltaByte( int oldValue, int newValue ) {
|
||
|
WriteDelta( oldValue, newValue, 8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteDeltaShort( int oldValue, int newValue ) {
|
||
|
WriteDelta( oldValue, newValue, -16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteDeltaLong( int oldValue, int newValue ) {
|
||
|
WriteDelta( oldValue, newValue, 32 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteDeltaFloat( float oldValue, float newValue ) {
|
||
|
WriteDelta( *reinterpret_cast<int *>(&oldValue), *reinterpret_cast<int *>(&newValue), 32 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::WriteDeltaFloat( float oldValue, float newValue, int exponentBits, int mantissaBits ) {
|
||
|
int oldBits = idMath::FloatToBits( oldValue, exponentBits, mantissaBits );
|
||
|
int newBits = idMath::FloatToBits( newValue, exponentBits, mantissaBits );
|
||
|
WriteDelta( oldBits, newBits, 1 + exponentBits + mantissaBits );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::BeginReading( void ) const {
|
||
|
readCount = 0;
|
||
|
readBit = 0;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsg::ReadByteAlign( void ) const {
|
||
|
readBit = 0;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::ReadChar( void ) const {
|
||
|
return (signed char)ReadBits( -8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::ReadByte( void ) const {
|
||
|
return (unsigned char)ReadBits( 8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::ReadShort( void ) const {
|
||
|
return (short)ReadBits( -16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::ReadUShort( void ) const {
|
||
|
return (unsigned short)ReadBits( 16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::ReadLong( void ) const {
|
||
|
return ReadBits( 32 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idBitMsg::ReadFloat( void ) const {
|
||
|
float value;
|
||
|
*reinterpret_cast<int *>(&value) = ReadBits( 32 );
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idBitMsg::ReadFloat( int exponentBits, int mantissaBits ) const {
|
||
|
int bits = ReadBits( 1 + exponentBits + mantissaBits );
|
||
|
return idMath::BitsToFloat( bits, exponentBits, mantissaBits );
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idBitMsg::ReadAngle8( void ) const {
|
||
|
return BYTE2ANGLE( ReadByte() );
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idBitMsg::ReadAngle16( void ) const {
|
||
|
return SHORT2ANGLE( ReadShort() );
|
||
|
}
|
||
|
|
||
|
ID_INLINE idVec3 idBitMsg::ReadDir( int numBits ) const {
|
||
|
return BitsToDir( ReadBits( numBits ), numBits );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::ReadDeltaChar( int oldValue ) const {
|
||
|
return (signed char)ReadDelta( oldValue, -8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::ReadDeltaByte( int oldValue ) const {
|
||
|
return (unsigned char)ReadDelta( oldValue, 8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::ReadDeltaShort( int oldValue ) const {
|
||
|
return (short)ReadDelta( oldValue, -16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsg::ReadDeltaLong( int oldValue ) const {
|
||
|
return ReadDelta( oldValue, 32 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idBitMsg::ReadDeltaFloat( float oldValue ) const {
|
||
|
float value;
|
||
|
*reinterpret_cast<int *>(&value) = ReadDelta( *reinterpret_cast<int *>(&oldValue), 32 );
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idBitMsg::ReadDeltaFloat( float oldValue, int exponentBits, int mantissaBits ) const {
|
||
|
int oldBits = idMath::FloatToBits( oldValue, exponentBits, mantissaBits );
|
||
|
int newBits = ReadDelta( oldBits, 1 + exponentBits + mantissaBits );
|
||
|
return idMath::BitsToFloat( newBits, exponentBits, mantissaBits );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
idBitMsgDelta
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
class idBitMsgDelta {
|
||
|
public:
|
||
|
idBitMsgDelta();
|
||
|
~idBitMsgDelta() {}
|
||
|
|
||
|
void InitWriting( const idBitMsg *base, idBitMsg *newBase, idBitMsg *delta );
|
||
|
void InitReading( const idBitMsg *base, idBitMsg *newBase, const idBitMsg *delta );
|
||
|
bool HasChanged( void ) const;
|
||
|
|
||
|
void WriteBits( int value, int numBits );
|
||
|
void WriteChar( int c );
|
||
|
void WriteByte( int c );
|
||
|
void WriteShort( int c );
|
||
|
void WriteUShort( int c );
|
||
|
void WriteLong( int c );
|
||
|
void WriteFloat( float f );
|
||
|
void WriteFloat( float f, int exponentBits, int mantissaBits );
|
||
|
// RAVEN BEGIN
|
||
|
// abahr:
|
||
|
void WriteVec3( const idVec3& v );
|
||
|
void WriteDeltaVec3( const idVec3& oldValue, const idVec3& newValue );
|
||
|
void WriteVec4( const idVec4& v );
|
||
|
void WriteDeltaVec4( const idVec4& oldValue, const idVec4& newValue );
|
||
|
void WriteQuat( const idQuat& q );
|
||
|
void WriteDeltaQuat( const idQuat& oldValue, const idQuat& newValue );
|
||
|
void WriteMat3( const idMat3& m );
|
||
|
void WriteDeltaMat3( const idMat3& oldValue, const idMat3& newValue );
|
||
|
// RAVEN END
|
||
|
void WriteAngle8( float f );
|
||
|
void WriteAngle16( float f );
|
||
|
void WriteDir( const idVec3 &dir, int numBits );
|
||
|
void WriteString( const char *s, int maxLength = -1 );
|
||
|
void WriteData( const void *data, int length );
|
||
|
void WriteDict( const idDict &dict );
|
||
|
|
||
|
void WriteDeltaChar( int oldValue, int newValue );
|
||
|
void WriteDeltaByte( int oldValue, int newValue );
|
||
|
void WriteDeltaShort( int oldValue, int newValue );
|
||
|
void WriteDeltaLong( int oldValue, int newValue );
|
||
|
void WriteDeltaFloat( float oldValue, float newValue );
|
||
|
void WriteDeltaFloat( float oldValue, float newValue, int exponentBits, int mantissaBits );
|
||
|
void WriteDeltaByteCounter( int oldValue, int newValue );
|
||
|
void WriteDeltaShortCounter( int oldValue, int newValue );
|
||
|
void WriteDeltaLongCounter( int oldValue, int newValue );
|
||
|
|
||
|
int ReadBits( int numBits ) const;
|
||
|
int ReadChar( void ) const;
|
||
|
int ReadByte( void ) const;
|
||
|
int ReadShort( void ) const;
|
||
|
int ReadUShort( void ) const;
|
||
|
int ReadLong( void ) const;
|
||
|
float ReadFloat( void ) const;
|
||
|
float ReadFloat( int exponentBits, int mantissaBits ) const;
|
||
|
// RAVEN BEGIN
|
||
|
// abahr
|
||
|
idVec3 ReadVec3( void ) const;
|
||
|
idVec3 ReadDeltaVec3( const idVec3& oldValue ) const;
|
||
|
idVec4 ReadVec4( void ) const;
|
||
|
idVec4 ReadDeltaVec4( const idVec4& oldValue ) const;
|
||
|
idQuat ReadQuat( void ) const;
|
||
|
idQuat ReadDeltaQuat( const idQuat& oldValue ) const;
|
||
|
idMat3 ReadMat3( void ) const;
|
||
|
idMat3 ReadDeltaMat3( const idMat3& oldValue ) const;
|
||
|
// RAVEN END
|
||
|
float ReadAngle8( void ) const;
|
||
|
float ReadAngle16( void ) const;
|
||
|
idVec3 ReadDir( int numBits ) const;
|
||
|
void ReadString( char *buffer, int bufferSize ) const;
|
||
|
void ReadData( void *data, int length ) const;
|
||
|
void ReadDict( idDict &dict );
|
||
|
|
||
|
int ReadDeltaChar( int oldValue ) const;
|
||
|
int ReadDeltaByte( int oldValue ) const;
|
||
|
int ReadDeltaShort( int oldValue ) const;
|
||
|
int ReadDeltaLong( int oldValue ) const;
|
||
|
float ReadDeltaFloat( float oldValue ) const;
|
||
|
float ReadDeltaFloat( float oldValue, int exponentBits, int mantissaBits ) const;
|
||
|
int ReadDeltaByteCounter( int oldValue ) const;
|
||
|
int ReadDeltaShortCounter( int oldValue ) const;
|
||
|
int ReadDeltaLongCounter( int oldValue ) const;
|
||
|
|
||
|
private:
|
||
|
const idBitMsg *base; // base
|
||
|
idBitMsg * newBase; // new base
|
||
|
idBitMsg * writeDelta; // delta from base to new base for writing
|
||
|
const idBitMsg *readDelta; // delta from base to new base for reading
|
||
|
mutable bool changed; // true if the new base is different from the base
|
||
|
|
||
|
private:
|
||
|
void WriteDelta( int oldValue, int newValue, int numBits );
|
||
|
int ReadDelta( int oldValue, int numBits ) const;
|
||
|
};
|
||
|
|
||
|
ID_INLINE idBitMsgDelta::idBitMsgDelta() {
|
||
|
base = NULL;
|
||
|
newBase = NULL;
|
||
|
writeDelta = NULL;
|
||
|
readDelta = NULL;
|
||
|
changed = false;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::InitWriting( const idBitMsg *base, idBitMsg *newBase, idBitMsg *delta ) {
|
||
|
this->base = base;
|
||
|
this->newBase = newBase;
|
||
|
this->writeDelta = delta;
|
||
|
this->readDelta = delta;
|
||
|
this->changed = false;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::InitReading( const idBitMsg *base, idBitMsg *newBase, const idBitMsg *delta ) {
|
||
|
this->base = base;
|
||
|
this->newBase = newBase;
|
||
|
this->writeDelta = NULL;
|
||
|
this->readDelta = delta;
|
||
|
this->changed = false;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idBitMsgDelta::HasChanged( void ) const {
|
||
|
return changed;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteChar( int c ) {
|
||
|
WriteBits( c, -8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteByte( int c ) {
|
||
|
WriteBits( c, 8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteShort( int c ) {
|
||
|
WriteBits( c, -16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteUShort( int c ) {
|
||
|
WriteBits( c, 16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteLong( int c ) {
|
||
|
WriteBits( c, 32 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteFloat( float f ) {
|
||
|
WriteBits( *reinterpret_cast<int *>(&f), 32 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteFloat( float f, int exponentBits, int mantissaBits ) {
|
||
|
int bits = idMath::FloatToBits( f, exponentBits, mantissaBits );
|
||
|
WriteBits( bits, 1 + exponentBits + mantissaBits );
|
||
|
}
|
||
|
|
||
|
// RAVEN BEGIN
|
||
|
// abahr
|
||
|
ID_INLINE void idBitMsgDelta::WriteVec3( const idVec3& v ) {
|
||
|
for( int ix = 0; ix < v.GetDimension(); ++ix ) {
|
||
|
WriteFloat( v[ix] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteDeltaVec3( const idVec3& oldValue, const idVec3& newValue ) {
|
||
|
for( int ix = 0; ix < oldValue.GetDimension(); ++ix ) {
|
||
|
WriteDeltaFloat( oldValue[ix], newValue[ix] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteVec4( const idVec4& v ) {
|
||
|
for( int ix = 0; ix < v.GetDimension(); ++ix ) {
|
||
|
WriteFloat( v[ix] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteDeltaVec4( const idVec4& oldValue, const idVec4& newValue ) {
|
||
|
for( int ix = 0; ix < oldValue.GetDimension(); ++ix ) {
|
||
|
WriteDeltaFloat( oldValue[ix], newValue[ix] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteQuat( const idQuat& q ) {
|
||
|
for( int ix = 0; ix < q.GetDimension(); ++ix ) {
|
||
|
WriteFloat( q[ix] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteDeltaQuat( const idQuat& oldValue, const idQuat& newValue ) {
|
||
|
for( int ix = 0; ix < oldValue.GetDimension(); ++ix ) {
|
||
|
WriteDeltaFloat( oldValue[ix], newValue[ix] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteMat3( const idMat3& m ) {
|
||
|
for( int ix = 0; ix < m.GetVec3Dimension(); ++ix ) {
|
||
|
WriteVec3( m[ix] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteDeltaMat3( const idMat3& oldValue, const idMat3& newValue ) {
|
||
|
for( int ix = 0; ix < oldValue.GetDimension(); ++ix ) {
|
||
|
WriteDeltaVec3( oldValue[ix], newValue[ix] );
|
||
|
}
|
||
|
}
|
||
|
// RAVEN END
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteAngle8( float f ) {
|
||
|
WriteBits( ANGLE2BYTE( f ), 8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteAngle16( float f ) {
|
||
|
WriteBits( ANGLE2SHORT(f), 16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteDir( const idVec3 &dir, int numBits ) {
|
||
|
WriteBits( idBitMsg::DirToBits( dir, numBits ), numBits );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteDeltaChar( int oldValue, int newValue ) {
|
||
|
WriteDelta( oldValue, newValue, -8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteDeltaByte( int oldValue, int newValue ) {
|
||
|
WriteDelta( oldValue, newValue, 8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteDeltaShort( int oldValue, int newValue ) {
|
||
|
WriteDelta( oldValue, newValue, -16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteDeltaLong( int oldValue, int newValue ) {
|
||
|
WriteDelta( oldValue, newValue, 32 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteDeltaFloat( float oldValue, float newValue ) {
|
||
|
WriteDelta( *reinterpret_cast<int *>(&oldValue), *reinterpret_cast<int *>(&newValue), 32 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idBitMsgDelta::WriteDeltaFloat( float oldValue, float newValue, int exponentBits, int mantissaBits ) {
|
||
|
int oldBits = idMath::FloatToBits( oldValue, exponentBits, mantissaBits );
|
||
|
int newBits = idMath::FloatToBits( newValue, exponentBits, mantissaBits );
|
||
|
WriteDelta( oldBits, newBits, 1 + exponentBits + mantissaBits );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsgDelta::ReadChar( void ) const {
|
||
|
return (signed char)ReadBits( -8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsgDelta::ReadByte( void ) const {
|
||
|
return (unsigned char)ReadBits( 8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsgDelta::ReadShort( void ) const {
|
||
|
return (short)ReadBits( -16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsgDelta::ReadUShort( void ) const {
|
||
|
return (unsigned short)ReadBits( 16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsgDelta::ReadLong( void ) const {
|
||
|
return ReadBits( 32 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idBitMsgDelta::ReadFloat( void ) const {
|
||
|
float value;
|
||
|
*reinterpret_cast<int *>(&value) = ReadBits( 32 );
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idBitMsgDelta::ReadFloat( int exponentBits, int mantissaBits ) const {
|
||
|
int bits = ReadBits( 1 + exponentBits + mantissaBits );
|
||
|
return idMath::BitsToFloat( bits, exponentBits, mantissaBits );
|
||
|
}
|
||
|
|
||
|
// RAVEN BEGIN
|
||
|
// abahr
|
||
|
ID_INLINE idVec3 idBitMsgDelta::ReadVec3() const {
|
||
|
idVec3 v;
|
||
|
for( int ix = 0; ix < v.GetDimension(); ++ix ) {
|
||
|
v[ix] = ReadFloat();
|
||
|
}
|
||
|
|
||
|
return v;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idVec3 idBitMsgDelta::ReadDeltaVec3( const idVec3& oldValue ) const {
|
||
|
idVec3 value;
|
||
|
for( int ix = 0; ix < value.GetDimension(); ++ix ) {
|
||
|
value[ix] = ReadDeltaFloat( oldValue[ix] );
|
||
|
}
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idVec4 idBitMsgDelta::ReadVec4( void ) const {
|
||
|
idVec4 v;
|
||
|
for( int ix = 0; ix < v.GetDimension(); ++ix ) {
|
||
|
v[ix] = ReadFloat();
|
||
|
}
|
||
|
|
||
|
return v;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idVec4 idBitMsgDelta::ReadDeltaVec4( const idVec4& oldValue ) const {
|
||
|
idVec4 value;
|
||
|
for( int ix = 0; ix < value.GetDimension(); ++ix ) {
|
||
|
value[ix] = ReadDeltaFloat( oldValue[ix] );
|
||
|
}
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idQuat idBitMsgDelta::ReadQuat( void ) const {
|
||
|
idQuat q;
|
||
|
for( int ix = 0; ix < q.GetDimension(); ++ix ) {
|
||
|
q[ix] = ReadFloat();
|
||
|
}
|
||
|
|
||
|
return q;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idQuat idBitMsgDelta::ReadDeltaQuat( const idQuat& oldValue ) const {
|
||
|
idQuat value;
|
||
|
for( int ix = 0; ix < value.GetDimension(); ++ix ) {
|
||
|
value[ix] = ReadDeltaFloat( oldValue[ix] );
|
||
|
}
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idMat3 idBitMsgDelta::ReadMat3() const {
|
||
|
idMat3 m;
|
||
|
|
||
|
for( int ix = 0; ix < m.GetVec3Dimension(); ++ix ) {
|
||
|
m[ix] = ReadVec3();
|
||
|
}
|
||
|
|
||
|
return m;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idMat3 idBitMsgDelta::ReadDeltaMat3( const idMat3& oldValue ) const {
|
||
|
idMat3 value;
|
||
|
|
||
|
for( int ix = 0; ix < value.GetVec3Dimension(); ++ix ) {
|
||
|
value[ix] = ReadDeltaVec3( oldValue[ix] );
|
||
|
}
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
// RAVEN END
|
||
|
|
||
|
ID_INLINE float idBitMsgDelta::ReadAngle8( void ) const {
|
||
|
return BYTE2ANGLE( ReadByte() );
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idBitMsgDelta::ReadAngle16( void ) const {
|
||
|
return SHORT2ANGLE( ReadShort() );
|
||
|
}
|
||
|
|
||
|
ID_INLINE idVec3 idBitMsgDelta::ReadDir( int numBits ) const {
|
||
|
return idBitMsg::BitsToDir( ReadBits( numBits ), numBits );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsgDelta::ReadDeltaChar( int oldValue ) const {
|
||
|
return (signed char)ReadDelta( oldValue, -8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsgDelta::ReadDeltaByte( int oldValue ) const {
|
||
|
return (unsigned char)ReadDelta( oldValue, 8 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsgDelta::ReadDeltaShort( int oldValue ) const {
|
||
|
return (short)ReadDelta( oldValue, -16 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idBitMsgDelta::ReadDeltaLong( int oldValue ) const {
|
||
|
return ReadDelta( oldValue, 32 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idBitMsgDelta::ReadDeltaFloat( float oldValue ) const {
|
||
|
float value;
|
||
|
*reinterpret_cast<int *>(&value) = ReadDelta( *reinterpret_cast<int *>(&oldValue), 32 );
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idBitMsgDelta::ReadDeltaFloat( float oldValue, int exponentBits, int mantissaBits ) const {
|
||
|
int oldBits = idMath::FloatToBits( oldValue, exponentBits, mantissaBits );
|
||
|
int newBits = ReadDelta( oldBits, 1 + exponentBits + mantissaBits );
|
||
|
return idMath::BitsToFloat( newBits, exponentBits, mantissaBits );
|
||
|
}
|
||
|
|
||
|
#define MAX_MSG_QUEUE_SIZE 16384 // must be a power of 2
|
||
|
|
||
|
class idMsgQueue {
|
||
|
public:
|
||
|
idMsgQueue();
|
||
|
|
||
|
void Init( int sequence );
|
||
|
|
||
|
bool Add( const byte *data, const int size, bool sequencing );
|
||
|
// prepend to a message without the need to a memcopy and readjust
|
||
|
bool AddConcat( const byte *data1, const int size1, const byte *data2, const int size2, bool sequencing );
|
||
|
bool Get( byte *data, int dataSize, int &size, bool sequencing );
|
||
|
int GetTotalSize( void ) const;
|
||
|
int GetSpaceLeft( void ) const;
|
||
|
int GetFirst( void ) const { return first; }
|
||
|
int GetLast( void ) const { return last; }
|
||
|
void CopyToBuffer( byte *buf ) const;
|
||
|
|
||
|
void WriteTo( idBitMsg &msg );
|
||
|
void FlushTo( idBitMsg &msg );
|
||
|
void ReadFrom( const idBitMsg &msg );
|
||
|
|
||
|
void Save( idFile *file ) const;
|
||
|
void Restore( idFile *file );
|
||
|
|
||
|
private:
|
||
|
byte buffer[MAX_MSG_QUEUE_SIZE];
|
||
|
int first; // sequence number of first message in queue
|
||
|
int last; // sequence number of last message in queue
|
||
|
int startIndex; // index pointing to the first byte of the first message
|
||
|
int endIndex; // index pointing to the first byte after the last message
|
||
|
|
||
|
public:
|
||
|
void WriteByte( byte b );
|
||
|
byte ReadByte( void );
|
||
|
void WriteShort( int s );
|
||
|
void WriteUShort( int s );
|
||
|
int ReadShort( void );
|
||
|
int ReadUShort( void );
|
||
|
void WriteLong( int l );
|
||
|
int ReadLong( void );
|
||
|
void WriteData( const byte *data, const int size );
|
||
|
void ReadData( byte *data, const int size );
|
||
|
};
|
||
|
|
||
|
class idBitMsgQueue {
|
||
|
public:
|
||
|
idBitMsgQueue();
|
||
|
|
||
|
void Init( void );
|
||
|
|
||
|
void Add( const idBitMsg &msg, const int timestamp );
|
||
|
bool Get( idBitMsg &msg, int ×tamp );
|
||
|
bool Get( idBitMsg &msg ) { int dummy; return Get( msg, dummy); }
|
||
|
bool GetTimestamp( int ×tamp );
|
||
|
|
||
|
private:
|
||
|
int nextTimestamp;
|
||
|
bool readTimestamp;
|
||
|
idLinkList<idMsgQueue> writeList, readList;
|
||
|
};
|
||
|
|
||
|
#endif /* !__BITMSG_H__ */
|