2022-11-21 23:33:22 +01:00
//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
2022-11-21 23:13:06 +01:00
//
// Purpose:
//
// $NoKeywords: $
//
// Serialization/unserialization buffer
//=============================================================================//
# ifndef UTLBUFFER_H
# define UTLBUFFER_H
# ifdef _WIN32
# pragma once
# endif
//#include "unitlib/unitlib.h" // just here for tests - remove before checking in!!!
# include "tier1/utlmemory.h"
# include "tier1/byteswap.h"
# include <tier0/annotations.h>
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct characterset_t ;
//-----------------------------------------------------------------------------
// Description of character conversions for string output
// Here's an example of how to use the macros to define a character conversion
// BEGIN_CHAR_CONVERSION( CStringConversion, '\\' )
// { '\n', "n" },
// { '\t', "t" }
// END_CHAR_CONVERSION( CStringConversion, '\\' )
//-----------------------------------------------------------------------------
class CUtlCharConversion
{
public :
struct ConversionArray_t
{
char m_nActualChar ;
char * m_pReplacementString ;
} ;
2023-02-12 17:54:15 +01:00
CUtlCharConversion ( char nEscapeChar , const char * pDelimiter , int64 nCount , ConversionArray_t * pArray ) ;
2022-11-21 23:13:06 +01:00
char GetEscapeChar ( ) const ;
const char * GetDelimiter ( ) const ;
2023-02-12 17:54:15 +01:00
int64 GetDelimiterLength ( ) const ;
2022-11-21 23:13:06 +01:00
const char * GetConversionString ( char c ) const ;
2023-02-12 17:54:15 +01:00
int64 GetConversionLength ( char c ) const ;
int64 MaxConversionLength ( ) const ;
2022-11-21 23:13:06 +01:00
// Finds a conversion for the passed-in string, returns length
2023-02-12 17:54:15 +01:00
virtual char FindConversion ( const char * pString , int64 * pLength ) ;
2022-11-21 23:13:06 +01:00
protected :
struct ConversionInfo_t
{
2023-02-12 17:54:15 +01:00
int64 m_nLength ;
2022-11-21 23:13:06 +01:00
char * m_pReplacementString ;
} ;
char m_nEscapeChar ;
const char * m_pDelimiter ;
2023-02-12 17:54:15 +01:00
int64 m_nDelimiterLength ;
int64 m_nCount ;
int64 m_nMaxConversionLength ;
2022-11-21 23:13:06 +01:00
char m_pList [ 256 ] ;
ConversionInfo_t m_pReplacements [ 256 ] ;
} ;
# define BEGIN_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \
static CUtlCharConversion : : ConversionArray_t s_pConversionArray # # _name [ ] = {
# define END_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \
} ; \
CUtlCharConversion _name ( _escapeChar , _delimiter , sizeof ( s_pConversionArray # # _name ) / sizeof ( CUtlCharConversion : : ConversionArray_t ) , s_pConversionArray # # _name ) ;
# define BEGIN_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \
static CUtlCharConversion : : ConversionArray_t s_pConversionArray # # _name [ ] = {
# define END_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \
} ; \
_className _name ( _escapeChar , _delimiter , sizeof ( s_pConversionArray # # _name ) / sizeof ( CUtlCharConversion : : ConversionArray_t ) , s_pConversionArray # # _name ) ;
//-----------------------------------------------------------------------------
// Character conversions for C strings
//-----------------------------------------------------------------------------
CUtlCharConversion * GetCStringCharConversion ( ) ;
//-----------------------------------------------------------------------------
// Character conversions for quoted strings, with no escape sequences
//-----------------------------------------------------------------------------
CUtlCharConversion * GetNoEscCharConversion ( ) ;
//-----------------------------------------------------------------------------
// Macro to set overflow functions easily
//-----------------------------------------------------------------------------
# define SetUtlBufferOverflowFuncs( _get, _put ) \
SetOverflowFuncs ( static_cast < UtlBufferOverflowFunc_t > ( _get ) , static_cast < UtlBufferOverflowFunc_t > ( _put ) )
typedef unsigned short ushort ;
template < class A >
static const char * GetFmtStr ( int nRadix = 10 , bool bPrint = true ) { Assert ( 0 ) ; return " " ; }
# if defined( LINUX ) || defined( __clang__ ) || ( defined( _MSC_VER ) && _MSC_VER >= 1900 )
template < > const char * GetFmtStr < short > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 ) ; return " %hd " ; }
template < > const char * GetFmtStr < ushort > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 ) ; return " %hu " ; }
template < > const char * GetFmtStr < int > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 ) ; return " %d " ; }
template < > const char * GetFmtStr < uint > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 | | nRadix = = 16 ) ; return nRadix = = 16 ? " %x " : " %u " ; }
template < > const char * GetFmtStr < int64 > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 ) ; return " %lld " ; }
template < > const char * GetFmtStr < float > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 ) ; return " %f " ; }
template < > const char * GetFmtStr < double > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 ) ; return bPrint ? " %.15lf " : " %lf " ; } // force Printf to print DBL_DIG=15 digits of precision for doubles - defaults to FLT_DIG=6
# else
template < > static const char * GetFmtStr < short > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 ) ; return " %hd " ; }
template < > static const char * GetFmtStr < ushort > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 ) ; return " %hu " ; }
template < > static const char * GetFmtStr < int > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 ) ; return " %d " ; }
template < > static const char * GetFmtStr < uint > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 | | nRadix = = 16 ) ; return nRadix = = 16 ? " %x " : " %u " ; }
template < > static const char * GetFmtStr < int64 > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 ) ; return " %lld " ; }
template < > static const char * GetFmtStr < float > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 ) ; return " %f " ; }
template < > static const char * GetFmtStr < double > ( int nRadix , bool bPrint ) { Assert ( nRadix = = 10 ) ; return bPrint ? " %.15lf " : " %lf " ; } // force Printf to print DBL_DIG=15 digits of precision for doubles - defaults to FLT_DIG=6
# endif
//-----------------------------------------------------------------------------
// Command parsing..
//-----------------------------------------------------------------------------
class CUtlBuffer
{
// Brian has on his todo list to revisit this as there are issues in some cases with CUtlVector using operator = instead of copy construtor in InsertMultiple, etc.
// The unsafe case is something like this:
// CUtlVector< CUtlBuffer > vecFoo;
//
// CUtlBuffer buf;
// buf.Put( xxx );
// vecFoo.Insert( buf );
//
// This will cause memory corruption when vecFoo is cleared
//
//private:
// // Disallow copying
// CUtlBuffer( const CUtlBuffer & );// { Assert( 0 ); }
// CUtlBuffer &operator=( const CUtlBuffer & );// { Assert( 0 ); return *this; }
public :
enum SeekType_t
{
SEEK_HEAD = 0 ,
SEEK_CURRENT ,
SEEK_TAIL
} ;
// flags
enum BufferFlags_t
{
TEXT_BUFFER = 0x1 , // Describes how get + put work (as strings, or binary)
EXTERNAL_GROWABLE = 0x2 , // This is used w/ external buffers and causes the utlbuf to switch to reallocatable memory if an overflow happens when Putting.
CONTAINS_CRLF = 0x4 , // For text buffers only, does this contain \n or \n\r?
READ_ONLY = 0x8 , // For external buffers; prevents null termination from happening.
AUTO_TABS_DISABLED = 0x10 , // Used to disable/enable push/pop tabs
} ;
// Overflow functions when a get or put overflows
2022-11-22 08:57:33 +01:00
typedef bool ( CUtlBuffer : : * UtlBufferOverflowFunc_t ) ( int64 nSize ) ;
2022-11-21 23:13:06 +01:00
// Constructors for growable + external buffers for serialization/unserialization
2022-11-22 08:57:33 +01:00
CUtlBuffer ( int64 growSize = 0 , int64 initSize = 0 , int nFlags = 0 ) ;
CUtlBuffer ( const void * pBuffer , int64 size , int nFlags = 0 ) ;
2022-11-21 23:13:06 +01:00
// This one isn't actually defined so that we catch contructors that are trying to pass a bool in as the third param.
2022-11-22 08:57:33 +01:00
CUtlBuffer ( const void * pBuffer , int64 size , bool crap ) = delete ;
2022-11-21 23:13:06 +01:00
// UtlBuffer objects should not be copyable; we do a slow copy if you use this but it asserts.
// (REI: I'd like to delete these but we have some python bindings that currently rely on being able to copy these objects)
CUtlBuffer ( const CUtlBuffer & ) ; // = delete;
CUtlBuffer & operator = ( const CUtlBuffer & ) ; // = delete;
# if VALVE_CPP11
// UtlBuffer is non-copyable (same as CUtlMemory), but it is moveable. We would like to declare these with '= default'
// but unfortunately VS2013 isn't fully C++11 compliant, so we have to manually declare these in the boilerplate way.
CUtlBuffer ( CUtlBuffer & & moveFrom ) ; // = default;
CUtlBuffer & operator = ( CUtlBuffer & & moveFrom ) ; // = default;
# endif
unsigned char GetFlags ( ) const ;
// NOTE: This will assert if you attempt to recast it in a way that
// is not compatible. The only valid conversion is binary-> text w/CRLF
void SetBufferType ( bool bIsText , bool bContainsCRLF ) ;
// Makes sure we've got at least this much memory
2022-11-24 15:41:52 +01:00
void EnsureCapacity ( int64 num ) ;
2022-11-21 23:13:06 +01:00
// Access for direct read into buffer
2022-11-24 15:41:52 +01:00
void * AccessForDirectRead ( int64 nBytes ) ;
2022-11-21 23:13:06 +01:00
// Attaches the buffer to external memory....
2023-02-12 17:54:15 +01:00
void SetExternalBuffer ( void * pMemory , int64 nSize , int64 nInitialPut , int nFlags = 0 ) ;
2022-11-21 23:13:06 +01:00
bool IsExternallyAllocated ( ) const ;
2023-02-12 17:54:15 +01:00
void AssumeMemory ( void * pMemory , int64 nSize , int64 nInitialPut , int nFlags = 0 ) ;
2022-11-21 23:13:06 +01:00
void * Detach ( ) ;
void * DetachMemory ( ) ;
// copies data from another buffer
void CopyBuffer ( const CUtlBuffer & buffer ) ;
2022-11-24 15:41:52 +01:00
void CopyBuffer ( const void * pubData , int64 cubData ) ;
2022-11-21 23:13:06 +01:00
void Swap ( CUtlBuffer & buf ) ;
void Swap ( CUtlMemory < uint8 > & mem ) ;
FORCEINLINE void ActivateByteSwappingIfBigEndian ( void )
{
2023-04-03 01:41:46 +02:00
if V_CONSTEXPR ( ( IsX360 ( ) | | IsPS3 ( ) ) )
2022-11-21 23:13:06 +01:00
ActivateByteSwapping ( true ) ;
}
// Controls endian-ness of binary utlbufs - default matches the current platform
void ActivateByteSwapping ( bool bActivate ) ;
void SetBigEndian ( bool bigEndian ) ;
bool IsBigEndian ( void ) ;
// Resets the buffer; but doesn't free memory
void Clear ( ) ;
// Clears out the buffer; frees memory
void Purge ( ) ;
// Dump the buffer to stdout
void Spew ( ) ;
// Read stuff out.
// Binary mode: it'll just read the bits directly in, and characters will be
// read for strings until a null character is reached.
// Text mode: it'll parse the file, turning text #s into real numbers.
// GetString will read a string until a space is reached
char GetChar ( ) ;
unsigned char GetUnsignedChar ( ) ;
short GetShort ( ) ;
unsigned short GetUnsignedShort ( ) ;
int GetInt ( ) ;
int64 GetInt64 ( ) ;
unsigned int GetIntHex ( ) ;
unsigned int GetUnsignedInt ( ) ;
uint64 GetUnsignedInt64 ( ) ;
float GetFloat ( ) ;
double GetDouble ( ) ;
void * GetPtr ( ) ;
2023-02-12 17:54:15 +01:00
void GetString ( char * pString , int64 nMaxChars ) ;
bool Get ( void * pMem , int64 size ) ;
void GetLine ( char * pLine , int64 nMaxChars ) ;
2022-11-21 23:13:06 +01:00
// Used for getting objects that have a byteswap datadesc defined
2023-02-12 17:54:15 +01:00
template < typename T > void GetObjects ( T * dest , int64 count = 1 ) ;
2022-11-21 23:13:06 +01:00
// This will get at least 1 byte and up to nSize bytes.
// It will return the number of bytes actually read.
2023-02-12 17:54:15 +01:00
int64 GetUpTo ( void * pMem , int64 nSize ) ;
2022-11-21 23:13:06 +01:00
// This version of GetString converts \" to \\ and " to \, etc.
// It also reads a " at the beginning and end of the string
2023-02-12 17:54:15 +01:00
void GetDelimitedString ( CUtlCharConversion * pConv , char * pString , int64 nMaxChars = 0 ) ;
2022-11-21 23:13:06 +01:00
char GetDelimitedChar ( CUtlCharConversion * pConv ) ;
// This will return the # of characters of the string about to be read out
// NOTE: The count will *include* the terminating 0!!
// In binary mode, it's the number of characters until the next 0
// In text mode, it's the number of characters until the next space.
2023-02-12 17:54:15 +01:00
int64 PeekStringLength ( ) ;
2022-11-21 23:13:06 +01:00
// This version of PeekStringLength converts \" to \\ and " to \, etc.
// It also reads a " at the beginning and end of the string
// NOTE: The count will *include* the terminating 0!!
// In binary mode, it's the number of characters until the next 0
// In text mode, it's the number of characters between "s (checking for \")
// Specifying false for bActualSize will return the pre-translated number of characters
// including the delimiters and the escape characters. So, \n counts as 2 characters when bActualSize == false
// and only 1 character when bActualSize == true
2023-02-12 17:54:15 +01:00
int64 PeekDelimitedStringLength ( CUtlCharConversion * pConv , bool bActualSize = true ) ;
2022-11-21 23:13:06 +01:00
// Just like scanf, but doesn't work in binary mode
2023-02-12 17:54:15 +01:00
int64 Scanf ( SCANF_FORMAT_STRING const char * pFmt , . . . ) ;
int64 VaScanf ( const char * pFmt , va_list list ) ;
2022-11-21 23:13:06 +01:00
// Eats white space, advances Get index
void EatWhiteSpace ( ) ;
// Eats C++ style comments
bool EatCPPComment ( ) ;
// (For text buffers only)
// Parse a token from the buffer:
// Grab all text that lies between a starting delimiter + ending delimiter
// (skipping whitespace that leads + trails both delimiters).
// If successful, the get index is advanced and the function returns true,
// otherwise the index is not advanced and the function returns false.
2023-02-12 17:54:15 +01:00
bool ParseToken ( const char * pStartingDelim , const char * pEndingDelim , char * pString , int64 nMaxLen ) ;
2022-11-21 23:13:06 +01:00
// Advance the get index until after the particular string is found
// Do not eat whitespace before starting. Return false if it failed
// String test is case-insensitive.
bool GetToken ( const char * pToken ) ;
// Parses the next token, given a set of character breaks to stop at
// Returns the length of the token parsed in bytes (-1 if none parsed)
2023-02-12 17:54:15 +01:00
int64 ParseToken ( characterset_t * pBreaks , char * pTokenBuf , int64 nMaxLen , bool bParseComments = true ) ;
2022-11-21 23:13:06 +01:00
// Write stuff in
// Binary mode: it'll just write the bits directly in, and strings will be
// written with a null terminating character
// Text mode: it'll convert the numbers to text versions
// PutString will not write a terminating character
void PutChar ( char c ) ;
void PutUnsignedChar ( unsigned char uc ) ;
void PutShort ( short s ) ;
void PutUnsignedShort ( unsigned short us ) ;
void PutInt ( int i ) ;
void PutInt64 ( int64 i ) ;
void PutUnsignedInt ( unsigned int u ) ;
void PutUnsignedInt64 ( uint64 u ) ;
void PutFloat ( float f ) ;
void PutDouble ( double d ) ;
void PutPtr ( void * ) ; // Writes the pointer, not the pointed to
void PutString ( const char * pString ) ;
2022-11-24 15:41:52 +01:00
void Put ( const void * pMem , int64 size ) ;
2022-11-21 23:13:06 +01:00
// Used for putting objects that have a byteswap datadesc defined
2023-02-12 17:54:15 +01:00
template < typename T > void PutObjects ( T * src , int64 count = 1 ) ;
2022-11-21 23:13:06 +01:00
// This version of PutString converts \ to \\ and " to \", etc.
// It also places " at the beginning and end of the string
void PutDelimitedString ( CUtlCharConversion * pConv , const char * pString ) ;
void PutDelimitedChar ( CUtlCharConversion * pConv , char c ) ;
// Just like printf, writes a terminating zero in binary mode
void Printf ( PRINTF_FORMAT_STRING const char * pFmt , . . . ) FMTFUNCTION ( 2 , 3 ) ;
void VaPrintf ( const char * pFmt , va_list list ) ;
// What am I writing (put)/reading (get)?
2023-02-12 17:54:15 +01:00
void * PeekPut ( int64 offset = 0 ) ;
2022-11-21 23:33:22 +01:00
const void * PeekGet ( int64 offset = 0 ) const ;
const void * PeekGet ( int64 nMaxSize , int64 nOffset ) ;
2022-11-21 23:13:06 +01:00
// Where am I writing (put)/reading (get)?
2022-11-21 23:33:22 +01:00
int64 TellPut ( ) const ;
int64 TellGet ( ) const ;
2022-11-21 23:13:06 +01:00
// What's the most I've ever written?
2022-11-21 23:33:22 +01:00
int64 TellMaxPut ( ) const ;
2022-11-21 23:13:06 +01:00
// How many bytes remain to be read?
// NOTE: This is not accurate for streaming text files; it overshoots
2022-11-21 23:33:22 +01:00
int64 GetBytesRemaining ( ) const ;
2022-11-21 23:13:06 +01:00
// Change where I'm writing (put)/reading (get)
2022-11-24 15:41:52 +01:00
void SeekPut ( SeekType_t type , int64 offset ) ;
void SeekGet ( SeekType_t type , int64 offset ) ;
2022-11-21 23:13:06 +01:00
// Buffer base
const void * Base ( ) const ;
void * Base ( ) ;
// memory allocation size, does *not* reflect size written or read,
// use TellPut or TellGet for that
2022-11-24 15:41:52 +01:00
int64 Size ( ) const ;
2022-11-21 23:13:06 +01:00
// Am I a text buffer?
bool IsText ( ) const ;
// Can I grow if I'm externally allocated?
bool IsGrowable ( ) const ;
// Am I valid? (overflow or underflow error), Once invalid it stays invalid
bool IsValid ( ) const ;
// Do I contain carriage return/linefeeds?
bool ContainsCRLF ( ) const ;
// Am I read-only
bool IsReadOnly ( ) const ;
// Converts a buffer from a CRLF buffer to a CR buffer (and back)
// Returns false if no conversion was necessary (and outBuf is left untouched)
// If the conversion occurs, outBuf will be cleared.
bool ConvertCRLF ( CUtlBuffer & outBuf ) ;
// Push/pop pretty-printing tabs
void PushTab ( ) ;
void PopTab ( ) ;
// Temporarily disables pretty print
void EnableTabs ( bool bEnable ) ;
# if !defined( _GAMECONSOLE )
// Swap my internal memory with another buffer,
// and copy all of its other members
void SwapCopy ( CUtlBuffer & other ) ;
# endif
protected :
// error flags
enum
{
PUT_OVERFLOW = 0x1 ,
GET_OVERFLOW = 0x2 ,
MAX_ERROR_FLAG = GET_OVERFLOW ,
} ;
void SetOverflowFuncs ( UtlBufferOverflowFunc_t getFunc , UtlBufferOverflowFunc_t putFunc ) ;
2022-11-22 08:57:33 +01:00
bool OnPutOverflow ( int64 nSize ) ;
bool OnGetOverflow ( int64 nSize ) ;
2022-11-21 23:13:06 +01:00
protected :
// Checks if a get/put is ok
2022-11-22 08:57:33 +01:00
bool CheckPut ( int64 size ) ;
bool CheckGet ( int64 size ) ;
2022-11-21 23:13:06 +01:00
// NOTE: Pass in nPut here even though it is just a copy of m_Put. This is almost always called immediately
// after modifying m_Put and this lets it stay in a register
2022-11-21 23:33:22 +01:00
void AddNullTermination ( int64 nPut ) ;
2022-11-21 23:13:06 +01:00
// Methods to help with pretty-printing
bool WasLastCharacterCR ( ) ;
void PutTabs ( ) ;
// Help with delimited stuff
char GetDelimitedCharInternal ( CUtlCharConversion * pConv ) ;
void PutDelimitedCharInternal ( CUtlCharConversion * pConv , char c ) ;
// Default overflow funcs
2022-11-22 08:57:33 +01:00
bool PutOverflow ( int64 nSize ) ;
bool GetOverflow ( int64 nSize ) ;
2022-11-21 23:13:06 +01:00
// Does the next bytes of the buffer match a pattern?
2023-02-12 17:54:15 +01:00
bool PeekStringMatch ( int64 nOffset , const char * pString , int64 nLen ) ;
2022-11-21 23:13:06 +01:00
// Peek size of line to come, check memory bound
2023-02-12 17:54:15 +01:00
int64 PeekLineLength ( ) ;
2022-11-21 23:13:06 +01:00
// How much whitespace should I skip?
2023-02-12 17:54:15 +01:00
int64 PeekWhiteSpace ( int64 nOffset ) ;
2022-11-21 23:13:06 +01:00
// Checks if a peek get is ok
2023-02-12 17:54:15 +01:00
bool CheckPeekGet ( int64 nOffset , int64 nSize ) ;
2022-11-21 23:13:06 +01:00
// Call this to peek arbitrarily long into memory. It doesn't fail unless
// it can't read *anything* new
2023-02-12 17:54:15 +01:00
bool CheckArbitraryPeekGet ( int64 nOffset , int64 & nIncrement ) ;
2022-11-21 23:13:06 +01:00
template < typename T > void GetType ( T & dest ) ;
template < typename T > void GetTypeBin ( T & dest ) ;
template < typename T > bool GetTypeText ( T & value , int nRadix = 10 ) ;
template < typename T > void GetObject ( T * src ) ;
template < typename T > void PutType ( T src ) ;
template < typename T > void PutTypeBin ( T src ) ;
template < typename T > void PutObject ( T * src ) ;
// be sure to also update the copy constructor
// and SwapCopy() when adding members.
CUtlMemory < unsigned char > m_Memory ;
2022-11-21 23:33:22 +01:00
int64 m_Get ;
int64 m_Put ;
2022-11-21 23:13:06 +01:00
unsigned char m_Error ;
unsigned char m_Flags ;
unsigned char m_Reserved ;
# if defined( _GAMECONSOLE )
unsigned char pad ;
# endif
int m_nTab ;
2022-11-21 23:33:22 +01:00
int64 m_nMaxPut ;
2022-11-21 23:13:06 +01:00
int64 m_nOffset ;
UtlBufferOverflowFunc_t m_GetOverflowFunc ;
UtlBufferOverflowFunc_t m_PutOverflowFunc ;
2022-11-21 23:33:22 +01:00
CByteSwap m_Byteswap ;
2023-02-12 18:02:37 +01:00
void * m_pUnk ; // Possibly padding?
const char * m_pName ;
int64 m_Count ; // Unknown count.
2022-11-21 23:13:06 +01:00
} ;
2023-02-12 18:02:37 +01:00
static_assert ( sizeof ( CUtlBuffer ) = = 0x70 ) ;
2022-11-21 23:13:06 +01:00
// Stream style output operators for CUtlBuffer
inline CUtlBuffer & operator < < ( CUtlBuffer & b , char v )
{
b . PutChar ( v ) ;
return b ;
}
inline CUtlBuffer & operator < < ( CUtlBuffer & b , unsigned char v )
{
b . PutUnsignedChar ( v ) ;
return b ;
}
inline CUtlBuffer & operator < < ( CUtlBuffer & b , short v )
{
b . PutShort ( v ) ;
return b ;
}
inline CUtlBuffer & operator < < ( CUtlBuffer & b , unsigned short v )
{
b . PutUnsignedShort ( v ) ;
return b ;
}
inline CUtlBuffer & operator < < ( CUtlBuffer & b , int v )
{
b . PutInt ( v ) ;
return b ;
}
inline CUtlBuffer & operator < < ( CUtlBuffer & b , unsigned int v )
{
b . PutUnsignedInt ( v ) ;
return b ;
}
inline CUtlBuffer & operator < < ( CUtlBuffer & b , float v )
{
b . PutFloat ( v ) ;
return b ;
}
inline CUtlBuffer & operator < < ( CUtlBuffer & b , double v )
{
b . PutDouble ( v ) ;
return b ;
}
inline CUtlBuffer & operator < < ( CUtlBuffer & b , const char * pv )
{
b . PutString ( pv ) ;
return b ;
}
inline CUtlBuffer & operator < < ( CUtlBuffer & b , const Vector3D & v )
{
b < < v . x < < " " < < v . y < < " " < < v . z ;
return b ;
}
inline CUtlBuffer & operator < < ( CUtlBuffer & b , const Vector2D & v )
{
b < < v . x < < " " < < v . y ;
return b ;
}
class CUtlInplaceBuffer : public CUtlBuffer
{
public :
2023-02-12 17:54:15 +01:00
CUtlInplaceBuffer ( int64 growSize = 0 , int64 initSize = 0 , int nFlags = 0 ) ;
2022-11-21 23:13:06 +01:00
//
// Routines returning buffer-inplace-pointers
//
public :
//
// Upon success, determines the line length, fills out the pointer to the
// beginning of the line and the line length, advances the "get" pointer
// offset by the line length and returns "true".
//
// If end of file is reached or upon error returns "false".
//
// Note: the returned length of the line is at least one character because the
// trailing newline characters are also included as part of the line.
//
// Note: the pointer returned points into the local memory of this buffer, in
// case the buffer gets relocated or destroyed the pointer becomes invalid.
//
// e.g.: -------------
//
// char *pszLine;
// int nLineLen;
// while ( pUtlInplaceBuffer->InplaceGetLinePtr( &pszLine, &nLineLen ) )
// {
// ...
// }
//
// -------------
//
// @param ppszInBufferPtr on return points into this buffer at start of line
// @param pnLineLength on return holds num bytes accessible via (*ppszInBufferPtr)
//
// @returns true if line was successfully read
// false when EOF is reached or error occurs
//
2023-02-12 17:54:15 +01:00
bool InplaceGetLinePtr ( /* out */ char * * ppszInBufferPtr , /* out */ int64 * pnLineLength ) ;
2022-11-21 23:13:06 +01:00
//
// Determines the line length, advances the "get" pointer offset by the line length,
// replaces the newline character with null-terminator and returns the initial pointer
// to now null-terminated line.
//
// If end of file is reached or upon error returns NULL.
//
// Note: the pointer returned points into the local memory of this buffer, in
// case the buffer gets relocated or destroyed the pointer becomes invalid.
//
// e.g.: -------------
//
// while ( char *pszLine = pUtlInplaceBuffer->InplaceGetLinePtr() )
// {
// ...
// }
//
// -------------
//
// @returns ptr-to-zero-terminated-line if line was successfully read and buffer modified
// NULL when EOF is reached or error occurs
//
char * InplaceGetLinePtr ( void ) ;
} ;
//-----------------------------------------------------------------------------
// Where am I reading?
//-----------------------------------------------------------------------------
2022-11-21 23:33:22 +01:00
inline int64 CUtlBuffer : : TellGet ( ) const
2022-11-21 23:13:06 +01:00
{
return m_Get ;
}
//-----------------------------------------------------------------------------
// How many bytes remain to be read?
//-----------------------------------------------------------------------------
2022-11-21 23:33:22 +01:00
inline int64 CUtlBuffer : : GetBytesRemaining ( ) const
2022-11-21 23:13:06 +01:00
{
return m_nMaxPut - TellGet ( ) ;
}
//-----------------------------------------------------------------------------
// What am I reading?
//-----------------------------------------------------------------------------
2022-11-21 23:33:22 +01:00
inline const void * CUtlBuffer : : PeekGet ( int64 offset ) const
2022-11-21 23:13:06 +01:00
{
return & m_Memory [ m_Get + offset - m_nOffset ] ;
}
//-----------------------------------------------------------------------------
// Unserialization
//-----------------------------------------------------------------------------
template < typename T >
inline void CUtlBuffer : : GetObject ( T * dest )
{
if ( CheckGet ( sizeof ( T ) ) )
{
if ( ! m_Byteswap . IsSwappingBytes ( ) | | ( sizeof ( T ) = = 1 ) )
{
* dest = * ( T * ) PeekGet ( ) ;
}
else
{
m_Byteswap . SwapFieldsToTargetEndian < T > ( dest , ( T * ) PeekGet ( ) ) ;
}
m_Get + = sizeof ( T ) ;
}
else
{
Q_memset ( & dest , 0 , sizeof ( T ) ) ;
}
}
template < typename T >
2023-02-12 17:54:15 +01:00
inline void CUtlBuffer : : GetObjects ( T * dest , int64 count )
2022-11-21 23:13:06 +01:00
{
2023-02-12 17:54:15 +01:00
for ( int64 i = 0 ; i < count ; + + i , + + dest )
2022-11-21 23:13:06 +01:00
{
GetObject < T > ( dest ) ;
}
}
template < typename T >
inline void CUtlBuffer : : GetTypeBin ( T & dest )
{
if ( CheckGet ( sizeof ( T ) ) )
{
if ( ! m_Byteswap . IsSwappingBytes ( ) | | ( sizeof ( T ) = = 1 ) )
{
dest = * ( T * ) PeekGet ( ) ;
}
else
{
m_Byteswap . SwapBufferToTargetEndian < T > ( & dest , ( T * ) PeekGet ( ) ) ;
}
m_Get + = sizeof ( T ) ;
}
else
{
dest = 0 ;
}
}
template < >
inline void CUtlBuffer : : GetTypeBin < float > ( float & dest )
{
if ( CheckGet ( sizeof ( float ) ) )
{
uintptr_t pData = ( uintptr_t ) PeekGet ( ) ;
2023-04-03 01:41:46 +02:00
if V_CONSTEXPR ( ( IsX360 ( ) | | IsPS3 ( ) ) & & ( pData & 0x03 ) )
2022-11-21 23:13:06 +01:00
{
// handle unaligned read
( ( unsigned char * ) & dest ) [ 0 ] = ( ( unsigned char * ) pData ) [ 0 ] ;
( ( unsigned char * ) & dest ) [ 1 ] = ( ( unsigned char * ) pData ) [ 1 ] ;
( ( unsigned char * ) & dest ) [ 2 ] = ( ( unsigned char * ) pData ) [ 2 ] ;
( ( unsigned char * ) & dest ) [ 3 ] = ( ( unsigned char * ) pData ) [ 3 ] ;
}
else
{
// aligned read
dest = * ( float * ) pData ;
}
if ( m_Byteswap . IsSwappingBytes ( ) )
{
m_Byteswap . SwapBufferToTargetEndian < float > ( & dest , & dest ) ;
}
m_Get + = sizeof ( float ) ;
}
else
{
dest = 0 ;
}
}
template < >
inline void CUtlBuffer : : GetTypeBin < double > ( double & dest )
{
if ( CheckGet ( sizeof ( double ) ) )
{
uintptr_t pData = ( uintptr_t ) PeekGet ( ) ;
2023-04-03 01:41:46 +02:00
if V_CONSTEXPR ( ( IsX360 ( ) | | IsPS3 ( ) ) & & ( pData & 0x07 ) )
2022-11-21 23:13:06 +01:00
{
// handle unaligned read
( ( unsigned char * ) & dest ) [ 0 ] = ( ( unsigned char * ) pData ) [ 0 ] ;
( ( unsigned char * ) & dest ) [ 1 ] = ( ( unsigned char * ) pData ) [ 1 ] ;
( ( unsigned char * ) & dest ) [ 2 ] = ( ( unsigned char * ) pData ) [ 2 ] ;
( ( unsigned char * ) & dest ) [ 3 ] = ( ( unsigned char * ) pData ) [ 3 ] ;
( ( unsigned char * ) & dest ) [ 4 ] = ( ( unsigned char * ) pData ) [ 4 ] ;
( ( unsigned char * ) & dest ) [ 5 ] = ( ( unsigned char * ) pData ) [ 5 ] ;
( ( unsigned char * ) & dest ) [ 6 ] = ( ( unsigned char * ) pData ) [ 6 ] ;
( ( unsigned char * ) & dest ) [ 7 ] = ( ( unsigned char * ) pData ) [ 7 ] ;
}
else
{
// aligned read
dest = * ( double * ) pData ;
}
if ( m_Byteswap . IsSwappingBytes ( ) )
{
m_Byteswap . SwapBufferToTargetEndian < double > ( & dest , & dest ) ;
}
m_Get + = sizeof ( double ) ;
}
else
{
dest = 0 ;
}
}
template < class T >
inline T StringToNumber ( char * pString , char * * ppEnd , int nRadix )
{
Assert ( 0 ) ;
* ppEnd = pString ;
return 0 ;
}
template < >
inline int8 StringToNumber ( char * pString , char * * ppEnd , int nRadix )
{
return ( int8 ) strtol ( pString , ppEnd , nRadix ) ;
}
template < >
inline uint8 StringToNumber ( char * pString , char * * ppEnd , int nRadix )
{
return ( uint8 ) strtoul ( pString , ppEnd , nRadix ) ;
}
template < >
inline int16 StringToNumber ( char * pString , char * * ppEnd , int nRadix )
{
return ( int16 ) strtol ( pString , ppEnd , nRadix ) ;
}
template < >
inline uint16 StringToNumber ( char * pString , char * * ppEnd , int nRadix )
{
return ( uint16 ) strtoul ( pString , ppEnd , nRadix ) ;
}
template < >
inline int32 StringToNumber ( char * pString , char * * ppEnd , int nRadix )
{
return ( int32 ) strtol ( pString , ppEnd , nRadix ) ;
}
template < >
inline uint32 StringToNumber ( char * pString , char * * ppEnd , int nRadix )
{
return ( uint32 ) strtoul ( pString , ppEnd , nRadix ) ;
}
template < >
inline int64 StringToNumber ( char * pString , char * * ppEnd , int nRadix )
{
# if defined(_PS3) || defined(POSIX)
return ( int64 ) strtoll ( pString , ppEnd , nRadix ) ;
# else // !_PS3
return ( int64 ) _strtoi64 ( pString , ppEnd , nRadix ) ;
# endif // _PS3
}
template < >
inline float StringToNumber ( char * pString , char * * ppEnd , int nRadix )
{
NOTE_UNUSED ( nRadix ) ;
return ( float ) strtod ( pString , ppEnd ) ;
}
template < >
inline double StringToNumber ( char * pString , char * * ppEnd , int nRadix )
{
NOTE_UNUSED ( nRadix ) ;
return ( double ) strtod ( pString , ppEnd ) ;
}
template < typename T >
inline bool CUtlBuffer : : GetTypeText ( T & value , int nRadix /*= 10*/ )
{
// NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
2023-02-12 17:54:15 +01:00
int64 nLength = 128 ;
2022-11-21 23:13:06 +01:00
if ( ! CheckArbitraryPeekGet ( 0 , nLength ) )
{
value = 0 ;
return false ;
}
char * pStart = ( char * ) PeekGet ( ) ;
char * pEnd = pStart ;
value = StringToNumber < T > ( pStart , & pEnd , nRadix ) ;
2022-11-21 23:33:22 +01:00
int64 nBytesRead = ( int64 ) ( pEnd - pStart ) ;
2022-11-21 23:13:06 +01:00
if ( nBytesRead = = 0 )
return false ;
m_Get + = nBytesRead ;
return true ;
}
template < typename T >
inline void CUtlBuffer : : GetType ( T & dest )
{
if ( ! IsText ( ) )
{
GetTypeBin ( dest ) ;
}
else
{
GetTypeText ( dest ) ;
}
}
inline char CUtlBuffer : : GetChar ( )
{
// LEGACY WARNING: this behaves differently than GetUnsignedChar()
char c ;
GetTypeBin ( c ) ; // always reads as binary
return c ;
}
inline unsigned char CUtlBuffer : : GetUnsignedChar ( )
{
// LEGACY WARNING: this behaves differently than GetChar()
unsigned char c ;
if ( ! IsText ( ) )
{
GetTypeBin ( c ) ;
}
else
{
c = ( unsigned char ) GetUnsignedShort ( ) ;
}
return c ;
}
inline short CUtlBuffer : : GetShort ( )
{
short s ;
GetType ( s ) ;
return s ;
}
inline unsigned short CUtlBuffer : : GetUnsignedShort ( )
{
unsigned short s ;
GetType ( s ) ;
return s ;
}
inline int CUtlBuffer : : GetInt ( )
{
int i ;
GetType ( i ) ;
return i ;
}
inline int64 CUtlBuffer : : GetInt64 ( )
{
int64 i ;
GetType ( i ) ;
return i ;
}
inline unsigned int CUtlBuffer : : GetIntHex ( )
{
uint i ;
if ( ! IsText ( ) )
{
GetTypeBin ( i ) ;
}
else
{
GetTypeText ( i , 16 ) ;
}
return i ;
}
inline unsigned int CUtlBuffer : : GetUnsignedInt ( )
{
unsigned int i ;
GetType ( i ) ;
return i ;
}
inline uint64 CUtlBuffer : : GetUnsignedInt64 ( )
{
uint64 i ;
GetType ( i ) ;
return i ;
}
inline float CUtlBuffer : : GetFloat ( )
{
float f ;
GetType ( f ) ;
return f ;
}
inline double CUtlBuffer : : GetDouble ( )
{
double d ;
GetType ( d ) ;
return d ;
}
inline void * CUtlBuffer : : GetPtr ( )
{
void * p ;
// LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal
# if !defined(X64BITS) && !defined(PLATFORM_64BITS)
2022-11-24 15:41:52 +01:00
p = ( void * ) GetUnsignedInt64 ( ) ;
2022-11-21 23:13:06 +01:00
# else
p = ( void * ) GetInt64 ( ) ;
# endif
return p ;
}
//-----------------------------------------------------------------------------
// Where am I writing?
//-----------------------------------------------------------------------------
inline unsigned char CUtlBuffer : : GetFlags ( ) const
{
return m_Flags ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
inline bool CUtlBuffer : : IsExternallyAllocated ( ) const
{
return m_Memory . IsExternallyAllocated ( ) ;
}
//-----------------------------------------------------------------------------
// Where am I writing?
//-----------------------------------------------------------------------------
2022-11-21 23:33:22 +01:00
inline int64 CUtlBuffer : : TellPut ( ) const
2022-11-21 23:13:06 +01:00
{
return m_Put ;
}
//-----------------------------------------------------------------------------
// What's the most I've ever written?
//-----------------------------------------------------------------------------
2022-11-21 23:33:22 +01:00
inline int64 CUtlBuffer : : TellMaxPut ( ) const
2022-11-21 23:13:06 +01:00
{
return m_nMaxPut ;
}
//-----------------------------------------------------------------------------
// What am I reading?
//-----------------------------------------------------------------------------
2023-02-12 17:54:15 +01:00
inline void * CUtlBuffer : : PeekPut ( int64 offset )
2022-11-21 23:13:06 +01:00
{
return & m_Memory [ m_Put + offset - m_nOffset ] ;
}
//-----------------------------------------------------------------------------
// Various put methods
//-----------------------------------------------------------------------------
template < typename T >
inline void CUtlBuffer : : PutObject ( T * src )
{
if ( CheckPut ( sizeof ( T ) ) )
{
if ( ! m_Byteswap . IsSwappingBytes ( ) | | ( sizeof ( T ) = = 1 ) )
{
* ( T * ) PeekPut ( ) = * src ;
}
else
{
m_Byteswap . SwapFieldsToTargetEndian < T > ( ( T * ) PeekPut ( ) , src ) ;
}
m_Put + = sizeof ( T ) ;
AddNullTermination ( m_Put ) ;
}
}
template < typename T >
2023-02-12 17:54:15 +01:00
inline void CUtlBuffer : : PutObjects ( T * src , int64 count )
2022-11-21 23:13:06 +01:00
{
2023-02-12 17:54:15 +01:00
for ( int64 i = 0 ; i < count ; + + i , + + src )
2022-11-21 23:13:06 +01:00
{
PutObject < T > ( src ) ;
}
}
template < typename T >
inline void CUtlBuffer : : PutTypeBin ( T src )
{
if ( CheckPut ( sizeof ( T ) ) )
{
if ( ! m_Byteswap . IsSwappingBytes ( ) | | ( sizeof ( T ) = = 1 ) )
{
* ( T * ) PeekPut ( ) = src ;
}
else
{
m_Byteswap . SwapBufferToTargetEndian < T > ( ( T * ) PeekPut ( ) , & src ) ;
}
m_Put + = sizeof ( T ) ;
AddNullTermination ( m_Put ) ;
}
}
# if defined( _GAMECONSOLE )
template < >
inline void CUtlBuffer : : PutTypeBin < float > ( float src )
{
if ( CheckPut ( sizeof ( src ) ) )
{
if ( m_Byteswap . IsSwappingBytes ( ) )
{
m_Byteswap . SwapBufferToTargetEndian < float > ( & src , & src ) ;
}
//
// Write the data
//
unsigned pData = ( unsigned ) PeekPut ( ) ;
if ( pData & 0x03 )
{
// handle unaligned write
byte * dst = ( byte * ) pData ;
byte * srcPtr = ( byte * ) & src ;
dst [ 0 ] = srcPtr [ 0 ] ;
dst [ 1 ] = srcPtr [ 1 ] ;
dst [ 2 ] = srcPtr [ 2 ] ;
dst [ 3 ] = srcPtr [ 3 ] ;
}
else
{
* ( float * ) pData = src ;
}
m_Put + = sizeof ( float ) ;
AddNullTermination ( m_Put ) ;
}
}
template < >
inline void CUtlBuffer : : PutTypeBin < double > ( double src )
{
if ( CheckPut ( sizeof ( src ) ) )
{
if ( m_Byteswap . IsSwappingBytes ( ) )
{
m_Byteswap . SwapBufferToTargetEndian < double > ( & src , & src ) ;
}
//
// Write the data
//
unsigned pData = ( unsigned ) PeekPut ( ) ;
if ( pData & 0x07 )
{
// handle unaligned write
byte * dst = ( byte * ) pData ;
byte * srcPtr = ( byte * ) & src ;
dst [ 0 ] = srcPtr [ 0 ] ;
dst [ 1 ] = srcPtr [ 1 ] ;
dst [ 2 ] = srcPtr [ 2 ] ;
dst [ 3 ] = srcPtr [ 3 ] ;
dst [ 4 ] = srcPtr [ 4 ] ;
dst [ 5 ] = srcPtr [ 5 ] ;
dst [ 6 ] = srcPtr [ 6 ] ;
dst [ 7 ] = srcPtr [ 7 ] ;
}
else
{
* ( double * ) pData = src ;
}
m_Put + = sizeof ( double ) ;
AddNullTermination ( m_Put ) ;
}
}
# endif
template < typename T >
inline void CUtlBuffer : : PutType ( T src )
{
if ( ! IsText ( ) )
{
PutTypeBin ( src ) ;
}
else
{
Printf ( GetFmtStr < T > ( ) , src ) ;
}
}
//-----------------------------------------------------------------------------
// Methods to help with pretty-printing
//-----------------------------------------------------------------------------
inline bool CUtlBuffer : : WasLastCharacterCR ( )
{
if ( ! IsText ( ) | | ( TellPut ( ) = = 0 ) )
return false ;
return ( * ( const char * ) PeekPut ( - 1 ) = = ' \n ' ) ;
}
inline void CUtlBuffer : : PutTabs ( )
{
int nTabCount = ( m_Flags & AUTO_TABS_DISABLED ) ? 0 : m_nTab ;
for ( int i = nTabCount ; - - i > = 0 ; )
{
PutTypeBin < char > ( ' \t ' ) ;
}
}
//-----------------------------------------------------------------------------
// Push/pop pretty-printing tabs
//-----------------------------------------------------------------------------
inline void CUtlBuffer : : PushTab ( )
{
+ + m_nTab ;
}
inline void CUtlBuffer : : PopTab ( )
{
if ( - - m_nTab < 0 )
{
m_nTab = 0 ;
}
}
//-----------------------------------------------------------------------------
// Temporarily disables pretty print
//-----------------------------------------------------------------------------
inline void CUtlBuffer : : EnableTabs ( bool bEnable )
{
if ( bEnable )
{
m_Flags & = ~ AUTO_TABS_DISABLED ;
}
else
{
m_Flags | = AUTO_TABS_DISABLED ;
}
}
inline void CUtlBuffer : : PutChar ( char c )
{
if ( WasLastCharacterCR ( ) )
{
PutTabs ( ) ;
}
PutTypeBin ( c ) ;
}
inline void CUtlBuffer : : PutUnsignedChar ( unsigned char c )
{
if ( ! IsText ( ) )
{
PutTypeBin ( c ) ;
}
else
{
PutUnsignedShort ( c ) ;
}
}
inline void CUtlBuffer : : PutShort ( short s )
{
PutType ( s ) ;
}
inline void CUtlBuffer : : PutUnsignedShort ( unsigned short s )
{
PutType ( s ) ;
}
inline void CUtlBuffer : : PutInt ( int i )
{
PutType ( i ) ;
}
inline void CUtlBuffer : : PutInt64 ( int64 i )
{
PutType ( i ) ;
}
inline void CUtlBuffer : : PutUnsignedInt ( unsigned int u )
{
PutType ( u ) ;
}
inline void CUtlBuffer : : PutUnsignedInt64 ( uint64 i )
{
PutType ( i ) ;
}
inline void CUtlBuffer : : PutFloat ( float f )
{
PutType ( f ) ;
}
inline void CUtlBuffer : : PutDouble ( double d )
{
PutType ( d ) ;
}
inline void CUtlBuffer : : PutPtr ( void * p )
{
// LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal
if ( ! IsText ( ) )
{
PutTypeBin ( p ) ;
}
else
{
Printf ( " 0x%p " , p ) ;
}
}
//-----------------------------------------------------------------------------
// Am I a text buffer?
//-----------------------------------------------------------------------------
inline bool CUtlBuffer : : IsText ( ) const
{
return ( m_Flags & TEXT_BUFFER ) ! = 0 ;
}
//-----------------------------------------------------------------------------
// Can I grow if I'm externally allocated?
//-----------------------------------------------------------------------------
inline bool CUtlBuffer : : IsGrowable ( ) const
{
return ( m_Flags & EXTERNAL_GROWABLE ) ! = 0 ;
}
//-----------------------------------------------------------------------------
// Am I valid? (overflow or underflow error), Once invalid it stays invalid
//-----------------------------------------------------------------------------
inline bool CUtlBuffer : : IsValid ( ) const
{
return m_Error = = 0 ;
}
//-----------------------------------------------------------------------------
// Do I contain carriage return/linefeeds?
//-----------------------------------------------------------------------------
inline bool CUtlBuffer : : ContainsCRLF ( ) const
{
return IsText ( ) & & ( ( m_Flags & CONTAINS_CRLF ) ! = 0 ) ;
}
//-----------------------------------------------------------------------------
// Am I read-only
//-----------------------------------------------------------------------------
inline bool CUtlBuffer : : IsReadOnly ( ) const
{
return ( m_Flags & READ_ONLY ) ! = 0 ;
}
//-----------------------------------------------------------------------------
// Buffer base and size
//-----------------------------------------------------------------------------
inline const void * CUtlBuffer : : Base ( ) const
{
return m_Memory . Base ( ) ;
}
inline void * CUtlBuffer : : Base ( )
{
return m_Memory . Base ( ) ;
}
2022-11-24 15:41:52 +01:00
inline int64 CUtlBuffer : : Size ( ) const
2022-11-21 23:13:06 +01:00
{
return m_Memory . NumAllocated ( ) ;
}
//-----------------------------------------------------------------------------
// Clears out the buffer; frees memory
//-----------------------------------------------------------------------------
inline void CUtlBuffer : : Clear ( )
{
m_Get = 0 ;
m_Put = 0 ;
m_Error = 0 ;
m_nOffset = 0 ;
m_nMaxPut = - 1 ;
AddNullTermination ( m_Put ) ;
}
inline void CUtlBuffer : : Purge ( )
{
m_Get = 0 ;
m_Put = 0 ;
m_nOffset = 0 ;
m_nMaxPut = 0 ;
m_Error = 0 ;
m_Memory . Purge ( ) ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
2022-11-24 15:41:52 +01:00
inline void * CUtlBuffer : : AccessForDirectRead ( int64 nBytes )
2022-11-21 23:13:06 +01:00
{
Assert ( m_Get = = 0 & & m_Put = = 0 & & m_nMaxPut = = 0 ) ;
EnsureCapacity ( nBytes ) ;
m_nMaxPut = nBytes ;
return Base ( ) ;
}
inline void * CUtlBuffer : : Detach ( )
{
void * p = m_Memory . Detach ( ) ;
Clear ( ) ;
return p ;
}
//-----------------------------------------------------------------------------
inline void CUtlBuffer : : Spew ( )
{
//SeekGet(CUtlBuffer::SEEK_HEAD, 0);
//char pTmpLine[1024];
//while (IsValid() && GetBytesRemaining())
//{
// memset(pTmpLine, 0, sizeof(pTmpLine));
// Get(pTmpLine, MIN((size_t)GetBytesRemaining(), sizeof(pTmpLine) - 1));
// DevMsg(eDLL_T::COMMON, _T("%s"), pTmpLine);
//}
}
# if !defined(_GAMECONSOLE)
inline void CUtlBuffer : : SwapCopy ( CUtlBuffer & other )
{
m_Get = other . m_Get ;
m_Put = other . m_Put ;
m_Error = other . m_Error ;
m_Flags = other . m_Flags ;
m_Reserved = other . m_Reserved ;
m_nTab = other . m_nTab ;
m_nMaxPut = other . m_nMaxPut ;
m_nOffset = other . m_nOffset ;
m_GetOverflowFunc = other . m_GetOverflowFunc ;
m_PutOverflowFunc = other . m_PutOverflowFunc ;
m_Byteswap = other . m_Byteswap ;
m_Memory . Swap ( other . m_Memory ) ;
}
# endif
inline void CUtlBuffer : : CopyBuffer ( const CUtlBuffer & buffer )
{
CopyBuffer ( buffer . Base ( ) , buffer . TellPut ( ) ) ;
}
2022-11-24 15:41:52 +01:00
inline void CUtlBuffer : : CopyBuffer ( const void * pubData , int64 cubData )
2022-11-21 23:13:06 +01:00
{
Clear ( ) ;
if ( cubData )
{
Put ( pubData , cubData ) ;
}
}
# endif // UTLBUFFER_H