263 lines
8.0 KiB
C++
263 lines
8.0 KiB
C++
//====== Copyright (c) 2014, Valve Corporation, All rights reserved. ========//
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are met:
|
|
//
|
|
// Redistributions of source code must retain the above copyright notice, this
|
|
// list of conditions and the following disclaimer.
|
|
// Redistributions in binary form must reproduce the above copyright notice,
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
// and/or other materials provided with the distribution.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
// THE POSSIBILITY OF SUCH DAMAGE.
|
|
//===========================================================================//
|
|
|
|
#ifndef DEMOFILEBITBUF_H
|
|
#define DEMOFILEBITBUF_H
|
|
|
|
#include <math.h>
|
|
#include "demofile.h"
|
|
|
|
// 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.0f/(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.0f/(COORD_DENOMINATOR_LOWPRECISION))
|
|
|
|
#define NORMAL_FRACTIONAL_BITS 11
|
|
#define NORMAL_DENOMINATOR ( (1<<(NORMAL_FRACTIONAL_BITS)) - 1 )
|
|
#define NORMAL_RESOLUTION (1.0f/(NORMAL_DENOMINATOR))
|
|
|
|
enum EBitCoordType
|
|
{
|
|
kCW_None,
|
|
kCW_LowPrecision,
|
|
kCW_Integral
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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;
|
|
}
|
|
|
|
class CBitRead
|
|
{
|
|
uint32 m_nInBufWord;
|
|
int m_nBitsAvail;
|
|
uint32 const *m_pDataIn;
|
|
uint32 const *m_pBufferEnd;
|
|
uint32 const *m_pData;
|
|
|
|
bool m_bOverflow;
|
|
int m_nDataBits;
|
|
size_t m_nDataBytes;
|
|
|
|
static const uint32 s_nMaskTable[ 33 ]; // 0 1 3 7 15 ..
|
|
|
|
public:
|
|
CBitRead( const void *pData, int nBytes, int nBits = -1 )
|
|
{
|
|
m_bOverflow = false;
|
|
m_nDataBits = -1;
|
|
m_nDataBytes = 0;
|
|
StartReading( pData, nBytes, 0, nBits );
|
|
}
|
|
|
|
CBitRead( void )
|
|
{
|
|
m_bOverflow = false;
|
|
m_nDataBits = -1;
|
|
m_nDataBytes = 0;
|
|
}
|
|
|
|
void SetOverflowFlag( void )
|
|
{
|
|
m_bOverflow = true;
|
|
}
|
|
|
|
bool IsOverflowed( void ) const
|
|
{
|
|
return m_bOverflow;
|
|
}
|
|
|
|
int Tell( void ) const
|
|
{
|
|
return GetNumBitsRead();
|
|
}
|
|
|
|
size_t TotalBytesAvailable( void ) const
|
|
{
|
|
return m_nDataBytes;
|
|
}
|
|
|
|
int GetNumBitsLeft( void ) const
|
|
{
|
|
return m_nDataBits - Tell();
|
|
}
|
|
|
|
int GetNumBytesLeft( void ) const
|
|
{
|
|
return GetNumBitsLeft() >> 3;
|
|
}
|
|
|
|
bool Seek( int nPosition );
|
|
|
|
bool SeekRelative( int nOffset )
|
|
{
|
|
return Seek( GetNumBitsRead() + nOffset );
|
|
}
|
|
|
|
unsigned char const * GetBasePointer()
|
|
{
|
|
return reinterpret_cast< unsigned char const *>( m_pData );
|
|
}
|
|
|
|
void StartReading( const void *pData, int nBytes, int iStartBit = 0, int nBits = -1 );
|
|
|
|
int GetNumBitsRead( void ) const;
|
|
int GetNumBytesRead( void ) const;
|
|
|
|
void GrabNextDWord( bool bOverFlowImmediately = false );
|
|
void FetchNext( void );
|
|
unsigned int ReadUBitLong( int numbits );
|
|
int ReadSBitLong( int numbits );
|
|
unsigned int ReadUBitVar( void );
|
|
unsigned int PeekUBitLong( int numbits );
|
|
bool ReadBytes( void *pOut, int nBytes );
|
|
|
|
// Returns 0 or 1.
|
|
int ReadOneBit( void );
|
|
int ReadLong( void );
|
|
int ReadChar( void );
|
|
int ReadByte( void );
|
|
int ReadShort( void );
|
|
int ReadWord( void );
|
|
float ReadFloat( void );
|
|
void ReadBits( void *pOut, int nBits );
|
|
|
|
float ReadBitCoord();
|
|
float ReadBitCoordMP( EBitCoordType coordType );
|
|
float ReadBitCellCoord( int bits, EBitCoordType coordType );
|
|
float ReadBitNormal();
|
|
void ReadBitVec3Coord( Vector& fa );
|
|
void ReadBitVec3Normal( Vector& fa );
|
|
void ReadBitAngles( QAngle& fa );
|
|
float ReadBitAngle( int numbits );
|
|
float ReadBitFloat( void );
|
|
|
|
// 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 varint encoded integer
|
|
uint32 ReadVarInt32();
|
|
uint64 ReadVarInt64();
|
|
int32 ReadSignedVarInt32() { return bitbuf::ZigZagDecode32( ReadVarInt32() ); }
|
|
int64 ReadSignedVarInt64() { return bitbuf::ZigZagDecode64( ReadVarInt64() ); }
|
|
};
|
|
|
|
inline unsigned int CBitRead::PeekUBitLong(int numbits)
|
|
{
|
|
int nSaveBA = m_nBitsAvail;
|
|
int nSaveW = m_nInBufWord;
|
|
uint32 const *pSaveP = m_pDataIn;
|
|
unsigned int nRet = ReadUBitLong(numbits);
|
|
m_nBitsAvail = nSaveBA;
|
|
m_nInBufWord = nSaveW;
|
|
m_pDataIn = pSaveP;
|
|
return nRet;
|
|
}
|
|
|
|
inline int CBitRead::ReadLong(void)
|
|
{
|
|
return (int)ReadUBitLong(sizeof(long) << 3);
|
|
}
|
|
|
|
inline float CBitRead::ReadFloat(void)
|
|
{
|
|
uint32 nUval = ReadUBitLong(sizeof(long) << 3);
|
|
return *((float *)&nUval);
|
|
}
|
|
|
|
#ifndef MIN
|
|
#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
|
|
#endif
|
|
|
|
#endif |