Files
FC1/CryCommon/Stream.h
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

1171 lines
27 KiB
C++

//////////////////////////////////////////////////////////////////////
//
// CryCommon source code
//
// File: stream.h
// Description: stream class
//
// History:
// -07/25/2001:Created by Alberto Demichelis
// -07/08/2002:Cleaned up, added compression Martin Mittring
//
//////////////////////////////////////////////////////////////////////
#ifndef _STREAM_H_
#define _STREAM_H_
// -------------------------------------------
// debugging defines:
//#define STREAM_ACTIVETYPECHECK // add a lot of bit for typechecking the steam
// -------------------------------------------
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// size in bytes
#define DEFAULT_STREAM_BYTESIZE 1124
#define MAX_STRING_SIZE 256
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif //CHAR_BIT
#define DIV8(n)((n) >> 3)
#define MODULO8(n)((n)&0x00000007)
#define BITS2BYTES(n)(MODULO8((n))?(DIV8((n)) + 1):DIV8((n)))
#define BYTES2BITS(n)((n) << 3)
#define GET_BYTE_INDEX(n) DIV8((n))
#include <string>
#include "Cry_Math.h" // Vec3
#include "ISystem.h" // ISystem
#include "IStreamEngine.h" // IStreamEngine
#include "IGame.h" // IGame
#include "INetwork.h" // INetwork
#include "ICompressionHelper.h" // ICompressionHelper
#include "ILog.h" // ILOg
class CStream;
#ifdef STREAM_ACTIVETYPECHECK
#define STREAM_VERIFY_TYPE_READ(a) { \
if((GetISystem()->GetStreamEngine()->GetStreamCompressionMask()&0x80)!=0) \
{ \
unsigned char t1=0,t2=(a); _Read(t1); \
if(t1!=t2) \
{ \
char str[256]; \
sprintf(str,"Entity read typedcookie error %d!=%d file '%s' @ line %d", \
(DWORD)t1,(DWORD)t2,__FILE__,__LINE__); \
Debug(str); \
assert(0); \
return false; \
} \
}}
#define STREAM_VERIFY_TYPE_WRITE(a) { \
if((GetISystem()->GetStreamEngine()->GetStreamCompressionMask()&0x80)!=0) \
{ \
unsigned char t=(a); _Write(t); \
}}
#else // !STREAM_ACTIVETYPECHECK
#define STREAM_VERIFY_TYPE_READ(a) {}
#define STREAM_VERIFY_TYPE_WRITE(a) {}
#endif // STREAM_ACTIVETYPECHECK
struct IStreamAllocator
{
virtual void *Alloc(size_t size)=0;
virtual void *Realloc(void *old,size_t size)=0;
virtual void Free(void *old)=0;
};
struct IStreamData
{
virtual bool Read( CStream &inStream ) const=0;
virtual bool Write( CStream &inStream ) const=0;
};
//#define OLD_STREAM
class CStream
{
public:
//! default constructor
CStream()
{
m_sa=NULL;
m_bStackBuffer=true;
m_dwAllocatedBitSize = DEFAULT_STREAM_BYTESIZE*8;
m_pBuffer=&m_vBuffer[0];
Reset();
if (m_dwAllocatedBitSize < 1)
CryError("CStream:CStream()");
m_iStreamVersion=999999; // newest
}
//! constructor
//! \param indwByteSize >0
//! \param sa pointer to the memory allocation helper, must not be 0
CStream( const size_t indwByteSize, IStreamAllocator *sa )
{
assert(indwByteSize>0);
assert(sa);
m_sa=sa;
m_bStackBuffer=false;
m_dwAllocatedBitSize = indwByteSize*8;
m_pBuffer=(BYTE *)m_sa->Alloc(BITS2BYTES(m_dwAllocatedBitSize));//new BYTE[BITS2BYTES(m_dwAllocatedBitSize)];
Reset();
m_iStreamVersion=999999; // newest
}
//! constructor (used by physics system for physics on demand to store physics state for not demanded phyiscs objects)
//! \param indwByteSize
//! \param inpBuffer
CStream( const size_t indwByteSize, BYTE *inpBuffer )
{
assert(indwByteSize);
assert(inpBuffer);
m_sa=NULL;
m_bStackBuffer=true;
m_dwAllocatedBitSize = m_dwBitSize = indwByteSize*8;
m_pBuffer=inpBuffer;
m_dwReadBitPos = 0;
m_nCheckPoint = 0;
m_iStreamVersion=999999; // newest
}
//! destructor
virtual ~CStream()
{
if(!m_bStackBuffer && m_pBuffer)
m_sa->Free(m_pBuffer);
m_pBuffer=NULL;
}
//! copy constructor
CStream(const CStream& s)
{
m_iStreamVersion=s.m_iStreamVersion;
m_pBuffer=&m_vBuffer[0];
if(s.m_bStackBuffer)
{
m_dwAllocatedBitSize = s.GetAllocatedSize();
if (m_dwAllocatedBitSize < 1)
CryError("CStream:GetAllocatedSize");
}
else
{
//m_dwAllocatedBitSize = s.GetAllocatedSize();
//m_pBuffer=new BYTE[BITS2BYTES(m_dwAllocatedBitSize)];
CryError("CStream:CStream");
}
m_bStackBuffer=s.m_bStackBuffer;
Reset();
if(s.GetSize())
{
SetSize(s.GetSize());
memcpy(GetPtr(),s.GetPtr(),BITS2BYTES(s.GetSize()));
}
}
//! assignment operator
CStream& operator =(const CStream &s)
{
m_iStreamVersion=s.m_iStreamVersion;
if(GetAllocatedSize() < s.GetAllocatedSize())
{
CryError("CStream:operator(=)");
}
Reset();
if(s.GetSize())
{
SetSize(s.GetSize());
memcpy(GetPtr(),s.GetPtr(),BITS2BYTES(s.GetSize()));
}
return *this;
}
void CStream::Debug( const char *inTxt=0 );
//! set a bit at the specified position in the bitstream
bool SetBit(size_t nPos, DWORD_PTR nValue);
//! get a bit at the specified position in the bitstream
bool GetBit(size_t nPos,bool &bBit);
//! append nSize bits at the end
bool WriteBits(BYTE *pBits, size_t nSize);
//! read nSize bits from the current read pos in the bitstream
bool ReadBits(BYTE *pBits, size_t nSize);
//! write a number into the bitsream using nSize bits
bool WriteNumberInBits(int n,size_t nSize);
bool WriteNumberInBits(unsigned int n,size_t nSize);
//! read a number into the bitsream using nSize bits
bool ReadNumberInBits(int &n,size_t nSize);
bool ReadNumberInBits(unsigned int &n,size_t nSize);
//! read a nSize bits from nPos in the bitstream
bool GetBits(BYTE *pBits, size_t nPos, size_t nSize);
//! write a nSize bits from nPos in the bitstream
bool SetBits(BYTE *pBits, size_t nPos, size_t nSize);
//! read a variable from the bitstream an increament the read position
//@{
bool Read(unsigned char &uc);
bool Read(unsigned short &us);
bool Read(unsigned int &ui);
bool Read(char &c);
bool Read(short &s);
bool Read(int &i);
bool Read(float &f);
bool Read(bool &b);
bool Read(char *psz, const DWORD indwBufferSize);
bool Read(string &str);
bool Read(Vec3 &v);
//!read all remaining data in the stream starting from the read pos
bool Read(CStream &stm);
//!read packed
bool ReadPkd(unsigned char &uc);
bool ReadPkd(unsigned short &us);
bool ReadPkd(unsigned int &ui);
bool ReadPkd(char &c);
bool ReadPkd(short &c);
bool ReadPkd(int &i);
//! packed, inType specifies the compression mode
bool ReadPkd( IStreamData &outData );
//@}
bool _Read(unsigned char &uc); // not typechecked
//! write a variable from the bitstream an increament the read position
//@{
bool Write(unsigned char uc);
bool Write(unsigned short us);
bool Write(unsigned int ui);
bool Write(char c);
bool Write(short c);
bool Write(int i);
bool Write(float f);
bool Write(bool b);
bool Write(const char *psz);
bool Write(const string &str);
bool Write(CStream &stm);
bool Write(const Vec3 &v);
bool _Write(unsigned char c); // not typechecked
bool WritePkd(unsigned char uc);
bool WritePkd(unsigned short us);
bool WritePkd(unsigned int ui);
bool WritePkd(char c);
bool WritePkd(short c);
bool WritePkd(int i);
//! packed, inType specifies the compression mode
//! /param v is modified to the reconstruction of the compressed value
bool WritePkd( const IStreamData &inData );
bool WritePacked(unsigned int ui);
#if defined(WIN64)
// Win64 defines size_t as 64-bit integer and there's an ambiguity between converting it to long or int automatically
// if we need to save/restore it really as a 64-bit int, care must be taken to match the write/read functions in 32-bit version
bool WritePacked(size_t sz) {return WritePacked((unsigned int)sz);}
bool ReadPacked(size_t &sz) { return ReadPacked((unsigned int&)sz); }
#endif
bool ReadPacked(unsigned int &ui);
//@}
//! write data to stream.
//! @param nSize size of buffer in bytes.
bool WriteData( const void *pBuffer,int nSize ) { return WriteBits( (BYTE*)pBuffer,nSize*8 ); };
//! read data from stream.
//! @param nSize size of buffer in bytes.
bool ReadData( void *pBuffer,int nSize ) { return ReadBits( (BYTE*)pBuffer,nSize*8 ); };
//! write a variable from the bitstream starting from the dwPos bit
//@{
bool GetAt(size_t dwPos, BYTE &c);
bool GetAt(size_t dwPos, WORD &w);
bool GetAt(size_t dwPos, DWORD &dw);
#if defined(WIN64) || defined(LINUX64)
bool GetAt(size_t dwPos, ULONG_PTR &dw);
#endif
//@}
//! move the read pointer to the dwPos bit
bool Seek(size_t dwPos = 0);
//! Get the sizeof the stream in bits
size_t GetSize()const {return m_dwBitSize;}
//! Set the sizeof the stream in bits
bool SetSize( const size_t indwBitSize )
{
if(m_dwAllocatedBitSize<indwBitSize)
{
if(!Resize(indwBitSize))
return false;
}
m_dwBitSize = indwBitSize;
return true;
}
//! Set the number of unreaded bites into the stream
size_t GetNumUnreadedBytes(){return m_dwBitSize - m_dwReadBitPos;}
//! Get the number of allocated bits into the stream(max size)
size_t GetAllocatedSize() const{ return m_dwAllocatedBitSize;}
//! get the current read position
size_t GetReadPos(){return m_dwReadBitPos;}
//! copy the stream into p
bool GetBuffer(BYTE *p, size_t nMaxBuf)
{
if (nMaxBuf < m_dwBitSize)
return false;
memcpy(p, GetPtr(), BITS2BYTES(m_dwBitSize));
return true;
}
//! get a pointer to the stream buffer
BYTE *GetPtr() const
{
return (BYTE *)m_pBuffer;
}
//! legacy
BYTE *GetUnreadedPtr()
{
return &m_vBuffer[m_dwReadBitPos];
}
//! (END OF STREAM)return true if the read pointer is at the end of the stream
bool EOS()
{
return m_dwBitSize<=m_dwReadBitPos;
}
//! cleanup the buffer ans reset size and read pointer to 0
void Reset();
//only for debug
// unsigned int TUNING_EvaluateRLE();
void SetCheckPoint(){m_nCheckPoint=m_dwReadBitPos;}
void AlignRead() { /*m_dwReadBitPos = (m_dwReadBitPos+7)&~7;*/ };
void AlignWrite() { /*m_dwBitSize = (m_dwBitSize +7)&~7;*/ }; // cannot overflow m_dwAllocatedBitSize if byte-aligned
//! resize the stream (is in bits)
bool Resize( const size_t iniBitSize )
{
if(!m_sa)return false;
size_t oldsize=BITS2BYTES(m_dwAllocatedBitSize);
m_pBuffer=(BYTE *)m_sa->Realloc(m_pBuffer,BITS2BYTES(iniBitSize));
if(oldsize<BITS2BYTES(iniBitSize))
memset(&m_pBuffer[oldsize],0,BITS2BYTES(iniBitSize)-oldsize);
m_dwAllocatedBitSize=iniBitSize;
return true;
}
//! used for to be able to load old savegames
int GetStreamVersion() const { return m_iStreamVersion; }
//! used for to be able to load old savegames
void SetStreamVersion( const int iVersion ) { m_iStreamVersion=iVersion; }
private: // -----------------------------------------------------------------------
unsigned int __htonl(unsigned int n){
return (unsigned int)(((n&0xFF000000)>>24) |
((n&0x00FF0000)>>8) |
((n&0x0000FF00)<<8) |
((n&0x000000FF)<<24));
}
unsigned int __ntohl(unsigned int n){
return (unsigned int)(((n&0xFF000000)>>24) |
((n&0x00FF0000)>>8) |
((n&0x0000FF00)<<8) |
((n&0x000000FF)<<24));
}
BYTE * m_pBuffer; //!<
BYTE m_vBuffer[DEFAULT_STREAM_BYTESIZE]; //!<
size_t m_dwAllocatedBitSize; //!< allocated size is in bits
size_t m_dwBitSize; //!< payload size is in bits
size_t m_dwReadBitPos; //!< pos in bits
size_t m_nCheckPoint; //!<
IStreamAllocator * m_sa; //!< might be 0 if there was no allocator specified
bool m_bStackBuffer; //!<
int m_iStreamVersion; //!< 999999=newest, PATCH1_SAVEVERSION, SAVEVERSION, ..
};
#define _GROW() {if(!Resize(m_dwAllocatedBitSize*2))return false;}
//! BIT are nubered as follow
//! [0 1 2 3 4 5 6 7|8 9 10 11 12 13 14...
//! for instance if you want write 3 bits you should shift your data of 5 bits
inline bool CStream::SetBit(size_t nPos, DWORD_PTR nValue)
{
if (nPos>=GetAllocatedSize())
{
if(!Resize(m_dwAllocatedBitSize*2))
{
Debug("SetBit resize failed");
return false;
}
}
BYTE *pBuf = GetPtr();
pBuf += GET_BYTE_INDEX(nPos);
if (nValue)
*pBuf|=0x80 >> MODULO8(nPos);
else
*pBuf&=~(0x80 >> MODULO8(nPos));
return true;
}
//////////////////////////////////////////////////////////////////////////
inline void CStream::Debug( const char *inTxt )
{
assert(0);
#if (defined(WIN32)||defined(WIN64))
{
char str[256];
sprintf(str,"CStream::Debug (%d/%d/%d %c)%s\n",m_dwReadBitPos,m_dwBitSize,m_dwAllocatedBitSize,m_sa?'t':'f',inTxt?inTxt:"");
OutputDebugString(str);
GetISystem()->GetILog()->LogError("%s",str);
}
#endif
}
inline bool CStream::GetBit(size_t nPos,bool &bBit)
{
if (nPos>=m_dwBitSize)
return false;
BYTE *pBuf = GetPtr();
pBuf += GET_BYTE_INDEX(nPos);
bBit=(*pBuf&(0x80 >> (MODULO8(nPos)))) != 0;
return true;
}
inline bool CStream::SetBits(BYTE *pBits, size_t nPos, size_t nSize)
{
#ifdef OLD_STREAM
BYTE *pBuf, *pSource;
DWORD_PTR nValue;
#endif
if ((nPos + nSize)>GetAllocatedSize())
{
_GROW();
}
BYTE *pBuffer=GetPtr();
// the following code can be optimized
#ifdef OLD_STREAM
for (size_t n = 0; n < nSize; n++)
{
pBuf = pBuffer;
pSource = pBits;
pSource += GET_BYTE_INDEX(n);
nValue = ((*pSource&(0x80 >> (MODULO8(n)))) != 0);
pBuf += GET_BYTE_INDEX(nPos + n);
if (nValue)
*pBuf|=0x80 >> MODULO8(nPos + n);
else
*pBuf&=~(0x80 >> MODULO8(nPos + n));
}
#else
BYTE *pSrc = pBits;
BYTE *pStart = &pBuffer[GET_BYTE_INDEX(nPos)];// + (nPos >> 3);
BYTE *pEnd = pBuffer + ((nSize + nPos - 1) >> 3);
size_t nUpShift = MODULO8(nPos);
size_t nDownShift= 8 - nUpShift;
BYTE cLastMask = 0xFF << (7-MODULO8((nPos + nSize - 1)));
BYTE cStartMask = 0xFF << nDownShift;
BYTE cCurrent = *pSrc++;
BYTE end=*pEnd;
*pStart=(cCurrent >> nUpShift) | (*pStart & cStartMask);
pStart++;
while(pStart <= pEnd)
{
BYTE next = *pSrc++;
*pStart++ = (cCurrent << nDownShift) | (next >> nUpShift);
cCurrent = next;
}
*pEnd &= cLastMask;
//m_dwBitSize += nSize;
#endif
return true;
}
inline bool CStream::GetBits(BYTE *pBits, size_t nPos, size_t nSize)
{
#ifdef OLD_STREAM
BYTE *pBuf, *pDest;
DWORD_PTR nValue;
#endif
BYTE *pBuffer=GetPtr();
if ((nPos + nSize)>m_dwBitSize)
return false;
// the following code can be optimized
#ifdef OLD_STREAM
for (size_t n = 0; n < nSize; n++)
{
pBuf = pBuffer;
pBuf += GET_BYTE_INDEX(nPos + n);
pDest = pBits;
pDest += GET_BYTE_INDEX(n);
nValue = ((*pBuf&(0x80 >> (MODULO8(nPos + n)))) != 0);
if (nValue)
*pDest|=0x80 >> MODULO8(n);
else
*pDest&=~(0x80 >> MODULO8(n));
}
#else
BYTE *stPtr = pBuffer + (nPos >> 3);
size_t byteCount = (nSize + 7) >> 3;
BYTE *ptr = (BYTE *) pBits;
size_t downShift = nPos & 0x7;
size_t upShift = 8 - downShift;
BYTE curB = *stPtr;
while(byteCount--)
{
BYTE nextB = *++stPtr;
*ptr++ = (curB << downShift) | (nextB >> upShift);
curB = nextB;
};
// if(nSize&7) *(ptr-1) &= (1<<(nSize&7))-1;
#endif
return true;
}
inline bool CStream::WriteBits(BYTE *pBits, size_t nSize)
{
if (!SetBits(pBits, m_dwBitSize, nSize))
return false;
m_dwBitSize += nSize;
return true;
}
inline bool CStream::ReadBits(BYTE *pBits, size_t nSize)
{
if (!GetBits(pBits, m_dwReadBitPos, nSize))
return false;
m_dwReadBitPos += nSize;
return true;
}
inline bool CStream::WriteNumberInBits(unsigned int n,size_t nSize)
{
STREAM_VERIFY_TYPE_WRITE(50);
assert(nSize>0 && nSize<=32);
unsigned int nSwapped;
if(nSize>32)
{
CryError("CStream:WriteNumberinBits");
return false;
}
n=n<<(32-nSize);
nSwapped=__htonl(n);
return WriteBits((BYTE *)&nSwapped,nSize);
}
inline bool CStream::ReadNumberInBits(unsigned int &n,size_t nSize)
{
STREAM_VERIFY_TYPE_READ(50);
assert(nSize>0 && nSize<=32);
unsigned int nSwapped;
if(nSize>32)
{
CryError("CStream:ReadNumberinBits ulong %d>32",(int)nSize);
return false;
}
if(!ReadBits((BYTE *)&nSwapped,nSize))return false;
n=__ntohl(nSwapped);
n=n>>(32-nSize);
return true;
}
inline bool CStream::WriteNumberInBits(int n,size_t nSize)
{
STREAM_VERIFY_TYPE_WRITE(51);
assert(nSize>0 && nSize<=32);
unsigned int nSwapped;
if(nSize>32)
{
CryError("CStream:WriteNumberinBits");
return false;
}
n=n<<(32-nSize);
nSwapped=__htonl((unsigned int)n);
return WriteBits((BYTE *)&nSwapped,nSize);
}
inline bool CStream::ReadNumberInBits(int &n,size_t nSize)
{
STREAM_VERIFY_TYPE_READ(51);
assert(nSize>0 && nSize<=32);
unsigned int nSwapped=0;
if(nSize>32)
{
CryError("CStream:ReadNumberinBits int %d>32",(int)nSize);
return false;
}
if(!ReadBits((BYTE *)&nSwapped,(nSize)))return false;
n=__ntohl((unsigned int)nSwapped);
n=(n>>(32-nSize))&(0xFFFFFFFF>>(32-nSize));
return true;
}
inline void CStream::Reset()
{
memset(GetPtr(), 0, BITS2BYTES(GetAllocatedSize()));
m_dwBitSize = 0;
m_dwReadBitPos = 0;
m_nCheckPoint = 0;
}
// *************************************
// ************** READ *****************
// *************************************
// not typechecked
inline bool CStream::_Read(unsigned char &uc)
{
return ReadBits((BYTE *)&uc, BYTES2BITS(sizeof(unsigned char)));
}
inline bool CStream::Read(bool &b)
{
STREAM_VERIFY_TYPE_READ(9);
static bool bRet;
static unsigned char cTemp;
cTemp=0;
bRet=GetBit(m_dwReadBitPos,b);
if(bRet)
m_dwReadBitPos++;
return bRet;
}
inline bool CStream::Read(unsigned char &uc)
{
STREAM_VERIFY_TYPE_READ(10);
return ReadBits((BYTE *)&uc, BYTES2BITS(sizeof(unsigned char)));
}
inline bool CStream::Read(unsigned short &us)
{
STREAM_VERIFY_TYPE_READ(11);
return ReadBits((BYTE *)&us, BYTES2BITS(sizeof(unsigned short)));
}
inline bool CStream::Read(unsigned int &ul)
{
STREAM_VERIFY_TYPE_READ(12);
return ReadBits((BYTE *)&ul, BYTES2BITS(sizeof(unsigned int)));
}
inline bool CStream::Read(char &c)
{
STREAM_VERIFY_TYPE_READ(13);
return ReadBits((BYTE *)&c, BYTES2BITS(sizeof(char)));
}
inline bool CStream::Read(short &s)
{
STREAM_VERIFY_TYPE_READ(14);
return ReadBits((BYTE *)&s, BYTES2BITS(sizeof(short)));
}
inline bool CStream::Read(int &i)
{
STREAM_VERIFY_TYPE_READ(15);
return ReadBits((BYTE *)&i, BYTES2BITS(sizeof(int)));
}
inline bool CStream::Read(float &f)
{
STREAM_VERIFY_TYPE_READ(16);
return ReadBits((BYTE *)&f, BYTES2BITS(sizeof(float)));
}
inline bool CStream::Read( char *psz, const DWORD indwBufferSize )
{
STREAM_VERIFY_TYPE_READ(30);
ICompressionHelper *pCHelper = GetISystem()->GetINetwork()->GetCompressionHelper();
return pCHelper->Read(*this,psz,indwBufferSize);
}
inline bool CStream::Read(string &str)
{
static char cTemp[MAX_STRING_SIZE];
STREAM_VERIFY_TYPE_READ(30);
ICompressionHelper *pCHelper = GetISystem()->GetINetwork()->GetCompressionHelper();
bool bRet = pCHelper->Read(*this,cTemp,MAX_STRING_SIZE);
str=cTemp;
return bRet;
}
inline bool CStream::Read(Vec3 &v)
{
STREAM_VERIFY_TYPE_READ(31);
Read(v.x);
Read(v.y);
return Read(v.z);
}
inline bool CStream::Read(CStream &stm)
{
size_t nToRead=GetSize()-GetReadPos();
if(nToRead>0 && ((stm.GetSize()+nToRead)<= stm.GetAllocatedSize()))
{
static BYTE cTemp[MAX_STRING_SIZE];
size_t readed;
while(nToRead>0)
{
readed=min((int)nToRead,(int)BYTES2BITS(100));
if(!ReadBits(cTemp,readed))return false;
stm.WriteBits(cTemp,readed);
nToRead-=readed;
}
return true;
}
return false;
}
// *************************************
// ************** WRITE ****************
// *************************************
// not typechecked
inline bool CStream::_Write(unsigned char uc)
{
return WriteBits((BYTE *)&uc, BYTES2BITS(sizeof(unsigned char)));
}
inline bool CStream::Write(bool b)
{
STREAM_VERIFY_TYPE_WRITE(9);
bool bRet=SetBit(m_dwBitSize,b);
if(bRet)
m_dwBitSize++;
return bRet;
}
inline bool CStream::Write(unsigned char uc)
{
STREAM_VERIFY_TYPE_WRITE(10);
return WriteBits((BYTE *)&uc, BYTES2BITS(sizeof(unsigned char)));
}
inline bool CStream::Write(unsigned short us)
{
STREAM_VERIFY_TYPE_WRITE(11);
return WriteBits((BYTE *)&us, BYTES2BITS(sizeof(unsigned short)));
}
inline bool CStream::Write(unsigned int ul)
{
STREAM_VERIFY_TYPE_WRITE(12);
return WriteBits((BYTE *)&ul, BYTES2BITS(sizeof(unsigned int)));
}
inline bool CStream::Write(char c)
{
STREAM_VERIFY_TYPE_WRITE(13);
return WriteBits((BYTE *)&c, BYTES2BITS(sizeof(char)));
}
inline bool CStream::Write(short s)
{
STREAM_VERIFY_TYPE_WRITE(14);
return WriteBits((BYTE *)&s, BYTES2BITS(sizeof(short)));
}
inline bool CStream::Write(int i)
{
STREAM_VERIFY_TYPE_WRITE(15);
return WriteBits((BYTE *)&i, BYTES2BITS(sizeof(int)));
}
inline bool CStream::Write(float f)
{
STREAM_VERIFY_TYPE_WRITE(16);
return WriteBits((BYTE *)&f, BYTES2BITS(sizeof(float)));
}
inline bool CStream::Write(CStream &stm)
{
if ((m_dwBitSize + stm.GetSize()) >= GetAllocatedSize())
{
_GROW()
}
WriteBits(stm.GetPtr(), stm.GetSize());
return true;
}
inline bool CStream::Write(const char *psz)
{
STREAM_VERIFY_TYPE_WRITE(30);
ICompressionHelper *pCHelper = GetISystem()->GetINetwork()->GetCompressionHelper();
return pCHelper->Write(*this,psz);
}
inline bool CStream::Write(const string &str)
{
return Write(str.c_str());
}
inline bool CStream::Write(const Vec3 &v)
{
STREAM_VERIFY_TYPE_WRITE(31);
Write(v.x);
Write(v.y);
return Write(v.z);
}
///////////////////////////////////////////////////////
inline bool CStream::WritePkd(unsigned char uc)
{
STREAM_VERIFY_TYPE_WRITE(40);
if(uc<=0x0F)
{
uc<<=4;
Write(true);
return WriteBits((BYTE *)&uc,4);
}
else{
Write(false);
return WriteBits((BYTE *)&uc, BYTES2BITS(sizeof(unsigned char)));
}
}
inline bool CStream::WritePkd(unsigned short us)
{
STREAM_VERIFY_TYPE_WRITE(41);
if(us<=0xFF)
{
Write(true);
return Write((BYTE)us);
}
else{
Write(false);
return WriteBits((BYTE *)&us, BYTES2BITS(sizeof(unsigned short)));
}
}
inline bool CStream::WritePkd(unsigned int ul)
{
STREAM_VERIFY_TYPE_WRITE(42);
if(ul<=0xFFFF)
{
Write(true);
return Write((unsigned short)ul);
}
else{
Write(false);
return WriteBits((BYTE *)&ul, BYTES2BITS(sizeof(unsigned int)));
}
}
inline bool CStream::WritePkd(char c)
{
STREAM_VERIFY_TYPE_WRITE(43);
return WriteBits((BYTE *)&c, BYTES2BITS(sizeof(char)));
}
inline bool CStream::WritePkd(short s)
{
STREAM_VERIFY_TYPE_WRITE(44);
if(abs(s)<=0xFF)
{
Write(true);
Write(s<0);
return Write((BYTE)abs(s));
}
else{
Write(false);
return WriteBits((BYTE *)&s, BYTES2BITS(sizeof(short)));
}
}
inline bool CStream::WritePkd(int i)
{
STREAM_VERIFY_TYPE_WRITE(45);
if(abs(i)<=0xFFFF)
{
Write(true);
Write(i<0);
return Write((unsigned short)abs(i));
}
else{
Write(false);
return WriteBits((BYTE *)&i, BYTES2BITS(sizeof(int)));
}
}
///////////////////////////////////////////////////////
inline bool CStream::ReadPkd(unsigned char &uc)
{
STREAM_VERIFY_TYPE_READ(40);
bool comp;
bool ret;
Read(comp);
if(comp)
{
BYTE b;
ret=ReadBits((BYTE *)&b, 4);
b>>=4;
uc=b;
}
else{
ret=ReadBits((BYTE *)&uc, BYTES2BITS(sizeof(unsigned char)));
}
return ret;
}
inline bool CStream::ReadPkd(unsigned short &us)
{
STREAM_VERIFY_TYPE_READ(41);
bool comp;
bool ret;
Read(comp);
if(comp)
{
BYTE b;
ret=Read(b);
us=b;
}
else{
ret=ReadBits((BYTE *)&us, BYTES2BITS(sizeof(unsigned short)));
}
return ret;
}
inline bool CStream::ReadPkd(unsigned int &ul)
{
STREAM_VERIFY_TYPE_READ(42);
bool ret;
bool comp;
ret=Read(comp);
if(comp){
unsigned short us;
ret=Read(us);
ul=us;
}
else{
ret=ReadBits((BYTE *)&ul, BYTES2BITS(sizeof(unsigned int)));
}
return ret;
}
inline bool CStream::ReadPkd(char &c)
{
STREAM_VERIFY_TYPE_READ(43);
return ReadBits((BYTE *)&c, BYTES2BITS(sizeof(char)));
}
inline bool CStream::ReadPkd(short &s)
{
STREAM_VERIFY_TYPE_READ(44);
bool comp,ret,sign;
Read(comp);
if(comp)
{
BYTE b;
Read(sign);
ret=Read(b);
s=sign?-b:b;
}
else
{
ret=ReadBits((BYTE *)&s, BYTES2BITS(sizeof(short)));
}
return ret;
}
inline bool CStream::ReadPkd(int &i)
{
STREAM_VERIFY_TYPE_READ(45);
bool comp,ret,sign;
Read(comp);
if(comp)
{
unsigned short b;
Read(sign);
ret=Read(b);
i=sign?-b:b;
}
else
ret=ReadBits((BYTE *)&i, BYTES2BITS(sizeof(int)));
return ret;
}
inline bool CStream::ReadPkd( IStreamData &outData )
{
return outData.Read(*this);
}
inline bool CStream::WritePkd( const IStreamData &inData )
{
return inData.Write(*this);
}
inline bool CStream::WritePacked(unsigned int ul)
{
STREAM_VERIFY_TYPE_WRITE(91);
int i;
for(i=1;i<16 && ul>=1u<<i*2;i++); // i=1..16
bool res = WriteNumberInBits(i-1,4); //
res = WriteNumberInBits(ul,i*2);
return res;
}
inline bool CStream::ReadPacked(unsigned int &ul)
{
STREAM_VERIFY_TYPE_READ(91);
int i;
ul = 0;
bool res = ReadNumberInBits(i,4);i++; // i=1..16
if(!res)
return res;
res = ReadNumberInBits(ul,i*2);
return res;
}
///////////////////////////////////////////////////////
inline bool CStream::GetAt(size_t dwPos, BYTE &c)
{
return GetBits((BYTE *)&c, dwPos, BYTES2BITS(sizeof(WORD)));
}
inline bool CStream::GetAt(size_t dwPos, WORD &w)
{
return GetBits((BYTE *)&w, dwPos, BYTES2BITS(sizeof(WORD)));
}
inline bool CStream::GetAt(size_t dwPos, DWORD &dw)
{
return GetBits((BYTE *)&dw, dwPos, BYTES2BITS(sizeof(DWORD)));
}
inline bool CStream::Seek(size_t dwPos)
{
if (dwPos <= m_dwBitSize)
m_dwReadBitPos = dwPos;
else
return false;
return true;
}
//#define NOT_COOKIEFIED
#ifndef NOT_COOKIEFIED
#define WRITE_COOKIE_NO(stm,c) {\
if((GetISystem()->GetStreamEngine()->GetStreamCompressionMask()&0x8)==0 || !GetISystem()->GetIGame()->GetModuleState(EGameMultiplayer))\
stm.Write((BYTE)(c));\
}
#define WRITE_COOKIE(stm) WRITE_COOKIE_NO(stm,0xAA);
#else
#define WRITE_COOKIE_NO(stm,c) {}
#define WRITE_COOKIE(stm) {}
#endif
#ifndef NOT_COOKIEFIED
#define VERIFY_COOKIE_NO(stm,c) {\
if((GetISystem()->GetStreamEngine()->GetStreamCompressionMask()&0x8)==0 || !GetISystem()->GetIGame()->GetModuleState(EGameMultiplayer))\
{\
BYTE cCookie; stm.Read(cCookie);\
if(cCookie!=(BYTE)(c))\
{ \
stm.Debug();\
CryError( "COOKIE ERROR %x!=%x AT %i, %s, %s",(DWORD)cCookie,(DWORD)(c), __LINE__, __FUNCTION__, __FILE__ );\
} else {stm.SetCheckPoint();} \
}\
}
#define VERIFY_COOKIE(stm) VERIFY_COOKIE_NO(stm,0xAA)
#define VERIFY_ENTITY_COOKIE_NO(stm,c) {\
if((GetISystem()->GetStreamEngine()->GetStreamCompressionMask()&0x8)==0 || !GetISystem()->GetIGame()->GetModuleState(EGameMultiplayer))\
{\
BYTE cCookie; stm.Read(cCookie);\
if (cCookie!=(BYTE)c)\
{\
stm.Debug();\
m_pISystem->GetILog()->LogError("Entity read cookie error %x!=%x file '%s' @ line %d (%s of class %s)",\
(DWORD)cCookie,(DWORD)c,__FILE__,__LINE__,GetName(),GetEntityClassName());\
return false;\
}\
}\
}
#define VERIFY_ENTITY_COOKIE(stm) VERIFY_ENTITY_COOKIE_NO(stm,0xAA)
#else
#define VERIFY_COOKIE(stm) {}
#define VERIFY_COOKIE_NO(stm,c) {}
#define VERIFY_ENTITY_COOKIE_NO(stm,c) {}
#define VERIFY_ENTITY_COOKIE(stm) {}
#endif
//////////////////////////////////////////////////////////////////////////
class CDefaultStreamAllocator : public IStreamAllocator
{
void *Alloc(size_t size) { return malloc(size); }
void *Realloc(void *old,size_t size) { return realloc(old,size); }
void Free(void *old) { free(old); }
};
#endif //_STREAM_H_