2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# ifndef __BITMSG_H__
# define __BITMSG_H__
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2012-11-28 15:47:07 +00:00
idBitMsg operates on a sequence of individual bits . It handles byte ordering and
avoids alignment errors . It allows concurrent writing and reading . The data set with Init
2012-11-26 18:58:24 +00:00
is never free - d .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
class idBitMsg
{
2012-11-26 18:58:24 +00:00
public :
2012-11-28 15:47:07 +00:00
idBitMsg ( )
{
InitWrite ( NULL , 0 ) ;
}
idBitMsg ( byte * data , int length )
{
InitWrite ( data , length ) ;
}
idBitMsg ( const byte * data , int length )
{
InitRead ( data , length ) ;
}
2012-11-26 18:58:24 +00:00
// both read & write
2012-11-28 15:47:07 +00:00
void InitWrite ( byte * data , int length ) ;
2012-11-26 18:58:24 +00:00
// read only
2012-11-28 15:47:07 +00:00
void InitRead ( const byte * data , int length ) ;
2012-11-26 18:58:24 +00:00
// get data for writing
2012-11-28 15:47:07 +00:00
byte * GetWriteData ( ) ;
2012-11-26 18:58:24 +00:00
// get data for reading
2012-11-28 15:47:07 +00:00
const byte * GetReadData ( ) const ;
2012-11-26 18:58:24 +00:00
// get the maximum message size
int GetMaxSize ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// generate error if not set and message is overflowed
void SetAllowOverflow ( bool set ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// returns true if the message was overflowed
bool IsOverflowed ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// size of the message in bytes
int GetSize ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the message size
void SetSize ( int size ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get current write bit
int GetWriteBit ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set current write bit
void SetWriteBit ( int bit ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// returns number of bits written
int GetNumBitsWritten ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// space left in bytes for writing
int GetRemainingSpace ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// space left in bits for writing
int GetRemainingWriteBits ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//------------------------
// Write State
//------------------------
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// save the write state
2012-11-28 15:47:07 +00:00
void SaveWriteState ( int & s , int & b , uint64 & t ) const ;
2012-11-26 18:58:24 +00:00
// restore the write state
void RestoreWriteState ( int s , int b , uint64 t ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//------------------------
// Reading
//------------------------
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// bytes read so far
int GetReadCount ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the number of bytes and bits read
void SetReadCount ( int bytes ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get current read bit
int GetReadBit ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set current read bit
void SetReadBit ( int bit ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// returns number of bits read
int GetNumBitsRead ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// number of bytes left to read
int GetRemainingData ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// number of bits left to read
int GetRemainingReadBits ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// save the read state
2012-11-28 15:47:07 +00:00
void SaveReadState ( int & c , int & b ) const ;
2012-11-26 18:58:24 +00:00
// restore the read state
void RestoreReadState ( int c , int b ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//------------------------
// Writing
//------------------------
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// begin writing
void BeginWriting ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// write up to the next byte boundary
void WriteByteAlign ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// write the specified number of bits
void WriteBits ( int value , int numBits ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
void WriteBool ( bool c ) ;
void WriteChar ( int8 c ) ;
void WriteByte ( uint8 c ) ;
void WriteShort ( int16 c ) ;
void WriteUShort ( uint16 c ) ;
void WriteLong ( int32 c ) ;
void WriteLongLong ( int64 c ) ;
void WriteFloat ( float f ) ;
void WriteFloat ( float f , int exponentBits , int mantissaBits ) ;
void WriteAngle8 ( float f ) ;
void WriteAngle16 ( float f ) ;
2012-11-28 15:47:07 +00:00
void WriteDir ( const idVec3 & dir , int numBits ) ;
void WriteString ( const char * s , int maxLength = - 1 , bool make7Bit = true ) ;
void WriteData ( const void * data , int length ) ;
2012-11-26 18:58:24 +00:00
void WriteNetadr ( const netadr_t adr ) ;
2012-11-28 15:47:07 +00:00
void WriteUNorm8 ( float f )
{
WriteByte ( idMath : : Ftob ( f * 255.0f ) ) ;
}
void WriteUNorm16 ( float f )
{
WriteUShort ( idMath : : Ftoi ( f * 65535.0f ) ) ;
}
void WriteNorm16 ( float f )
{
WriteShort ( idMath : : Ftoi ( f * 32767.0f ) ) ;
}
void WriteDeltaChar ( int8 oldValue , int8 newValue )
{
WriteByte ( newValue - oldValue ) ;
}
void WriteDeltaByte ( uint8 oldValue , uint8 newValue )
{
WriteByte ( newValue - oldValue ) ;
}
void WriteDeltaShort ( int16 oldValue , int16 newValue )
{
WriteUShort ( newValue - oldValue ) ;
}
void WriteDeltaUShort ( uint16 oldValue , uint16 newValue )
{
WriteUShort ( newValue - oldValue ) ;
}
void WriteDeltaLong ( int32 oldValue , int32 newValue )
{
WriteLong ( newValue - oldValue ) ;
}
void WriteDeltaFloat ( float oldValue , float newValue )
{
WriteFloat ( newValue - oldValue ) ;
}
void WriteDeltaFloat ( float oldValue , float newValue , int exponentBits , int mantissaBits )
{
WriteFloat ( newValue - oldValue , exponentBits , mantissaBits ) ;
}
bool WriteDeltaDict ( const idDict & dict , const idDict * base ) ;
2012-11-26 18:58:24 +00:00
template < int _max_ , int _numBits_ >
void WriteQuantizedFloat ( float value ) ;
template < int _max_ , int _numBits_ >
void WriteQuantizedUFloat ( float value ) ; // Quantize a float to a variable number of bits (assumes unsigned, uses simple quantization)
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
template < typename T >
2012-11-28 15:47:07 +00:00
void WriteVectorFloat ( const T & v )
{
for ( int i = 0 ; i < v . GetDimension ( ) ; i + + )
{
WriteFloat ( v [ i ] ) ;
}
}
2012-11-26 18:58:24 +00:00
template < typename T >
2012-11-28 15:47:07 +00:00
void WriteVectorUNorm8 ( const T & v )
{
for ( int i = 0 ; i < v . GetDimension ( ) ; i + + )
{
WriteUNorm8 ( v [ i ] ) ;
}
}
2012-11-26 18:58:24 +00:00
template < typename T >
2012-11-28 15:47:07 +00:00
void WriteVectorUNorm16 ( const T & v )
{
for ( int i = 0 ; i < v . GetDimension ( ) ; i + + )
{
WriteUNorm16 ( v [ i ] ) ;
}
}
2012-11-26 18:58:24 +00:00
template < typename T >
2012-11-28 15:47:07 +00:00
void WriteVectorNorm16 ( const T & v )
{
for ( int i = 0 ; i < v . GetDimension ( ) ; i + + )
{
WriteNorm16 ( v [ i ] ) ;
}
}
2012-11-26 18:58:24 +00:00
// Compress a vector to a variable number of bits (assumes signed, uses simple quantization)
template < typename T , int _max_ , int _numBits_ >
2012-11-28 15:47:07 +00:00
void WriteQuantizedVector ( const T & v )
{
for ( int i = 0 ; i < v . GetDimension ( ) ; i + + )
{
WriteQuantizedFloat < _max_ , _numBits_ > ( v [ i ] ) ;
}
}
2012-11-26 18:58:24 +00:00
// begin reading.
void BeginReading ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// read up to the next byte boundary
void ReadByteAlign ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// read the specified number of bits
int ReadBits ( int numBits ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool ReadBool ( ) const ;
int ReadChar ( ) const ;
int ReadByte ( ) const ;
int ReadShort ( ) const ;
int ReadUShort ( ) const ;
int ReadLong ( ) const ;
int64 ReadLongLong ( ) const ;
float ReadFloat ( ) const ;
float ReadFloat ( int exponentBits , int mantissaBits ) const ;
float ReadAngle8 ( ) const ;
float ReadAngle16 ( ) const ;
idVec3 ReadDir ( int numBits ) const ;
2012-11-28 15:47:07 +00:00
int ReadString ( char * buffer , int bufferSize ) const ;
int ReadString ( idStr & str ) const ;
int ReadData ( void * data , int length ) const ;
void ReadNetadr ( netadr_t * adr ) const ;
float ReadUNorm8 ( ) const
{
return ReadByte ( ) / 255.0f ;
}
float ReadUNorm16 ( ) const
{
return ReadUShort ( ) / 65535.0f ;
}
float ReadNorm16 ( ) const
{
return ReadShort ( ) / 32767.0f ;
}
int8 ReadDeltaChar ( int8 oldValue ) const
{
return oldValue + ReadByte ( ) ;
}
uint8 ReadDeltaByte ( uint8 oldValue ) const
{
return oldValue + ReadByte ( ) ;
}
int16 ReadDeltaShort ( int16 oldValue ) const
{
return oldValue + ReadUShort ( ) ;
}
uint16 ReadDeltaUShort ( uint16 oldValue ) const
{
return oldValue + ReadUShort ( ) ;
}
int32 ReadDeltaLong ( int32 oldValue ) const
{
return oldValue + ReadLong ( ) ;
}
float ReadDeltaFloat ( float oldValue ) const
{
return oldValue + ReadFloat ( ) ;
}
float ReadDeltaFloat ( float oldValue , int exponentBits , int mantissaBits ) const
{
return oldValue + ReadFloat ( exponentBits , mantissaBits ) ;
}
bool ReadDeltaDict ( idDict & dict , const idDict * base ) const ;
2012-11-26 18:58:24 +00:00
template < int _max_ , int _numBits_ >
float ReadQuantizedFloat ( ) const ;
template < int _max_ , int _numBits_ >
float ReadQuantizedUFloat ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
template < typename T >
2012-11-28 15:47:07 +00:00
void ReadVectorFloat ( T & v ) const
{
for ( int i = 0 ; i < v . GetDimension ( ) ; i + + )
{
v [ i ] = ReadFloat ( ) ;
}
}
2012-11-26 18:58:24 +00:00
template < typename T >
2012-11-28 15:47:07 +00:00
void ReadVectorUNorm8 ( T & v ) const
{
for ( int i = 0 ; i < v . GetDimension ( ) ; i + + )
{
v [ i ] = ReadUNorm8 ( ) ;
}
}
2012-11-26 18:58:24 +00:00
template < typename T >
2012-11-28 15:47:07 +00:00
void ReadVectorUNorm16 ( T & v ) const
{
for ( int i = 0 ; i < v . GetDimension ( ) ; i + + )
{
v [ i ] = ReadUNorm16 ( ) ;
}
}
2012-11-26 18:58:24 +00:00
template < typename T >
2012-11-28 15:47:07 +00:00
void ReadVectorNorm16 ( T & v ) const
{
for ( int i = 0 ; i < v . GetDimension ( ) ; i + + )
{
v [ i ] = ReadNorm16 ( ) ;
}
}
2012-11-26 18:58:24 +00:00
template < typename T , int _max_ , int _numBits_ >
2012-11-28 15:47:07 +00:00
void ReadQuantizedVector ( T & v ) const
{
for ( int i = 0 ; i < v . GetDimension ( ) ; i + + )
{
v [ i ] = ReadQuantizedFloat < _max_ , _numBits_ > ( ) ;
}
}
static int DirToBits ( const idVec3 & dir , int numBits ) ;
2012-11-26 18:58:24 +00:00
static idVec3 BitsToDir ( int bits , int numBits ) ;
2012-11-28 15:47:07 +00:00
void SetHasChanged ( bool b )
{
hasChanged = b ;
}
bool HasChanged ( ) const
{
return hasChanged ;
}
2012-11-26 18:58:24 +00:00
private :
2012-11-28 15:47:07 +00:00
byte * writeData ; // pointer to data for writing
const byte * readData ; // pointer to data for reading
2012-11-26 18:58:24 +00:00
int maxSize ; // maximum size of message in bytes
int curSize ; // current size of message in bytes
mutable 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 error when the message is overflowed
bool overflowed ; // set true if buffer size failed (with allowOverflow set)
bool hasChanged ; // Hack
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mutable uint64 tempValue ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
private :
bool CheckOverflow ( int numBits ) ;
2012-11-28 15:47:07 +00:00
byte * GetByteSpace ( int length ) ;
2012-11-26 18:58:24 +00:00
} ;
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : InitWrite
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : InitWrite ( byte * data , int length )
{
2012-11-26 18:58:24 +00:00
writeData = data ;
readData = data ;
maxSize = length ;
curSize = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
writeBit = 0 ;
readCount = 0 ;
readBit = 0 ;
allowOverflow = false ;
overflowed = false ;
tempValue = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : InitRead
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : InitRead ( const byte * data , int length )
{
2012-11-26 18:58:24 +00:00
writeData = NULL ;
readData = data ;
maxSize = length ;
curSize = length ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
writeBit = 0 ;
readCount = 0 ;
readBit = 0 ;
allowOverflow = false ;
overflowed = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
tempValue = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetWriteData
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE byte * idBitMsg : : GetWriteData ( )
{
2012-11-26 18:58:24 +00:00
return writeData ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetReadData
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE const byte * idBitMsg : : GetReadData ( ) const
{
2012-11-26 18:58:24 +00:00
return readData ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetMaxSize
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : GetMaxSize ( ) const
{
2012-11-26 18:58:24 +00:00
return maxSize ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : SetAllowOverflow
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : SetAllowOverflow ( bool set )
{
2012-11-26 18:58:24 +00:00
allowOverflow = set ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : IsOverflowed
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE bool idBitMsg : : IsOverflowed ( ) const
{
2012-11-26 18:58:24 +00:00
return overflowed ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetSize
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : GetSize ( ) const
{
2012-11-26 18:58:24 +00:00
return curSize + ( writeBit ! = 0 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : SetSize
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : SetSize ( int size )
{
2012-11-26 18:58:24 +00:00
assert ( writeBit = = 0 ) ;
2012-11-28 15:47:07 +00:00
if ( size > maxSize )
{
2012-11-26 18:58:24 +00:00
curSize = maxSize ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
curSize = size ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetWriteBit
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : GetWriteBit ( ) const
{
2012-11-26 18:58:24 +00:00
return writeBit ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : SetWriteBit
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : SetWriteBit ( int bit )
{
2012-11-26 18:58:24 +00:00
// see idBitMsg::WriteByteAlign
assert ( false ) ;
writeBit = bit & 7 ;
2012-11-28 15:47:07 +00:00
if ( writeBit )
{
2012-11-26 18:58:24 +00:00
writeData [ curSize - 1 ] & = ( 1 < < writeBit ) - 1 ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetNumBitsWritten
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : GetNumBitsWritten ( ) const
{
2012-11-26 18:58:24 +00:00
return ( curSize < < 3 ) + writeBit ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetRemainingSpace
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : GetRemainingSpace ( ) const
{
2012-11-26 18:58:24 +00:00
return maxSize - GetSize ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetRemainingWriteBits
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : GetRemainingWriteBits ( ) const
{
2012-11-26 18:58:24 +00:00
return ( maxSize < < 3 ) - GetNumBitsWritten ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : SaveWriteState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : SaveWriteState ( int & s , int & b , uint64 & t ) const
{
2012-11-26 18:58:24 +00:00
s = curSize ;
b = writeBit ;
t = tempValue ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : RestoreWriteState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : RestoreWriteState ( int s , int b , uint64 t )
{
2012-11-26 18:58:24 +00:00
curSize = s ;
writeBit = b & 7 ;
2012-11-28 15:47:07 +00:00
if ( writeBit )
{
2012-11-26 18:58:24 +00:00
writeData [ curSize ] & = ( 1 < < writeBit ) - 1 ;
}
tempValue = t ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetReadCount
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : GetReadCount ( ) const
{
2012-11-26 18:58:24 +00:00
return readCount ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : SetReadCount
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : SetReadCount ( int bytes )
{
2012-11-26 18:58:24 +00:00
readCount = bytes ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetReadBit
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : GetReadBit ( ) const
{
2012-11-26 18:58:24 +00:00
return readBit ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : SetReadBit
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : SetReadBit ( int bit )
{
2012-11-26 18:58:24 +00:00
readBit = bit & 7 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetNumBitsRead
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : GetNumBitsRead ( ) const
{
2012-11-26 18:58:24 +00:00
return ( ( readCount < < 3 ) - ( ( 8 - readBit ) & 7 ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetRemainingData
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : GetRemainingData ( ) const
{
2012-11-26 18:58:24 +00:00
assert ( writeBit = = 0 ) ;
return curSize - readCount ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : GetRemainingReadBits
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : GetRemainingReadBits ( ) const
{
2012-11-26 18:58:24 +00:00
assert ( writeBit = = 0 ) ;
return ( curSize < < 3 ) - GetNumBitsRead ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : SaveReadState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : SaveReadState ( int & c , int & b ) const
{
2012-11-26 18:58:24 +00:00
assert ( writeBit = = 0 ) ;
c = readCount ;
b = readBit ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : RestoreReadState
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : RestoreReadState ( int c , int b )
{
2012-11-26 18:58:24 +00:00
assert ( writeBit = = 0 ) ;
readCount = c ;
readBit = b & 7 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : BeginWriting
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : BeginWriting ( )
{
2012-11-26 18:58:24 +00:00
curSize = 0 ;
overflowed = false ;
writeBit = 0 ;
tempValue = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteByteAlign
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteByteAlign ( )
{
2012-11-26 18:58:24 +00:00
// it is important that no uninitialized data slips in the msg stream,
// because we use memcmp to decide if entities have changed and wether we should transmit them
// this function has the potential to leave uninitialized bits into the stream,
// however idBitMsg::WriteBits is properly initializing the byte to 0 so hopefully we are still safe
// adding this extra check just in case
curSize + = writeBit ! = 0 ;
assert ( writeBit = = 0 | | ( ( writeData [ curSize - 1 ] > > writeBit ) = = 0 ) ) ; // had to early out writeBit == 0 because when writeBit == 0 writeData[curSize - 1] may be the previous byte written and trigger false positives
writeBit = 0 ;
tempValue = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteBool
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteBool ( bool c )
{
2012-11-26 18:58:24 +00:00
WriteBits ( c , 1 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteChar
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteChar ( int8 c )
{
2012-11-26 18:58:24 +00:00
WriteBits ( c , - 8 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteByte
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteByte ( uint8 c )
{
2012-11-26 18:58:24 +00:00
WriteBits ( c , 8 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteShort
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteShort ( int16 c )
{
2012-11-26 18:58:24 +00:00
WriteBits ( c , - 16 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteUShort
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteUShort ( uint16 c )
{
2012-11-26 18:58:24 +00:00
WriteBits ( c , 16 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteLong
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteLong ( int32 c )
{
2012-11-26 18:58:24 +00:00
WriteBits ( c , 32 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteLongLong
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteLongLong ( int64 c )
{
2012-11-26 18:58:24 +00:00
int a = c ;
int b = c > > 32 ;
WriteBits ( a , 32 ) ;
WriteBits ( b , 32 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteFloat
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteFloat ( float f )
{
WriteBits ( * reinterpret_cast < int * > ( & f ) , 32 ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteFloat
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteFloat ( float f , int exponentBits , int mantissaBits )
{
2012-11-26 18:58:24 +00:00
int bits = idMath : : FloatToBits ( f , exponentBits , mantissaBits ) ;
WriteBits ( bits , 1 + exponentBits + mantissaBits ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteAngle8
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteAngle8 ( float f )
{
2012-11-26 18:58:24 +00:00
WriteByte ( ANGLE2BYTE ( f ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteAngle16
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteAngle16 ( float f )
{
WriteShort ( ANGLE2SHORT ( f ) ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteDir
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteDir ( const idVec3 & dir , int numBits )
{
2012-11-26 18:58:24 +00:00
WriteBits ( DirToBits ( dir , numBits ) , numBits ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : BeginReading
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : BeginReading ( ) const
{
2012-11-26 18:58:24 +00:00
readCount = 0 ;
readBit = 0 ;
writeBit = 0 ;
tempValue = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadByteAlign
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : ReadByteAlign ( ) const
{
2012-11-26 18:58:24 +00:00
readBit = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadBool
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE bool idBitMsg : : ReadBool ( ) const
{
2012-11-26 18:58:24 +00:00
return ( ReadBits ( 1 ) = = 1 ) ? true : false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadChar
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : ReadChar ( ) const
{
return ( signed char ) ReadBits ( - 8 ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadByte
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : ReadByte ( ) const
{
return ( unsigned char ) ReadBits ( 8 ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadShort
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : ReadShort ( ) const
{
return ( short ) ReadBits ( - 16 ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadUShort
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : ReadUShort ( ) const
{
return ( unsigned short ) ReadBits ( 16 ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadLong
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int idBitMsg : : ReadLong ( ) const
{
2012-11-26 18:58:24 +00:00
return ReadBits ( 32 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadLongLong
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE int64 idBitMsg : : ReadLongLong ( ) const
{
2012-11-26 18:58:24 +00:00
int64 a = ReadBits ( 32 ) ;
int64 b = ReadBits ( 32 ) ;
int64 c = ( 0x00000000ffffffff & a ) | ( b < < 32 ) ;
return c ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadFloat
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE float idBitMsg : : ReadFloat ( ) const
{
2012-11-26 18:58:24 +00:00
float value ;
2012-11-28 15:47:07 +00:00
* reinterpret_cast < int * > ( & value ) = ReadBits ( 32 ) ;
2012-11-26 18:58:24 +00:00
return value ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadFloat
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE float idBitMsg : : ReadFloat ( int exponentBits , int mantissaBits ) const
{
2012-11-26 18:58:24 +00:00
int bits = ReadBits ( 1 + exponentBits + mantissaBits ) ;
return idMath : : BitsToFloat ( bits , exponentBits , mantissaBits ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadAngle8
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE float idBitMsg : : ReadAngle8 ( ) const
{
2012-11-26 18:58:24 +00:00
return BYTE2ANGLE ( ReadByte ( ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadAngle16
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE float idBitMsg : : ReadAngle16 ( ) const
{
2012-11-26 18:58:24 +00:00
return SHORT2ANGLE ( ReadShort ( ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadDir
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
ID_INLINE idVec3 idBitMsg : : ReadDir ( int numBits ) const
{
2012-11-26 18:58:24 +00:00
return BitsToDir ( ReadBits ( numBits ) , numBits ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteQuantizedFloat
= = = = = = = = = = = = = = = = = = = = = = = =
*/
template < int _max_ , int _numBits_ >
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteQuantizedFloat ( float value )
{
2012-11-26 18:58:24 +00:00
enum { storeMax = ( 1 < < ( _numBits_ - 1 ) ) - 1 } ;
2012-11-28 15:47:07 +00:00
if ( _max_ > storeMax )
{
2012-11-26 18:58:24 +00:00
// Scaling down (scale should be < 1)
2012-11-28 15:47:07 +00:00
const float scale = ( float ) storeMax / ( float ) _max_ ;
WriteBits ( idMath : : ClampInt ( - storeMax , storeMax , idMath : : Ftoi ( value * scale ) ) , - _numBits_ ) ;
}
else
{
2012-11-26 18:58:24 +00:00
// Scaling up (scale should be >= 1) (Preserve whole numbers when possible)
enum { scale = storeMax / _max_ } ;
2012-11-28 15:47:07 +00:00
WriteBits ( idMath : : ClampInt ( - storeMax , storeMax , idMath : : Ftoi ( value * scale ) ) , - _numBits_ ) ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : WriteQuantizedUFloat
= = = = = = = = = = = = = = = = = = = = = = = =
*/
template < int _max_ , int _numBits_ >
2012-11-28 15:47:07 +00:00
ID_INLINE void idBitMsg : : WriteQuantizedUFloat ( float value )
{
2012-11-26 18:58:24 +00:00
enum { storeMax = ( 1 < < _numBits_ ) - 1 } ;
2012-11-28 15:47:07 +00:00
if ( _max_ > storeMax )
{
2012-11-26 18:58:24 +00:00
// Scaling down (scale should be < 1)
2012-11-28 15:47:07 +00:00
const float scale = ( float ) storeMax / ( float ) _max_ ;
WriteBits ( idMath : : ClampInt ( 0 , storeMax , idMath : : Ftoi ( value * scale ) ) , _numBits_ ) ;
}
else
{
2012-11-26 18:58:24 +00:00
// Scaling up (scale should be >= 1) (Preserve whole numbers when possible)
enum { scale = storeMax / _max_ } ;
2012-11-28 15:47:07 +00:00
WriteBits ( idMath : : ClampInt ( 0 , storeMax , idMath : : Ftoi ( value * scale ) ) , _numBits_ ) ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadQuantizedFloat
= = = = = = = = = = = = = = = = = = = = = = = =
*/
template < int _max_ , int _numBits_ >
2012-11-28 15:47:07 +00:00
ID_INLINE float idBitMsg : : ReadQuantizedFloat ( ) const
{
2012-11-26 18:58:24 +00:00
enum { storeMax = ( 1 < < ( _numBits_ - 1 ) ) - 1 } ;
2012-11-28 15:47:07 +00:00
if ( _max_ > storeMax )
{
2012-11-26 18:58:24 +00:00
// Scaling down (scale should be < 1)
2012-11-28 15:47:07 +00:00
const float invScale = ( float ) _max_ / ( float ) storeMax ;
return ( float ) ReadBits ( - _numBits_ ) * invScale ;
}
else
{
2012-11-26 18:58:24 +00:00
// Scaling up (scale should be >= 1) (Preserve whole numbers when possible)
2012-11-28 15:47:07 +00:00
// Scale will be a whole number.
2012-11-26 18:58:24 +00:00
// We use a float to get rid of (potential divide by zero) which is handled above, but the compiler is dumb
const float scale = storeMax / _max_ ;
const float invScale = 1.0f / scale ;
2012-11-28 15:47:07 +00:00
return ( float ) ReadBits ( - _numBits_ ) * invScale ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idBitMsg : : ReadQuantizedUFloat
= = = = = = = = = = = = = = = = = = = = = = = =
*/
template < int _max_ , int _numBits_ >
2012-11-28 15:47:07 +00:00
float idBitMsg : : ReadQuantizedUFloat ( ) const
{
2012-11-26 18:58:24 +00:00
enum { storeMax = ( 1 < < _numBits_ ) - 1 } ;
2012-11-28 15:47:07 +00:00
if ( _max_ > storeMax )
{
2012-11-26 18:58:24 +00:00
// Scaling down (scale should be < 1)
2012-11-28 15:47:07 +00:00
const float invScale = ( float ) _max_ / ( float ) storeMax ;
return ( float ) ReadBits ( _numBits_ ) * invScale ;
}
else
{
2012-11-26 18:58:24 +00:00
// Scaling up (scale should be >= 1) (Preserve whole numbers when possible)
2012-11-28 15:47:07 +00:00
// Scale will be a whole number.
2012-11-26 18:58:24 +00:00
// We use a float to get rid of (potential divide by zero) which is handled above, but the compiler is dumb
2012-11-28 15:47:07 +00:00
const float scale = storeMax / _max_ ;
2012-11-26 18:58:24 +00:00
const float invScale = 1.0f / scale ;
2012-11-28 15:47:07 +00:00
return ( float ) ReadBits ( _numBits_ ) * invScale ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = =
WriteFloatArray
Writes all the values from the array to the bit message .
= = = = = = = = = = = = = = = =
*/
template < class _arrayType_ >
2012-11-28 15:47:07 +00:00
void WriteFloatArray ( idBitMsg & message , const _arrayType_ & sourceArray )
{
for ( int i = 0 ; i < idTupleSize < _arrayType_ > : : value ; + + i )
{
2012-11-26 18:58:24 +00:00
message . WriteFloat ( sourceArray [ i ] ) ;
}
}
/*
= = = = = = = = = = = = = = = =
WriteFloatArrayDelta
Writes _num_ values from the array to the bit message .
= = = = = = = = = = = = = = = =
*/
template < class _arrayType_ >
2012-11-28 15:47:07 +00:00
void WriteDeltaFloatArray ( idBitMsg & message , const _arrayType_ & oldArray , const _arrayType_ & newArray )
{
for ( int i = 0 ; i < idTupleSize < _arrayType_ > : : value ; + + i )
{
2012-11-26 18:58:24 +00:00
message . WriteDeltaFloat ( oldArray [ i ] , newArray [ i ] ) ;
}
}
/*
= = = = = = = = = = = = = = = =
ReadFloatArray
Reads _num_ values from the array to the bit message .
= = = = = = = = = = = = = = = =
*/
template < class _arrayType_ >
2012-11-28 15:47:07 +00:00
_arrayType_ ReadFloatArray ( const idBitMsg & message )
{
2012-11-26 18:58:24 +00:00
_arrayType_ result ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < idTupleSize < _arrayType_ > : : value ; + + i )
{
2012-11-26 18:58:24 +00:00
result [ i ] = message . ReadFloat ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return result ;
}
/*
= = = = = = = = = = = = = = = =
ReadDeltaFloatArray
Reads _num_ values from the array to the bit message .
= = = = = = = = = = = = = = = =
*/
template < class _arrayType_ >
2012-11-28 15:47:07 +00:00
_arrayType_ ReadDeltaFloatArray ( const idBitMsg & message , const _arrayType_ & oldArray )
{
2012-11-26 18:58:24 +00:00
_arrayType_ result ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < idTupleSize < _arrayType_ > : : value ; + + i )
{
2012-11-26 18:58:24 +00:00
result [ i ] = message . ReadDeltaFloat ( oldArray [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return result ;
}
# endif /* !__BITMSG_H__ */