//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // // Serialization/unserialization buffer //=============================================================================// #ifndef UTLBUFFER_H #define UTLBUFFER_H #ifdef _WIN32 #pragma once #endif #include "tier1/utlmemory.h" #include "tier1/byteswap.h" #include //----------------------------------------------------------------------------- // 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; const char *m_pReplacementString; }; CUtlCharConversion( char nEscapeChar, const char *pDelimiter, int nCount, ConversionArray_t *pArray ); char GetEscapeChar() const; const char *GetDelimiter() const; int GetDelimiterLength() const; const char *GetConversionString( char c ) const; int GetConversionLength( char c ) const; int MaxConversionLength() const; // Finds a conversion for the passed-in string, returns length virtual char FindConversion( const char *pString, int *pLength ); protected: struct ConversionInfo_t { int m_nLength; const char *m_pReplacementString; }; char m_nEscapeChar; const char *m_pDelimiter; int m_nDelimiterLength; int m_nCount; int m_nMaxConversionLength; 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 ( _get ), static_cast ( _put ) ) //----------------------------------------------------------------------------- // Command parsing.. //----------------------------------------------------------------------------- class CUtlBuffer { 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 typedef bool (CUtlBuffer::*UtlBufferOverflowFunc_t)( int nSize ); // Constructors for growable + external buffers for serialization/unserialization CUtlBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 ); CUtlBuffer( const void* pBuffer, int size, int nFlags = 0 ); // This one isn't actually defined so that we catch contructors that are trying to pass a bool in as the third param. CUtlBuffer( const void *pBuffer, int size, bool crap ); 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 void EnsureCapacity( int num ); // Attaches the buffer to external memory.... void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 ); bool IsExternallyAllocated() const; // Takes ownership of the passed memory, including freeing it when this buffer is destroyed. void AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags = 0 ); // copies data from another buffer void CopyBuffer( const CUtlBuffer &buffer ); void CopyBuffer( const void *pubData, int cubData ); void Swap( CUtlBuffer &buf ); void Swap( CUtlMemory &mem ); FORCEINLINE void ActivateByteSwappingIfBigEndian( void ) { if ( IsX360() ) 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(); // 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( ); int GetIntHex( ); unsigned int GetUnsignedInt( ); float GetFloat( ); double GetDouble( ); template void GetString( char( &pString )[maxLenInChars] ) { GetStringInternal( pString, maxLenInChars ); } void GetStringManualCharCount( char *pString, size_t maxLenInChars ) { GetStringInternal( pString, maxLenInChars ); } void Get( void* pMem, int size ); void GetLine( char* pLine, int nMaxChars = 0 ); // Used for getting objects that have a byteswap datadesc defined template void GetObjects( T *dest, int count = 1 ); // This will get at least 1 byte and up to nSize bytes. // It will return the number of bytes actually read. int GetUpTo( void *pMem, int nSize ); // This version of GetString converts \" to \\ and " to \, etc. // It also reads a " at the beginning and end of the string void GetDelimitedString( CUtlCharConversion *pConv, char *pString, int nMaxChars = 0 ); 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. int PeekStringLength(); // 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 int PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActualSize = true ); // Just like scanf, but doesn't work in binary mode int Scanf( SCANF_FORMAT_STRING const char* pFmt, ... ); int VaScanf( const char* pFmt, va_list list ); // 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. bool ParseToken( const char *pStartingDelim, const char *pEndingDelim, char* pString, int nMaxLen ); // 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) int ParseToken( characterset_t *pBreaks, char *pTokenBuf, int nMaxLen, bool bParseComments = true ); // 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 PutUint64( uint64 ub ); void PutInt16( int16 s16 ); void PutShort( short s ); void PutUnsignedShort( unsigned short us ); void PutInt( int i ); void PutInt64( int64 i ); void PutUnsignedInt( unsigned int u ); void PutFloat( float f ); void PutDouble( double d ); void PutString( const char* pString ); void Put( const void* pMem, int size ); // Used for putting objects that have a byteswap datadesc defined template void PutObjects( T *src, int count = 1 ); // 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)? void* PeekPut( int offset = 0 ); const void* PeekGet( int offset = 0 ) const; const void* PeekGet( int nMaxSize, int nOffset ); // Where am I writing (put)/reading (get)? int TellPut( ) const; int TellGet( ) const; // What's the most I've ever written? int TellMaxPut( ) const; // How many bytes remain to be read? // NOTE: This is not accurate for streaming text files; it overshoots int GetBytesRemaining() const; // Change where I'm writing (put)/reading (get) void SeekPut( SeekType_t type, int offset ); void SeekGet( SeekType_t type, int offset ); // Buffer base const void* Base() const; void* Base(); // Returns the base as a const char*, only valid in text mode. const char *String() const; // memory allocation size, does *not* reflect size written or read, // use TellPut or TellGet for that int Size() const; // 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 ); protected: // error flags enum { PUT_OVERFLOW = 0x1, GET_OVERFLOW = 0x2, MAX_ERROR_FLAG = GET_OVERFLOW, }; void SetOverflowFuncs( UtlBufferOverflowFunc_t getFunc, UtlBufferOverflowFunc_t putFunc ); bool OnPutOverflow( int nSize ); bool OnGetOverflow( int nSize ); protected: // Checks if a get/put is ok bool CheckPut( int size ); bool CheckGet( int size ); void AddNullTermination( ); // 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 bool PutOverflow( int nSize ); bool GetOverflow( int nSize ); // Does the next bytes of the buffer match a pattern? bool PeekStringMatch( int nOffset, const char *pString, int nLen ); // Peek size of line to come, check memory bound int PeekLineLength(); // How much whitespace should I skip? int PeekWhiteSpace( int nOffset ); // Checks if a peek get is ok bool CheckPeekGet( int nOffset, int nSize ); // Call this to peek arbitrarily long into memory. It doesn't fail unless // it can't read *anything* new bool CheckArbitraryPeekGet( int nOffset, int &nIncrement ); void GetStringInternal( char *pString, size_t maxLenInChars ); template void GetType( T& dest, const char *pszFmt ); template void GetTypeBin( T& dest ); template void GetObject( T *src ); template void PutType( T src, const char *pszFmt ); template void PutTypeBin( T src ); template void PutObject( T *src ); CUtlMemory m_Memory; int m_Get; int m_Put; unsigned char m_Error; unsigned char m_Flags; unsigned char m_Reserved; #if defined( _X360 ) unsigned char pad; #endif int m_nTab; int m_nMaxPut; int m_nOffset; UtlBufferOverflowFunc_t m_GetOverflowFunc; UtlBufferOverflowFunc_t m_PutOverflowFunc; CByteswap m_Byteswap; }; // 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 Vector &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: CUtlInplaceBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 ); // // 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 // bool InplaceGetLinePtr( /* out */ char **ppszInBufferPtr, /* out */ int *pnLineLength ); // // 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? //----------------------------------------------------------------------------- inline int CUtlBuffer::TellGet( ) const { return m_Get; } //----------------------------------------------------------------------------- // How many bytes remain to be read? //----------------------------------------------------------------------------- inline int CUtlBuffer::GetBytesRemaining() const { return m_nMaxPut - TellGet(); } //----------------------------------------------------------------------------- // What am I reading? //----------------------------------------------------------------------------- inline const void* CUtlBuffer::PeekGet( int offset ) const { return &m_Memory[ m_Get + offset - m_nOffset ]; } //----------------------------------------------------------------------------- // Unserialization //----------------------------------------------------------------------------- template inline void CUtlBuffer::GetObject( T *dest ) { if ( CheckGet( sizeof(T) ) ) { if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) { *dest = *(T *)PeekGet(); } else { m_Byteswap.SwapFieldsToTargetEndian( dest, (T*)PeekGet() ); } m_Get += sizeof(T); } else { Q_memset( dest, 0, sizeof(T) ); } } template inline void CUtlBuffer::GetObjects( T *dest, int count ) { for ( int i = 0; i < count; ++i, ++dest ) { GetObject( dest ); } } template inline void CUtlBuffer::GetTypeBin( T &dest ) { if ( CheckGet( sizeof(T) ) ) { if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) { dest = *(T *)PeekGet(); } else { m_Byteswap.SwapBufferToTargetEndian( &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(); if ( IsX360() && ( pData & 0x03 ) ) { // 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::GetType( T &dest, const char *pszFmt ) { if (!IsText()) { GetTypeBin( dest ); } else { dest = 0; Scanf( pszFmt, &dest ); } } inline char CUtlBuffer::GetChar( ) { char c; GetType( c, "%c" ); return c; } inline unsigned char CUtlBuffer::GetUnsignedChar( ) { unsigned char c; GetType( c, "%u" ); return c; } inline short CUtlBuffer::GetShort( ) { short s; GetType( s, "%d" ); return s; } inline unsigned short CUtlBuffer::GetUnsignedShort( ) { unsigned short s; GetType( s, "%u" ); return s; } inline int CUtlBuffer::GetInt( ) { int i; GetType( i, "%d" ); return i; } inline int64 CUtlBuffer::GetInt64( ) { int64 i; GetType( i, "%lld" ); return i; } inline int CUtlBuffer::GetIntHex( ) { int i; GetType( i, "%x" ); return i; } inline unsigned int CUtlBuffer::GetUnsignedInt( ) { unsigned int u; GetType( u, "%u" ); return u; } inline float CUtlBuffer::GetFloat( ) { float f; GetType( f, "%f" ); return f; } inline double CUtlBuffer::GetDouble( ) { double d; GetType( d, "%f" ); return d; } //----------------------------------------------------------------------------- // 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? //----------------------------------------------------------------------------- inline int CUtlBuffer::TellPut( ) const { return m_Put; } //----------------------------------------------------------------------------- // What's the most I've ever written? //----------------------------------------------------------------------------- inline int CUtlBuffer::TellMaxPut( ) const { return m_nMaxPut; } //----------------------------------------------------------------------------- // What am I reading? //----------------------------------------------------------------------------- inline void* CUtlBuffer::PeekPut( int offset ) { return &m_Memory[m_Put + offset - m_nOffset]; } //----------------------------------------------------------------------------- // Various put methods //----------------------------------------------------------------------------- template 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*)PeekPut(), src ); } m_Put += sizeof(T); AddNullTermination(); } } template inline void CUtlBuffer::PutObjects( T *src, int count ) { for ( int i = 0; i < count; ++i, ++src ) { PutObject( src ); } } template 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*)PeekPut(), &src ); } m_Put += sizeof(T); AddNullTermination(); } } template inline void CUtlBuffer::PutType( T src, const char *pszFmt ) { if (!IsText()) { PutTypeBin( src ); } else { Printf( pszFmt, 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( '\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 ) { PutType( c, "%u" ); } inline void CUtlBuffer::PutUint64( uint64 ub ) { PutType( ub, "%llu" ); } inline void CUtlBuffer::PutInt16( int16 s16 ) { PutType( s16, "%d" ); } inline void CUtlBuffer::PutShort( short s ) { PutType( s, "%d" ); } inline void CUtlBuffer::PutUnsignedShort( unsigned short s ) { PutType( s, "%u" ); } inline void CUtlBuffer::PutInt( int i ) { PutType( i, "%d" ); } inline void CUtlBuffer::PutInt64( int64 i ) { PutType( i, "%llu" ); } inline void CUtlBuffer::PutUnsignedInt( unsigned int u ) { PutType( u, "%u" ); } inline void CUtlBuffer::PutFloat( float f ) { PutType( f, "%f" ); } inline void CUtlBuffer::PutDouble( double d ) { PutType( d, "%f" ); } //----------------------------------------------------------------------------- // 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(); } // Returns the base as a const char*, only valid in text mode. inline const char *CUtlBuffer::String() const { Assert( IsText() ); return reinterpret_cast( m_Memory.Base() ); } inline int CUtlBuffer::Size() const { 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(); } inline void CUtlBuffer::Purge() { m_Get = 0; m_Put = 0; m_nOffset = 0; m_nMaxPut = 0; m_Error = 0; m_Memory.Purge(); } inline void CUtlBuffer::CopyBuffer( const CUtlBuffer &buffer ) { CopyBuffer( buffer.Base(), buffer.TellPut() ); } inline void CUtlBuffer::CopyBuffer( const void *pubData, int cubData ) { Clear(); if ( cubData ) { Put( pubData, cubData ); } } #endif // UTLBUFFER_H