From 3bf9df6b2785fa6d951086978a3e66f49427166a Mon Sep 17 00:00:00 2001 From: FluorescentCIAAfricanAmerican <0934gj3049fk@protonmail.com> Date: Wed, 22 Apr 2020 12:56:21 -0400 Subject: 1 --- tracker/common/UtlMsgBuffer.cpp | 332 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 tracker/common/UtlMsgBuffer.cpp (limited to 'tracker/common/UtlMsgBuffer.cpp') diff --git a/tracker/common/UtlMsgBuffer.cpp b/tracker/common/UtlMsgBuffer.cpp new file mode 100644 index 0000000..b547d6a --- /dev/null +++ b/tracker/common/UtlMsgBuffer.cpp @@ -0,0 +1,332 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "UtlMsgBuffer.h" + +#include + +//----------------------------------------------------------------------------- +// Purpose: bitfields for use in variable descriptors +//----------------------------------------------------------------------------- +enum +{ + PACKBIT_CONTROLBIT = 0x01, // this must always be set + PACKBIT_INTNAME = 0x02, // if this is set then it's an int named variable, instead of a string + PACKBIT_BINARYDATA = 0x04, // signifies the data in this variable is binary, it's not a string +}; + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CUtlMsgBuffer::CUtlMsgBuffer(unsigned short msgID, int initialSize) : m_Memory(0, initialSize) +{ + m_iMsgID = msgID; + m_iWritePos = 0; + m_iReadPos = 0; + m_iNextVarPos = 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor, takes initial data +//----------------------------------------------------------------------------- +CUtlMsgBuffer::CUtlMsgBuffer(unsigned short msgID, void const *data, int dataSize) : m_Memory(0, dataSize) +{ + m_iMsgID = msgID; + m_iWritePos = (short)dataSize; + m_iReadPos = 0; + m_iNextVarPos = 0; + + memcpy(Base(), data, dataSize); +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CUtlMsgBuffer::~CUtlMsgBuffer() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Copy +//----------------------------------------------------------------------------- +CUtlMsgBuffer &CUtlMsgBuffer::Copy(const CUtlMsgBuffer &rhs) +{ + 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()); + } + return *this; +} + +//----------------------------------------------------------------------------- +// Purpose: Writes string data to the message +// Input : *name - name of the variable +// *data - pointer to the string data to write +//----------------------------------------------------------------------------- +void CUtlMsgBuffer::WriteString(const char *name, const char *data) +{ + // write out the variable type + unsigned char vtype = PACKBIT_CONTROLBIT; // stringname var, string data + Write(&vtype, 1); + + // write out the variable name + Write(name, strlen(name) + 1); + + // write out the size of the data + unsigned short size = (unsigned short)(strlen(data) + 1); + Write(&size, 2); + + // write out the data itself + Write(data, size); +} + +//----------------------------------------------------------------------------- +// Purpose: Writes out a named block of data +//----------------------------------------------------------------------------- +void CUtlMsgBuffer::WriteBlob(const char *name, const void *data, int dataSize) +{ + // write out the variable type + unsigned char vtype = PACKBIT_CONTROLBIT | PACKBIT_BINARYDATA; // stringname var, binary data + Write(&vtype, 1); + + // write out the variable name + Write(name, strlen(name) + 1); + + // write out the size of the data + unsigned short size = (unsigned short)dataSize; + Write(&size, 2); + + // write out the data itself + Write(data, dataSize); +} + +//----------------------------------------------------------------------------- +// Purpose: Writes out another UtlMsgBuffer as an element of this one +//----------------------------------------------------------------------------- +void CUtlMsgBuffer::WriteBuffer(const char *name, const CUtlMsgBuffer *buffer) +{ + // write out the variable type + unsigned char vtype = PACKBIT_CONTROLBIT | PACKBIT_BINARYDATA; // stringname var, binary data + Write(&vtype, 1); + + // write out the variable name + Write(name, strlen(name) + 1); + + // write out the size of the data + unsigned short size = (unsigned short) buffer->DataSize(); + Write(&size, 2); + + // write out the data itself + Write(buffer->Base(), size); +} + +//----------------------------------------------------------------------------- +// Purpose: Reads from the buffer, increments read position +// returns false if past end of buffer +//----------------------------------------------------------------------------- +bool CUtlMsgBuffer::Read(void *buffer, int readAmount) +{ + if (m_iReadPos + readAmount >= m_iWritePos) + return false; + + memcpy(buffer, &m_Memory[m_iReadPos], readAmount); + m_iReadPos += readAmount; + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Reads characterse from the buffer until a null is hit +//----------------------------------------------------------------------------- +bool CUtlMsgBuffer::ReadUntilNull(void *buffer, int bufferSize) +{ + int nullPos = m_iReadPos; + + // look through the buffer for the null terminator + while (nullPos < m_Memory.NumAllocated() && m_Memory[nullPos] != 0) + { + nullPos++; + } + + if (nullPos >= m_Memory.NumAllocated()) + { + // never found a null terminator + ((char *)buffer)[0] = 0; + return false; + } + + // copy from the null terminator + int copySize = nullPos - m_iReadPos; + if (copySize > bufferSize) + { + copySize = bufferSize - 1; + } + + // copy out the data and return + memcpy(buffer, &m_Memory[m_iReadPos], copySize); + ((char *)buffer)[copySize] = 0; + m_iReadPos += (copySize+1); + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Writes to the buffer, incrementing the write position +// assumes enough space has already been allocated for the write +//----------------------------------------------------------------------------- +void CUtlMsgBuffer::Write(void const *data, int size) +{ + // make sure it will fit + m_Memory.EnsureCapacity(m_iWritePos + size); + + // normal write + memcpy(&m_Memory[m_iWritePos], data, size); + + // increment write position + m_iWritePos += size; +} + +//----------------------------------------------------------------------------- +// Purpose: Reads in a named variable length data blob +// returns number of bytes read, 0 on failure +//----------------------------------------------------------------------------- +int CUtlMsgBuffer::ReadBlob(const char *name, void *data, int dataBufferSize) +{ + int dataSize = 0; + char *readData = (char *)FindVar(name, dataSize); + if (!readData) + { + memset(data, 0, dataBufferSize); + return 0; + } + + // ensure against buffer overflow + if (dataSize > dataBufferSize) + dataSize = dataBufferSize; + + // copy out data + memcpy(data, readData, dataSize); + return dataSize; +} + +//----------------------------------------------------------------------------- +// Purpose: Reads a blob of binary data into it's own buffer +//----------------------------------------------------------------------------- +bool CUtlMsgBuffer::ReadBuffer(const char *name, CUtlMsgBuffer &buffer) +{ + int dataSize = 0; + char *readData = (char *)FindVar(name, dataSize); + if (!readData) + { + return false; + } + + buffer.m_Memory.EnsureCapacity(dataSize); + memcpy(&buffer.m_Memory[0], readData, dataSize); + buffer.m_iReadPos = 0; + buffer.m_iWritePos = (short)dataSize; + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: 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 CUtlMsgBuffer::ReadNextVar(char varname[32], bool &stringData, void *data, int &dataSize) +{ + // read the type + unsigned char vtype = 1; + if (!Read(&vtype, 1)) + return false; + + // check for null-termination type + if (vtype == 0) + return false; + + stringData = !(vtype & PACKBIT_BINARYDATA); + + // read the variable name + if (!ReadUntilNull(varname, 31)) + return false; + + // read the data size + unsigned short size = 0; + if (!Read(&size, 2)) + return false; + + // ensure against buffer overflows + if (dataSize > size) + dataSize = size; + + // copy data + memcpy(data, &m_Memory[m_iReadPos], dataSize); + + // store of the next position, since that is probably where the next read needs to occur + m_iReadPos += size; + m_iNextVarPos = m_iReadPos; + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: sets the read/write position to be at the specified variable +// returns pointer to buffer position on success, NULL if not found +//----------------------------------------------------------------------------- +void *CUtlMsgBuffer::FindVar(const char *name, int &dataSize) +{ + // reset to where we Think the next var will be read from + m_iReadPos = m_iNextVarPos; + int loopCount = 2; + + // loop through looking for the specified variable + while (loopCount--) + { + unsigned char vtype = 1; + while (Read(&vtype, 1)) + { + // check for null-termination type + if (vtype == 0) + break; + + // read the variable name + char varname[32]; + if (!ReadUntilNull(varname, 31)) + break; + + // read the data size + unsigned short size = 0; + if (!Read(&size, 2)) + break; + + // is this our variable? + if (!stricmp(varname, name)) + { + dataSize = size; + void *data = &m_Memory[m_iReadPos]; + + // store of the next position, since that is probably where the next read needs to occur + m_iReadPos += size; + m_iNextVarPos = m_iReadPos; + return data; + } + + // skip over the data block to the next variable + m_iReadPos += size; + if (m_iReadPos >= m_iWritePos) + break; + } + + // we haven't found the data yet, Start again + m_iReadPos = 0; + } + + return NULL; +} -- cgit v1.2.3