////////////////////////////////////////////////////////////////////// // // 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 #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_dwAllocatedBitSizeRealloc(m_pBuffer,BITS2BYTES(iniBitSize)); if(oldsize>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<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_