//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: Generic named data buffer, declaration and implementation // //============================================================================= #ifndef UTLMSGBUFFER_H #define UTLMSGBUFFER_H #ifdef _WIN32 #pragma once #endif #include "UtlMemory.h" #pragma warning(disable: 4244) // warning C4244: '=' : conversion from 'int' to 'short', possible loss of data //----------------------------------------------------------------------------- // Purpose: Generic named data buffer //----------------------------------------------------------------------------- class CUtlMsgBuffer { public: CUtlMsgBuffer(unsigned short msgID, int initialSize); CUtlMsgBuffer(unsigned short msgID, void const *data, int dataSize); ~CUtlMsgBuffer(); unsigned short GetMsgID() const { return m_iMsgID; } void SetMsgID(unsigned short msgID) { m_iMsgID = msgID; } // read functions bool ReadInt(const char *name, int &data); bool ReadUInt(const char *name, unsigned int &data); bool ReadString(const char *name, char *data, int dataBufferSize); bool ReadBuffer(const char *name, CUtlMsgBuffer &buffer); // returns number of bytes read, 0 on failure int ReadBlob(const char *name, void *data, int dataBufferSize); // reads out the next variable available in the buffer // fills out parameters with var details and data // returns false if no more vars available bool ReadNextVar(char name[32], bool &stringData, void *data, int &dataSize); // write functions void WriteInt(const char *name, int data); void WriteUInt(const char *name, unsigned int data); void WriteString(const char *name, const char *data); void WriteBlob(const char *name, const void *data, int dataSize); void WriteBuffer(const char *name, const CUtlMsgBuffer *buffer); // returns a pointer to the data buffer, and its size, of the specified variable void *FindVar(const char *name, int &dataSizeOut); // pads the buffer to the specified boundary (in bytes) void PadBuffer(int boundary); // makes sure the message has this much space allocated void EnsureCapacity(int dataSize); // returns the number of bytes used by the message int DataSize() const; // returns a pointer to the base data void *Base(); // returns a const pointer to the base data const void *Base() const; // advances the write pointer - used when you write directly into the buffer void SetWritePos(int size); CUtlMsgBuffer& Copy(const CUtlMsgBuffer &rhs); // copy constructor CUtlMsgBuffer(const CUtlMsgBuffer &rhs) { m_iMsgID = rhs.m_iMsgID; m_iWritePos = rhs.m_iWritePos; m_iReadPos = rhs.m_iReadPos; m_iNextVarPos = rhs.m_iNextVarPos; m_Memory.EnsureCapacity(rhs.m_Memory.NumAllocated()); if ( rhs.m_Memory.NumAllocated() > 0 ) { memcpy(Base(), rhs.Base(), rhs.m_Memory.NumAllocated()); } } private: bool Read(void *buffer, int readAmount); bool ReadUntilNull(void *buffer, int bufferSize); void Write(void const *data, int size); CUtlMemory m_Memory; unsigned short m_iMsgID; short m_iWritePos; // position in buffer we are currently writing to short m_iReadPos; // current reading position short m_iNextVarPos; // a guess at which variable is most likely to be read next }; //----------------------------------------------------------------------------- // Purpose: returns the number of bytes used by the message //----------------------------------------------------------------------------- inline int CUtlMsgBuffer::DataSize() const { // return the highest read/write mark if (m_iWritePos > m_iReadPos) return m_iWritePos; return m_iReadPos; } //----------------------------------------------------------------------------- // Purpose: returns a pointer to the base data //----------------------------------------------------------------------------- inline void *CUtlMsgBuffer::Base() { return &m_Memory[0]; } //----------------------------------------------------------------------------- // Purpose: returns a pointer to the base data //----------------------------------------------------------------------------- inline const void *CUtlMsgBuffer::Base() const { return &m_Memory[0]; } //----------------------------------------------------------------------------- // Purpose: ensures capacity //----------------------------------------------------------------------------- inline void CUtlMsgBuffer::EnsureCapacity(int dataSize) { m_Memory.EnsureCapacity(dataSize); } //----------------------------------------------------------------------------- // Purpose: pads the buffer to the specified boundary (in bytes) //----------------------------------------------------------------------------- inline void CUtlMsgBuffer::PadBuffer(int boundary) { // pad the buffer to be the right size for encryption int pad = (boundary - (DataSize() % boundary)); Write("\0\0\0\0\0\0\0\0\0\0\0\0", pad); } //----------------------------------------------------------------------------- // Purpose: Reads in a named 4-byte int, returns true on sucess, false on failure //----------------------------------------------------------------------------- inline bool CUtlMsgBuffer::ReadInt(const char *name, int &data) { return (ReadBlob(name, &data, 4) == 4); } //----------------------------------------------------------------------------- // Purpose: Reads in a named 4-byte unsigned int, returns true on sucess, false on failure //----------------------------------------------------------------------------- inline bool CUtlMsgBuffer::ReadUInt(const char *name, unsigned int &data) { return (ReadBlob(name, &data, 4) == 4); } //----------------------------------------------------------------------------- // Purpose: Reads in a named variable length character string // returns true on sucess, false on failure //----------------------------------------------------------------------------- inline bool CUtlMsgBuffer::ReadString(const char *name, char *data, int dataBufferSize) { return (ReadBlob(name, data, dataBufferSize) > 0); } //----------------------------------------------------------------------------- // Purpose: Writes out an integer to the message //----------------------------------------------------------------------------- inline void CUtlMsgBuffer::WriteInt(const char *name, int data) { WriteBlob(name, &data, 4); } //----------------------------------------------------------------------------- // Purpose: Writes out an unsigned integer to the message //----------------------------------------------------------------------------- inline void CUtlMsgBuffer::WriteUInt(const char *name, unsigned int data) { WriteBlob(name, &data, 4); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- inline void CUtlMsgBuffer::SetWritePos(int size) { m_iWritePos = size; } #endif // UTLMSGBUFFER_H